diff --git a/.bazelversion b/.bazelversion new file mode 100644 index 0000000..2bf50aa --- /dev/null +++ b/.bazelversion @@ -0,0 +1 @@ +8.3.0 diff --git a/.github/ISSUE_TEMPLATE/bug_fix.md b/.github/ISSUE_TEMPLATE/bug_fix.md new file mode 100644 index 0000000..c9c4f35 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_fix.md @@ -0,0 +1,11 @@ +--- +name: Bugfix +about: 'Issue to track a bugfix' +title: 'Bugfix: Your bugfix title' +labels: 'codeowner_review' +assignees: '' + +--- + +> [!IMPORTANT] +> Make sure to link this issue with the PR for your bugfix. diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..fe251a3 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,24 @@ +--- +name: Bug report +about: Create a report for a bug +title: 'Bug: Your bug title' +labels: 'bug' +assignees: '' + +--- + +### Describe the bug: + + +### Steps to reproduce the behavior: +1. +2. + +### Observed behavior: + +### Expected behavior: + +### Occurrence: + + +### Attachments / Logs: diff --git a/.github/ISSUE_TEMPLATE/improvement.md b/.github/ISSUE_TEMPLATE/improvement.md new file mode 100644 index 0000000..fd2c171 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/improvement.md @@ -0,0 +1,11 @@ +--- +name: Improvement +about: 'Issue to track a improvement' +title: 'Improvement: Your improvement title' +labels: 'codeowner_review' +assignees: '' + +--- + +> [!IMPORTANT] +> Make sure to link this issue with the PR for your improvement. diff --git a/.github/PULL_REQUEST_TEMPLATE/bug_fix.md b/.github/PULL_REQUEST_TEMPLATE/bug_fix.md new file mode 100644 index 0000000..8341f51 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/bug_fix.md @@ -0,0 +1,19 @@ +# Bugfix + +> [!IMPORTANT] +> Use this template only for bugfixes that do not influence topics covered by contribution requests or improvements. + +> [!CAUTION] +> Make sure to submit your pull-request as **Draft** until you are ready to have it reviewed by the Committers. + +## Description + +[A short description of the bug being fixed by the contribution.] + +## Related ticket + +> [!IMPORTANT] +> Please replace `[ISSUE-NUMBER]` with the issue-number that tracks this bug fix. If there is no such +> ticket yet, create one via [this issue template](../ISSUE_TEMPLATE/new?template=bug_fix.md). + +closes [ISSUE-NUMBER] (bugfix ticket) diff --git a/.github/PULL_REQUEST_TEMPLATE/improvement.md b/.github/PULL_REQUEST_TEMPLATE/improvement.md new file mode 100644 index 0000000..090ad43 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/improvement.md @@ -0,0 +1,19 @@ +# Improvement + +> [!IMPORTANT] +> Use this template only for improvement that do not influence topics covered by contribution requests or bug fixes. + +> [!CAUTION] +> Make sure to submit your pull-request as **Draft** until you are ready to have it reviewed by the Committers. + +## Description + +[A short description of the improvement being addressed by the contribution.] + +## Related ticket + +> [!IMPORTANT] +> Please replace `[ISSUE-NUMBER]` with the issue-number that tracks this bug fix. If there is no such +> ticket yet, create one via [this issue template](../ISSUE_TEMPLATE/new?template=improvement.md). + +closes [ISSUE-NUMBER] (improvement ticket) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..17a5117 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,33 @@ + + + +## Notes for Reviewer + + +## Pre-Review Checklist for the PR Author + +* [ ] PR title is short, expressive and meaningful +* [ ] Commits are properly organized +* [ ] Relevant issues are linked in the [References](#references) section +* [ ] Tests are conducted +* [ ] Unit tests are added + +## Checklist for the PR Reviewer + +* [ ] Commits are properly organized and messages follow [S-CORE commit guidelines](https://eclipse-score.github.io/score/main/contribute/contribution_request/index.html) +* [ ] Unit tests have been written for new behavior +* [ ] Public API is documented +* [ ] PR title describes the changes + +## Post-review Checklist for the PR Author + +* [ ] All open points are addressed and tracked via issues + +## References + + + +Closes # + + + diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..0dba4ff --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,57 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +name: Tests + +on: + pull_request: + push: + branches: + - main + +permissions: + contents: read + +jobs: + test-sanitizers: + name: Test ${{ matrix.config }} + runs-on: ubuntu-24.04 + + strategy: + fail-fast: false + matrix: + config: + - asan_ubsan_lsan + - tsan + + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Setup Bazel + uses: bazel-contrib/setup-bazel@0.18.0 + with: + bazelisk-cache: true + cache-save: ${{ github.event_name == 'push' }} + + - name: Test with ${{ matrix.config }} + working-directory: tests + run: bazel test --config=${{ matrix.config }} //... --verbose_failures + + - name: Upload test logs on failure + if: failure() + uses: actions/upload-artifact@v7 + with: + name: testlogs-${{ matrix.config }}-${{ github.run_id }} + path: tests/bazel-testlogs/**/test.log + if-no-files-found: ignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1eeaf4d --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +# Bazel build outputs +bazel-* +.bazel-* + +# IDE files +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# OS files +.DS_Store +Thumbs.db +*.lock diff --git a/BUILD.bazel b/BUILD.bazel new file mode 100644 index 0000000..27b9458 --- /dev/null +++ b/BUILD.bazel @@ -0,0 +1,20 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +exports_files( + [ + "LICENSE.md", + "NOTICE", + ], + visibility = ["//visibility:public"], +) diff --git a/CONTRIBUTION.md b/CONTRIBUTION.md new file mode 100644 index 0000000..40924f6 --- /dev/null +++ b/CONTRIBUTION.md @@ -0,0 +1,15 @@ +# score_cpp_policies Contribution Guide + +The [Eclipse Safe Open Vehicle Core (S-CORE)](https://projects.eclipse.org/projects/automotive.score) project develops an open-source core stack for Software Defined Vehicles (SDVs). This repository centralizes the shared C++ quality tool policies (sanitizers, clang-tidy, clang-format) that S-CORE modules reuse to maintain consistent, safety-focused defaults. + +Project communication happens via the [score-dev mailing list](https://accounts.eclipse.org/mailing-list/score-dev), GitHub issues and pull requests, and Slack. + +Please note that the [Eclipse Foundation's Terms of Use](https://www.eclipse.org/legal/terms-of-use/) apply. Contributors must sign both the [ECA](https://www.eclipse.org/legal/ECA.php) and the [DCO](https://www.eclipse.org/legal/dco/). + +## Contributing changes + +1. Open an issue describing the policy change you propose (e.g., enabling/disabling a sanitizer option or clang-tidy rule) and the rationale, including links to any affected projects. +2. Submit a PR referencing the issue. Keep changes minimal and well-documented, and include examples that justify the chosen defaults when possible. +3. Request reviews from the S-CORE committers. Follow the commit message rules in the [Eclipse Foundation Project Handbook](https://www.eclipse.org/projects/handbook/#resources-commit). + +If you are new to the project, see the S-CORE process descriptions and templates at [https://eclipse-score.github.io/score/process_description/](https://eclipse-score.github.io/score/process_description/). diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/MODULE.bazel b/MODULE.bazel new file mode 100644 index 0000000..af8b1fa --- /dev/null +++ b/MODULE.bazel @@ -0,0 +1,21 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +module( + name = "score_cpp_policies", + version = "0.0.0", +) + +bazel_dep(name = "bazel_skylib", version = "1.8.2") +bazel_dep(name = "platforms", version = "0.0.10") + diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000..e75f6ff --- /dev/null +++ b/NOTICE @@ -0,0 +1,23 @@ +# Notices for Eclipse S-CORE + +This content is produced and maintained by the Eclipse S-CORE project. + +* Project home: https://projects.eclipse.org/projects/automotive.score + +## Trademarks + +Eclipse S-CORE is a trademark of the Eclipse Foundation. + +## Copyright + +All content is the property of the respective authors or their employers. +For more information regarding authorship of content, please consult the +listed source code repository logs. + +## Declared Project Licenses + +This program and the accompanying materials are made available under the +terms of the Apache License Version 2.0 which is available at +https://www.apache.org/licenses/LICENSE-2.0 + +SPDX-License-Identifier: Apache-2.0 diff --git a/README.md b/README.md index 65d58ab..42bb4d3 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,145 @@ # score_cpp_policies -Centralized C++ quality tool policies for S-CORE, including sanitizer configurations and safety-critical guidelines. + +Centralized C++ quality tool policies for Eclipse S-CORE, providing sanitizer configurations reusable across all S-CORE modules (logging, communication, baselibs, etc.). + +Planned: clang-tidy, clang-format, code coverage policies. + +## What This Provides + +- **Sanitizer Bazel feature flags** — ASan, UBSan, LSan, TSan as Bazel build features +- **`//sanitizers:wrapper`** — shell script that sets all sanitizer runtime options centrally +- **`sanitizers/sanitizers.bazelrc`** — canonical config that consumers import or copy +- **Suppression files** — per-sanitizer suppression lists for known false positives (GoogleTest, etc.) +- **Constraint system** — `target_compatible_with` settings for sanitizer-incompatible targets + +## Available Sanitizer Configurations + +| Config | Sanitizers | Notes | +|--------|-----------|-------| +| `--config=asan_ubsan_lsan` | ASan + UBSan + LSan | **Recommended** — catches memory errors, UB, and leaks | +| `--config=asan` | AddressSanitizer | Alias for `asan_ubsan_lsan` | +| `--config=ubsan` | UndefinedBehaviorSanitizer | Alias for `asan_ubsan_lsan` | +| `--config=lsan` | LeakSanitizer | Alias for `asan_ubsan_lsan` | +| `--config=tsan` | ThreadSanitizer | Cannot be combined with ASan | + +## Usage + +### Add Dependency + +```python +bazel_dep(name = "score_cpp_policies", version = "0.0.0") +``` + +### Configure Sanitizers + +Copy the sanitizer configs from `sanitizers/sanitizers.bazelrc` into your `.bazelrc` and adapt the paths: + +```bazelrc +# ASan + UBSan + LSan (Combined) +build:asan_ubsan_lsan --features=asan +build:asan_ubsan_lsan --features=ubsan +build:asan_ubsan_lsan --features=lsan +build:asan_ubsan_lsan --platform_suffix=asan_ubsan_lsan +test:asan_ubsan_lsan --config=with_debug_symbols +test:asan_ubsan_lsan --test_tag_filters=-no-asan,-no-lsan,-no-ubsan +test:asan_ubsan_lsan --@score_cpp_policies//sanitizers/flags:sanitizer=asan_ubsan_lsan +test:asan_ubsan_lsan --run_under=@score_cpp_policies//sanitizers:wrapper + +# Shortcuts +build:asan --config=asan_ubsan_lsan +test:asan --test_tag_filters=-no-asan +build:ubsan --config=asan_ubsan_lsan +test:ubsan --test_tag_filters=-no-ubsan +build:lsan --config=asan_ubsan_lsan +test:lsan --test_tag_filters=-no-lsan + +# ThreadSanitizer +build:tsan --features=tsan +build:tsan --platform_suffix=tsan +test:tsan --config=with_debug_symbols +test:tsan --cxxopt=-O1 +test:tsan --test_tag_filters=-no-tsan +test:tsan --@score_cpp_policies//sanitizers/flags:sanitizer=tsan +test:tsan --run_under=@score_cpp_policies//sanitizers:wrapper +``` + +> **Note**: The `--run_under=@score_cpp_policies//sanitizers:wrapper` automatically loads runtime options and suppressions from the module. + +### Run Tests + +```bash +# ASan + UBSan + LSan (recommended) +bazel test --config=asan_ubsan_lsan //... + +# ThreadSanitizer (separate run — cannot combine with ASan) +bazel test --config=tsan //... +``` + +## Tagging Tests for Sanitizer Compatibility + +```python +cc_test( + name = "my_test", + srcs = ["my_test.cpp"], + tags = ["no-tsan"], # skip when running --config=tsan + deps = ["@googletest//:gtest_main"], +) +``` + +| Tag | Skipped when using | +|-----|--------------------| +| `no-tsan` | `--config=tsan` | +| `no-asan` | `--config=asan` or `asan_ubsan_lsan` | +| `no-lsan` | `--config=lsan` or `asan_ubsan_lsan` | +| `no-ubsan` | `--config=ubsan` or `asan_ubsan_lsan` | + +## Suppression Files + +Default suppressions for common third-party libraries are included: + +| File | Sanitizer | Current Suppressions | +|------|-----------|---------------------| +| `sanitizers/suppressions/asan.supp` | ASan | *(empty)* | +| `sanitizers/suppressions/lsan.supp` | LSan | GoogleTest static initialization leaks | +| `sanitizers/suppressions/tsan.supp` | TSan | stdlib false positives, Rust test suppressions | +| `sanitizers/suppressions/ubsan.supp` | UBSan | *(empty)* | + +**Adding project-specific suppressions:** Currently, the wrapper loads suppressions from this module only. For project-specific suppressions, you'll need to create a custom wrapper or extend the environment variables in your `.bazelrc`. This is a known limitation being tracked for future improvements. + +> **Runtime Options**: See [`sanitizers/templates/`](sanitizers/templates/) for detailed documentation of all sanitizer options configured by the wrapper. + +## Constraint System + +Use constraints to mark targets as incompatible with specific sanitizers: + +```python +cc_library( + name = "legacy_lib", + target_compatible_with = [ + "@score_cpp_policies//sanitizers/constraints:no_tsan", + ], +) +``` + +| Constraint | Effect | +|-----------|--------| +| `@score_cpp_policies//sanitizers/constraints:no_tsan` | Skip when `--config=tsan` | +| `@score_cpp_policies//sanitizers/constraints:no_asan_ubsan_lsan` | Skip when `--config=asan_ubsan_lsan` | +| `@score_cpp_policies//sanitizers/constraints:any_sanitizer` | Only builds with a sanitizer enabled | + +## Testing This Repository + +```bash +cd tests + +bazel test --config=asan_ubsan_lsan //... +bazel test --config=tsan //... +``` + +## Contributing + +See [CONTRIBUTION.md](CONTRIBUTION.md) for guidelines. All commits must follow [Eclipse Foundation commit rules](https://www.eclipse.org/projects/handbook/#resources-commit). Contributors must sign the ECA and DCO. + +## License + +Apache License 2.0 — see [LICENSE](LICENSE) for details. diff --git a/sanitizers/BUILD.bazel b/sanitizers/BUILD.bazel new file mode 100644 index 0000000..b0bfb19 --- /dev/null +++ b/sanitizers/BUILD.bazel @@ -0,0 +1,73 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +load("//sanitizers/private:expand_template.bzl", "expand_template") + +exports_files( + ["sanitizers.bazelrc"], + visibility = ["//visibility:public"], +) + +filegroup( + name = "env_template", + srcs = select({ + "//sanitizers/flags:tsan": ["templates/tsan.env.template"], + "//sanitizers/flags:asan_ubsan_lsan": ["templates/asan_ubsan_lsan.env.template"], + }), + target_compatible_with = ["//sanitizers/constraints:any_sanitizer"], +) + +[ + expand_template( + name = name + "_env", + out = name + "_sanitizer.env", + substitutions = {"%ROOT%": root}, + target_compatible_with = ["//sanitizers/constraints:any_sanitizer"], + template = ":env_template", + visibility = ["//visibility:public"], + ) + for name, root in [ + ("absolute", "/"), + ("relative", "./"), + ] +] + +filegroup( + name = "suppressions", + srcs = select({ + "//sanitizers/flags:tsan": ["suppressions/tsan.supp"], + "//sanitizers/flags:asan_ubsan_lsan": [ + "suppressions/asan.supp", + "suppressions/lsan.supp", + "suppressions/ubsan.supp", + ], + "//conditions:default": [ + "suppressions/asan.supp", + "suppressions/lsan.supp", + "suppressions/tsan.supp", + "suppressions/ubsan.supp", + ], + }), + visibility = ["//visibility:public"], +) + +sh_binary( + name = "wrapper", + srcs = ["wrapper.sh"], + data = [ + ":relative_env", + ":suppressions", + ], + target_compatible_with = ["//sanitizers/constraints:any_sanitizer"], + visibility = ["//visibility:public"], +) diff --git a/sanitizers/constraints/BUILD.bazel b/sanitizers/constraints/BUILD.bazel new file mode 100644 index 0000000..0f123ae --- /dev/null +++ b/sanitizers/constraints/BUILD.bazel @@ -0,0 +1,49 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +constraint_setting( + name = "sanitizer_compat_setting", + default_constraint_value = ":always_true", +) + +constraint_value( + name = "always_true", + constraint_setting = ":sanitizer_compat_setting", +) + +alias( + name = "any_sanitizer", + actual = select({ + "//sanitizers/flags:any_sanitizer": ":always_true", + "//conditions:default": "@platforms//:incompatible", + }), + visibility = ["//visibility:public"], +) + +alias( + name = "no_asan_ubsan_lsan", + actual = select({ + "//sanitizers/flags:asan_ubsan_lsan": "@platforms//:incompatible", + "//conditions:default": ":always_true", + }), + visibility = ["//visibility:public"], +) + +alias( + name = "no_tsan", + actual = select({ + "//sanitizers/flags:tsan": "@platforms//:incompatible", + "//conditions:default": ":always_true", + }), + visibility = ["//visibility:public"], +) diff --git a/sanitizers/flags/BUILD.bazel b/sanitizers/flags/BUILD.bazel new file mode 100644 index 0000000..fef3ce3 --- /dev/null +++ b/sanitizers/flags/BUILD.bazel @@ -0,0 +1,53 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +load("@bazel_skylib//lib:selects.bzl", "selects") +load("@bazel_skylib//rules:common_settings.bzl", "string_flag") + +string_flag( + name = "sanitizer", + build_setting_default = "none", + values = [ + "none", + "asan_ubsan_lsan", + "tsan", + ], + visibility = ["//visibility:public"], +) + +config_setting( + name = "none", + flag_values = {":sanitizer": "none"}, + visibility = ["//visibility:public"], +) + +config_setting( + name = "asan_ubsan_lsan", + flag_values = {":sanitizer": "asan_ubsan_lsan"}, + visibility = ["//visibility:public"], +) + +config_setting( + name = "tsan", + flag_values = {":sanitizer": "tsan"}, + visibility = ["//visibility:public"], +) + +selects.config_setting_group( + name = "any_sanitizer", + match_any = [ + ":asan_ubsan_lsan", + ":tsan", + ], + visibility = ["//visibility:public"], +) diff --git a/sanitizers/private/BUILD.bazel b/sanitizers/private/BUILD.bazel new file mode 100644 index 0000000..ad28815 --- /dev/null +++ b/sanitizers/private/BUILD.bazel @@ -0,0 +1,17 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +exports_files( + ["expand_template.bzl"], + visibility = ["//sanitizers:__pkg__"], +) diff --git a/sanitizers/private/expand_template.bzl b/sanitizers/private/expand_template.bzl new file mode 100644 index 0000000..cdc57eb --- /dev/null +++ b/sanitizers/private/expand_template.bzl @@ -0,0 +1,30 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +"""Wrapper rule around the expand_template action.""" + +def _expand_template_impl(ctx): + ctx.actions.expand_template( + template = ctx.file.template, + output = ctx.outputs.out, + substitutions = ctx.attr.substitutions, + ) + +expand_template = rule( + implementation = _expand_template_impl, + attrs = { + "out": attr.output(mandatory = True), + "substitutions": attr.string_dict(default = {}), + "template": attr.label(allow_single_file = True, mandatory = True), + }, +) diff --git a/sanitizers/sanitizers.bazelrc b/sanitizers/sanitizers.bazelrc new file mode 100644 index 0000000..73328b6 --- /dev/null +++ b/sanitizers/sanitizers.bazelrc @@ -0,0 +1,60 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +# ============================================================================== +# Centralized Sanitizer Configurations for S-CORE C++ Modules +# ============================================================================== +# +# Available configurations: +# --config=asan_ubsan_lsan : AddressSanitizer + UndefinedBehaviorSanitizer + LeakSanitizer (Combined) +# --config=asan : AddressSanitizer only +# --config=lsan : LeakSanitizer only +# --config=tsan : ThreadSanitizer (cannot be combined with ASan) +# --config=ubsan : UndefinedBehaviorSanitizer only +# ============================================================================== + +# -g1: Minimal debug info (function names + line numbers) for sanitizer stack traces +# GCC and Clang compatible. Note: Clang's -gline-tables-only provides column info but is not GCC-compatible. +test:with_debug_symbols --cxxopt=-g1 +test:with_debug_symbols --strip=never + +# AddressSanitizer + UndefinedBehaviorSanitizer + LeakSanitizer (Combined) +build:asan_ubsan_lsan --features=asan +build:asan_ubsan_lsan --features=ubsan +build:asan_ubsan_lsan --features=lsan +build:asan_ubsan_lsan --platform_suffix=asan_ubsan_lsan +test:asan_ubsan_lsan --config=with_debug_symbols +test:asan_ubsan_lsan --test_tag_filters=-no-asan,-no-lsan,-no-ubsan +test:asan_ubsan_lsan --@score_cpp_policies//sanitizers/flags:sanitizer=asan_ubsan_lsan +test:asan_ubsan_lsan --run_under=@score_cpp_policies//sanitizers:wrapper + +# AddressSanitizer only +build:asan --config=asan_ubsan_lsan +build:asan --test_tag_filters=-no-asan + +# UndefinedBehaviorSanitizer only +build:ubsan --config=asan_ubsan_lsan +build:ubsan --test_tag_filters=-no-ubsan + +# LeakSanitizer only +build:lsan --config=asan_ubsan_lsan +build:lsan --test_tag_filters=-no-lsan + +# ThreadSanitizer (cannot be combined with ASan/LSan) +build:tsan --features=tsan +build:tsan --platform_suffix=tsan +test:tsan --config=with_debug_symbols +test:tsan --cxxopt=-O1 +test:tsan --test_tag_filters=-no-tsan +test:tsan --@score_cpp_policies//sanitizers/flags:sanitizer=tsan +test:tsan --run_under=@score_cpp_policies//sanitizers:wrapper diff --git a/sanitizers/suppressions/asan.supp b/sanitizers/suppressions/asan.supp new file mode 100644 index 0000000..e9257de --- /dev/null +++ b/sanitizers/suppressions/asan.supp @@ -0,0 +1,17 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +# Suppressions for the AddressSanitizer +# See: https://clang.llvm.org/docs/AddressSanitizer.html#issue-suppression +# Every suppression requires a justification. +# Suppressions that share the same justification may be organized in a single block. diff --git a/sanitizers/suppressions/lsan.supp b/sanitizers/suppressions/lsan.supp new file mode 100644 index 0000000..043286e --- /dev/null +++ b/sanitizers/suppressions/lsan.supp @@ -0,0 +1,25 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +# Suppressions for the LeakSanitizer +# See: https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer#suppressions +# Every suppression requires a justification. +# Suppressions that share the same justification may be organized in a single block. + + +# GoogleTest uses global singletons and static state that are intentionally +# never freed. These are by design and not real leaks. +leak:testing::internal::RegisterTest +leak:testing::UnitTest::GetInstance +leak:testing::internal::UnitTestImpl + diff --git a/sanitizers/suppressions/tsan.supp b/sanitizers/suppressions/tsan.supp new file mode 100644 index 0000000..c1796b6 --- /dev/null +++ b/sanitizers/suppressions/tsan.supp @@ -0,0 +1,29 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +# Suppressions for the ThreadSanitizer +# See: https://github.com/google/sanitizers/wiki/ThreadSanitizerSuppressions +# Every suppression requires a justification. +# Suppressions that share the same justification may be organized in a single block. + + +# Standard library false positives (caused by a stdlib built without tsan instrumentation) +# We accept this because building the stdlib with instrumentation is currently out of scope. +race:include/c++/v1/ios + +# Rust standard test runner false positives (affects all repos using Rust tests under TSan) +# These are benign races in the Rust test infrastructure's result collection mechanism. +# The race in Channel occurs during parallel test execution result aggregation. +# The race in test::run_test is due to the test runner's pthread_create not being visible to TSan. +race:> +race:test::run_test diff --git a/sanitizers/suppressions/ubsan.supp b/sanitizers/suppressions/ubsan.supp new file mode 100644 index 0000000..a71ef2a --- /dev/null +++ b/sanitizers/suppressions/ubsan.supp @@ -0,0 +1,2 @@ +# Suppressions for the UndefinedBehaviorSanitizer +# See: https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html#runtime-suppressions diff --git a/sanitizers/templates/asan_ubsan_lsan.env.template b/sanitizers/templates/asan_ubsan_lsan.env.template new file mode 100644 index 0000000..3091a11 --- /dev/null +++ b/sanitizers/templates/asan_ubsan_lsan.env.template @@ -0,0 +1,3 @@ +ASAN_OPTIONS=exitcode=55 allow_addr2line=1 verbosity=1 check_initialization_order=1 detect_stack_use_after_return=1 print_stats=1 halt_on_error=1 allocator_may_return_null=1 detect_leaks=1 suppressions=%ROOT%sanitizers/suppressions/asan.supp +UBSAN_OPTIONS=exitcode=55 allow_addr2line=1 verbosity=1 print_stacktrace=1 halt_on_error=1 suppressions=%ROOT%sanitizers/suppressions/ubsan.supp +LSAN_OPTIONS=exitcode=55 suppressions=%ROOT%sanitizers/suppressions/lsan.supp diff --git a/sanitizers/templates/tsan.env.template b/sanitizers/templates/tsan.env.template new file mode 100644 index 0000000..338b420 --- /dev/null +++ b/sanitizers/templates/tsan.env.template @@ -0,0 +1 @@ +TSAN_OPTIONS=exitcode=55 allow_addr2line=1 verbosity=1 detect_deadlocks=1 second_deadlock_stack=1 halt_on_error=1 suppressions=%ROOT%sanitizers/suppressions/tsan.supp diff --git a/sanitizers/wrapper.sh b/sanitizers/wrapper.sh new file mode 100755 index 0000000..19d8fa1 --- /dev/null +++ b/sanitizers/wrapper.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +WRAPPER_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +IFS=' +' +# shellcheck disable=SC2046 +export $(sed "s|\./sanitizers/|$WRAPPER_DIR/|g" "$WRAPPER_DIR/relative_sanitizer.env" | grep -v '^#' | grep -v '^$') +exec "$@" diff --git a/tests/.bazelrc b/tests/.bazelrc new file mode 100644 index 0000000..b89ed3f --- /dev/null +++ b/tests/.bazelrc @@ -0,0 +1,19 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +# Import centralized sanitizer configurations +# (includes --test_tag_filters for all configs) +import %workspace%/../sanitizers/sanitizers.bazelrc + +common --registry=https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/ +common --registry=https://bcr.bazel.build diff --git a/tests/.bazelversion b/tests/.bazelversion new file mode 100644 index 0000000..2bf50aa --- /dev/null +++ b/tests/.bazelversion @@ -0,0 +1 @@ +8.3.0 diff --git a/tests/BUILD.bazel b/tests/BUILD.bazel new file mode 100644 index 0000000..3b96f4f --- /dev/null +++ b/tests/BUILD.bazel @@ -0,0 +1,105 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_test") + +# ============================================================================== +# Positive tests - verify clean code passes with all sanitizers +# ============================================================================== + +cc_test( + name = "sample_test", + srcs = ["sample_test.cpp"], + tags = ["no-tsan"], # TSAN has known issues with googletest + deps = [ + "@googletest//:gtest", + "@googletest//:gtest_main", + ], +) + +# ============================================================================== +# Negative test binaries - intentionally trigger sanitizer violations +# ============================================================================== + +cc_binary( + name = "asan_fail_test", + srcs = ["negative/asan_fail.cpp"], + testonly = True, +) + +cc_binary( + name = "lsan_fail_test", + srcs = ["negative/lsan_fail.cpp"], + testonly = True, +) + +cc_binary( + name = "tsan_fail_test", + srcs = ["negative/tsan_fail.cpp"], + testonly = True, +) + +cc_binary( + name = "ubsan_fail_test", + srcs = ["negative/ubsan_fail.cpp"], + testonly = True, +) + +# ============================================================================== +# Shell tests - verify sanitizers catch violations (exit code 55) +# ============================================================================== + +sh_test( + name = "asan_fail", + srcs = ["negative/verify_sanitizer_failure.sh"], + args = [ + "$(location :asan_fail_test)", + "55", + ], + data = [":asan_fail_test"], + tags = ["no-tsan"], +) + +sh_test( + name = "lsan_fail", + srcs = ["negative/verify_sanitizer_failure.sh"], + args = [ + "$(location :lsan_fail_test)", + "55", + ], + data = [":lsan_fail_test"], + tags = ["no-tsan"], +) + +sh_test( + name = "tsan_fail", + srcs = ["negative/verify_sanitizer_failure.sh"], + args = [ + "$(location :tsan_fail_test)", + "55", + ], + data = [":tsan_fail_test"], + tags = ["no-asan", "no-lsan", "no-ubsan"], +) + +sh_test( + name = "ubsan_fail", + srcs = ["negative/verify_sanitizer_failure.sh"], + args = [ + "$(location :ubsan_fail_test)", + "55", + ], + data = [":ubsan_fail_test"], + tags = ["no-tsan"], +) + diff --git a/tests/MODULE.bazel b/tests/MODULE.bazel new file mode 100644 index 0000000..3b1106d --- /dev/null +++ b/tests/MODULE.bazel @@ -0,0 +1,26 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +module( + name = "score_cpp_policies_tests", + version = "0.0.0", +) + +bazel_dep(name = "googletest", version = "1.17.0.bcr.2") +bazel_dep(name = "rules_cc", version = "0.2.16") + +bazel_dep(name = "score_cpp_policies", version = "") +local_path_override( + module_name = "score_cpp_policies", + path = "..", +) diff --git a/tests/negative/asan_fail.cpp b/tests/negative/asan_fail.cpp new file mode 100644 index 0000000..6268d66 --- /dev/null +++ b/tests/negative/asan_fail.cpp @@ -0,0 +1,22 @@ +// ******************************************************************************* +// Copyright (c) 2026 Contributors to the Eclipse Foundation +// +// See the NOTICE file(s) distributed with this work for additional +// information regarding copyright ownership. +// +// This program and the accompanying materials are made available under the +// terms of the Apache License Version 2.0 which is available at +// https://www.apache.org/licenses/LICENSE-2.0 +// +// SPDX-License-Identifier: Apache-2.0 +// ******************************************************************************* + +#include + +int main() { + int* array = new int[10]; + // Intentional out-of-bounds access + int value = array[10]; // ASan should detect this + delete[] array; + return value; +} diff --git a/tests/negative/lsan_fail.cpp b/tests/negative/lsan_fail.cpp new file mode 100644 index 0000000..783a261 --- /dev/null +++ b/tests/negative/lsan_fail.cpp @@ -0,0 +1,22 @@ +// ******************************************************************************* +// Copyright (c) 2026 Contributors to the Eclipse Foundation +// +// See the NOTICE file(s) distributed with this work for additional +// information regarding copyright ownership. +// +// This program and the accompanying materials are made available under the +// terms of the Apache License Version 2.0 which is available at +// https://www.apache.org/licenses/LICENSE-2.0 +// +// SPDX-License-Identifier: Apache-2.0 +// ******************************************************************************* + +#include + +int main() { + // Intentional leak - never freed + int* leak = new int[100]; + *leak = 42; + // No delete[] - LSan should detect this + return 0; +} diff --git a/tests/negative/tsan_fail.cpp b/tests/negative/tsan_fail.cpp new file mode 100644 index 0000000..70bb80f --- /dev/null +++ b/tests/negative/tsan_fail.cpp @@ -0,0 +1,31 @@ +// ******************************************************************************* +// Copyright (c) 2026 Contributors to the Eclipse Foundation +// +// See the NOTICE file(s) distributed with this work for additional +// information regarding copyright ownership. +// +// This program and the accompanying materials are made available under the +// terms of the Apache License Version 2.0 which is available at +// https://www.apache.org/licenses/LICENSE-2.0 +// +// SPDX-License-Identifier: Apache-2.0 +// ******************************************************************************* + +#include + +int global_counter = 0; + +void increment() { + for (int i = 0; i < 10000; ++i) { + // Intentional unsynchronized access - TSan should detect race + global_counter++; + } +} + +int main() { + std::thread t1(increment); + std::thread t2(increment); + t1.join(); + t2.join(); + return 0; +} diff --git a/tests/negative/ubsan_fail.cpp b/tests/negative/ubsan_fail.cpp new file mode 100644 index 0000000..02cf19d --- /dev/null +++ b/tests/negative/ubsan_fail.cpp @@ -0,0 +1,21 @@ +// ******************************************************************************* +// Copyright (c) 2026 Contributors to the Eclipse Foundation +// +// See the NOTICE file(s) distributed with this work for additional +// information regarding copyright ownership. +// +// This program and the accompanying materials are made available under the +// terms of the Apache License Version 2.0 which is available at +// https://www.apache.org/licenses/LICENSE-2.0 +// +// SPDX-License-Identifier: Apache-2.0 +// ******************************************************************************* + +#include + +int main() { + int max = std::numeric_limits::max(); + // Intentional overflow - UBSan should detect this + int overflow = max + 1; + return overflow; +} diff --git a/tests/negative/verify_sanitizer_failure.sh b/tests/negative/verify_sanitizer_failure.sh new file mode 100755 index 0000000..9eb6227 --- /dev/null +++ b/tests/negative/verify_sanitizer_failure.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash + +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +set -euo pipefail + +BINARY="$1" +EXPECTED_EXIT_CODE="${2:-55}" + +echo "Running: $BINARY" +echo "Expected exit code: $EXPECTED_EXIT_CODE" + +# Run the binary and capture exit code +set +e +"$BINARY" +ACTUAL_EXIT_CODE=$? +set -e + +echo "Actual exit code: $ACTUAL_EXIT_CODE" + +# Verify the binary failed with the expected exit code +if [ "$ACTUAL_EXIT_CODE" -eq "$EXPECTED_EXIT_CODE" ]; then + echo "✓ PASS: Binary failed with exit code $EXPECTED_EXIT_CODE (sanitizer detected violation)" + exit 0 +else + echo "✗ FAIL: Binary exited with code $ACTUAL_EXIT_CODE, expected $EXPECTED_EXIT_CODE" + echo "This means the sanitizer did NOT catch the expected violation!" + exit 1 +fi diff --git a/tests/sample_test.cpp b/tests/sample_test.cpp new file mode 100644 index 0000000..85e93e9 --- /dev/null +++ b/tests/sample_test.cpp @@ -0,0 +1,63 @@ +// ******************************************************************************* +// Copyright (c) 2026 Contributors to the Eclipse Foundation +// +// See the NOTICE file(s) distributed with this work for additional +// information regarding copyright ownership. +// +// This program and the accompanying materials are made available under the +// terms of the Apache License Version 2.0 which is available at +// https://www.apache.org/licenses/LICENSE-2.0 +// +// SPDX-License-Identifier: Apache-2.0 +// ******************************************************************************* + +#include +#include +#include +#include +#include + +// Simple test that should pass with all sanitizers +TEST(SampleTest, BasicFunctionality) { + std::vector vec = {1, 2, 3, 4, 5}; + EXPECT_EQ(vec.size(), 5); + EXPECT_EQ(vec[0], 1); + EXPECT_EQ(vec[4], 5); +} + +// Memory allocation test that should pass with all sanitizers +TEST(SampleTest, MemoryAllocation) { + auto ptr = std::make_unique(42); + EXPECT_EQ(*ptr, 42); +} + +// Test with multiple threads using proper synchronization (atomics) +// Validates that thread-safe code passes ASan/UBSan/LSan cleanly +TEST(SampleTest, MultiThreaded) { + std::atomic counter{0}; + + auto increment = [&counter]() { + for (int i = 0; i < 1000; ++i) { + counter.fetch_add(1, std::memory_order_relaxed); + } + }; + + std::vector threads; + for (int i = 0; i < 4; ++i) { + threads.emplace_back(increment); + } + + for (auto& t : threads) { + t.join(); + } + + EXPECT_EQ(counter.load(), 4000); +} + +// Basic arithmetic test that should pass with all sanitizers +TEST(SampleTest, NoUndefinedBehavior) { + int x = 5; + int y = 2; + EXPECT_EQ(x / y, 2); + EXPECT_EQ(x % y, 1); +}