From dd9e8f303622f74abecf4b4a3f7197bdf2bd2c9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Svensson?= Date: Fri, 10 Nov 2023 12:13:41 +0100 Subject: [PATCH] Add sanitizers to GitHub Actions CI Run all testcases with ASan, UBSan and TSan during Linux CI except some special testcases for ExitedWithCode and AllowLeak. Introduces the following defines to indicate when built with a sanitizer, which can be used to disable sanitizers on testcase level: - GTEST_HAS_ADDRESS_SANITIZER - GTEST_HAS_UNDEFINED_BEHAVIOR_SANITIZER - GTEST_HAS_THREAD_SANITIZER and the following bazel test tags to disable on test binary level: no_asan, no_ubsan, no_tsan Co-authored-by: tbonza --- .bazelrc | 29 +++++++++++++++++++ .github/workflows/gtest-ci.yml | 14 +++++++++ BUILD.bazel | 4 +++ googlemock/test/gmock-spec-builders_test.cc | 2 ++ googletest/test/googletest-death-test-test.cc | 3 ++ 5 files changed, 52 insertions(+) create mode 100644 .bazelrc diff --git a/.bazelrc b/.bazelrc new file mode 100644 index 00000000..2335a12e --- /dev/null +++ b/.bazelrc @@ -0,0 +1,29 @@ +build:asan --strip=never +build:asan --copt -fsanitize=address +build:asan --copt -DGTEST_HAS_ADDRESS_SANITIZER +build:asan --copt -O2 +build:asan --copt -g +build:asan --copt -fno-omit-frame-pointer +build:asan --copt -fno-sanitize-recover=all +build:asan --linkopt -fsanitize=address +build:asan --test_tag_filters=-no_asan + +build:ubsan --strip=never +build:ubsan --copt -fsanitize=undefined +build:ubsan --copt -DGTEST_HAS_UNDEFINED_BEHAVIOR_SANITIZER +build:ubsan --copt -O2 +build:ubsan --copt -g +build:ubsan --copt -fno-omit-frame-pointer +build:ubsan --copt -fno-sanitize-recover=all +build:ubsan --linkopt -fsanitize=undefined +build:ubsan --test_tag_filters=-no_ubsan + +build:tsan --strip=never +build:tsan --copt -fsanitize=thread +build:tsan --copt -DGTEST_HAS_THREAD_SANITIZER +build:tsan --copt -O2 +build:tsan --copt -g +build:tsan --copt -fno-omit-frame-pointer +build:tsan --copt -fno-sanitize-recover=all +build:tsan --linkopt -fsanitize=thread +build:tsan --test_tag_filters=-no_tsan \ No newline at end of file diff --git a/.github/workflows/gtest-ci.yml b/.github/workflows/gtest-ci.yml index 03a8cc5e..686373cb 100644 --- a/.github/workflows/gtest-ci.yml +++ b/.github/workflows/gtest-ci.yml @@ -19,6 +19,20 @@ jobs: - name: Tests run: bazel test --cxxopt=-std=c++14 --features=external_include_paths --test_output=errors ... + Linux_with_sanitizer: + runs-on: ubuntu-latest + strategy: + matrix: + config: [asan, ubsan, tsan] + + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Tests with '${{ matrix.config }}' + run: bazel test -c dbg --config=${{ matrix.config }} --cxxopt=-std=c++14 --features=external_include_paths --test_output=errors ... + macOS: runs-on: macos-latest steps: diff --git a/BUILD.bazel b/BUILD.bazel index b1e3b7fb..dd11ebdd 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -215,5 +215,9 @@ cc_test( name = "sample10_unittest", size = "small", srcs = ["googletest/samples/sample10_unittest.cc"], + tags = [ + # A memory error is expected. + "no_asan", + ], deps = [":gtest"], ) diff --git a/googlemock/test/gmock-spec-builders_test.cc b/googlemock/test/gmock-spec-builders_test.cc index aaf88d74..a0449c68 100644 --- a/googlemock/test/gmock-spec-builders_test.cc +++ b/googlemock/test/gmock-spec-builders_test.cc @@ -2154,6 +2154,7 @@ TEST_F(GMockLogTest, DoesNotPrintWarningInternallyIfVerbosityIsError) { helper_.Foo(PrintMeNot()); // This should generate a warning. } +#if !defined(GTEST_HAS_ADDRESS_SANITIZER) // Tests Mock::AllowLeak(). TEST(AllowLeakTest, AllowsLeakingUnusedMockObject) { @@ -2193,6 +2194,7 @@ TEST(AllowLeakTest, WorksWhenBothOnCallAndExpectCallArePresent) { EXPECT_CALL(*a, DoA(_)).Times(AnyNumber()); Mock::AllowLeak(a); } +#endif // Tests that we can verify and clear a mock object's expectations // when none of its methods has expectations. diff --git a/googletest/test/googletest-death-test-test.cc b/googletest/test/googletest-death-test-test.cc index 4cc81b72..f04bcbe0 100644 --- a/googletest/test/googletest-death-test-test.cc +++ b/googletest/test/googletest-death-test-test.cc @@ -283,6 +283,8 @@ TEST(ExitStatusPredicateTest, ExitedWithCode) { EXPECT_FALSE(pred1(status42)); } +#if !defined(GTEST_HAS_ADDRESS_SANITIZER) && \ + !defined(GTEST_HAS_THREAD_SANITIZER) // Tests the KilledBySignal predicate. TEST(ExitStatusPredicateTest, KilledBySignal) { const int status_segv = KilledExitStatus(SIGSEGV); @@ -294,6 +296,7 @@ TEST(ExitStatusPredicateTest, KilledBySignal) { EXPECT_FALSE(pred_segv(status_kill)); EXPECT_FALSE(pred_kill(status_segv)); } +#endif #endif // GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA