From fabc80b6ae7318cb958c55a6be0d858701cc91f6 Mon Sep 17 00:00:00 2001 From: streshchukvitaly Date: Wed, 13 Nov 2024 12:04:17 +0300 Subject: [PATCH] Add DataRace test for Thread Sanitizer Signed-off-by: streshchukvitaly --- configs/test_config.yaml | 14 +++++++++++ tests/CMakeLists.txt | 2 ++ tests/tsan/data-race/CMakeLists.txt | 16 ++++++++++++ tests/tsan/data-race/README.md | 14 +++++++++++ tests/tsan/data-race/src/a.cpp | 16 ++++++++++++ tests/tsan/data-race/src/main.cpp | 38 +++++++++++++++++++++++++++++ 6 files changed, 100 insertions(+) create mode 100644 tests/tsan/data-race/CMakeLists.txt create mode 100644 tests/tsan/data-race/README.md create mode 100644 tests/tsan/data-race/src/a.cpp create mode 100644 tests/tsan/data-race/src/main.cpp diff --git a/configs/test_config.yaml b/configs/test_config.yaml index 062c49c..1d87a16 100644 --- a/configs/test_config.yaml +++ b/configs/test_config.yaml @@ -762,6 +762,18 @@ define: &ubsan-integer-overflow orig: "PASSED" adlt: "PASSED" +define: &tsan-data-race + path: "tsan/data-race" + binary: "tsanDataRace_main" + cases: + - prefix: "tsanDataRace_main" + gtest-filter: "" + args: [] + env: ["TSAN_OPTIONS=\"exitcode=0:abort_on_error=0:halt_on_error=0:log_path=tsan_report.log\""] + states: + orig: "FAILED" + adlt: "FAILED" + test-list: tests: [ *base-cross, @@ -817,4 +829,6 @@ test-list: *benchmarks-load-one, *ubsan-integer-overflow, + + *tsan-data-race, ] diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 292abfd..d6aef39 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -49,3 +49,5 @@ add_subdirectory(ld-musl/libc_secure) add_subdirectory(benchmarks/load_one) add_subdirectory(ubsan/integer-overflow) + +add_subdirectory(tsan/data-race) diff --git a/tests/tsan/data-race/CMakeLists.txt b/tests/tsan/data-race/CMakeLists.txt new file mode 100644 index 0000000..39a1f64 --- /dev/null +++ b/tests/tsan/data-race/CMakeLists.txt @@ -0,0 +1,16 @@ +initproject(PROJECT_NAME tsanDataRace EXECUTABLES main LIBS a) + +add_library(${a} SHARED src/a.cpp) +target_compile_options(${a} PRIVATE "-fsanitize=thread") +target_link_options(${a} PRIVATE "-fsanitize=thread") + +add_custom_target( + ${ADLT_PROJECT_LIB} ALL + DEPENDS ${a} + COMMAND python3 ${toolsDir}/build_adlt_lib.py -od ${CMAKE_CURRENT_BINARY_DIR} + -i ${ADLT_LIB_CONTENTS} -o "${ADLT_PROJECT_LIB}") + +add_adlt_test(TARGET ${main} SOURCES src/main.cpp LIBS ${a}) +target_link_options( + ${main} PRIVATE + "-Wl,${LLVM}/lib/clang/15.0.4/lib/aarch64-linux-ohos/libclang_rt.tsan.a") diff --git a/tests/tsan/data-race/README.md b/tests/tsan/data-race/README.md new file mode 100644 index 0000000..2c0f60c --- /dev/null +++ b/tests/tsan/data-race/README.md @@ -0,0 +1,14 @@ +`qemu-aarch64-static` has a problem with running tests with the option: `-fsanitize=thread`. Launching any program causes an error like: +``` +execve failed, errno 8. +``` + +To be able to run a test with thread sanitizer, it is necessary to use a script: +https://github.com/qemu/qemu/blob/master/scripts/qemu-binfmt-conf.sh + +It is necessary to execute the command and specify the path to qemu, for example: +```shell +sudo qemu-binfmt-conf.sh --qemu-path $HOME/work/sdk/ +``` + +You should then be able to run the binary without errors. diff --git a/tests/tsan/data-race/src/a.cpp b/tests/tsan/data-race/src/a.cpp new file mode 100644 index 0000000..8b4bd20 --- /dev/null +++ b/tests/tsan/data-race/src/a.cpp @@ -0,0 +1,16 @@ +#include + +extern int global; + +void *testThread(void *x) { + global = 42; + return x; +} + +int testDataRace() { + pthread_t t; + pthread_create(&t, NULL, testThread, NULL); + global = 43; + pthread_join(t, NULL); + return global; +} diff --git a/tests/tsan/data-race/src/main.cpp b/tests/tsan/data-race/src/main.cpp new file mode 100644 index 0000000..9c19e02 --- /dev/null +++ b/tests/tsan/data-race/src/main.cpp @@ -0,0 +1,38 @@ +#include "gtest/gtest.h" +#include +#include + +int global; + +extern int testDataRace(); + +TEST(tsan, DataRace) { + int result = testDataRace(); + (void)result; + + std::string filename = "tsan_report.log." + std::to_string(getpid()); + + ASSERT_TRUE(!filename.empty()) << "TSan report not found!"; + + std::ifstream reportFile(filename); + ASSERT_TRUE(reportFile) << "Unable to open file: " << filename; + + // Read all data from the file. + std::stringstream strStream; + strStream << reportFile.rdbuf(); + std::string reportData = strStream.str(); + + ASSERT_TRUE(!reportData.empty()) + << "Report file: " << filename << " is empty!"; + + std::string firstCase = "SUMMARY: ThreadSanitizer: data race"; + if (reportData.find(firstCase) == std::string::npos) + FAIL() << "Failed to match a string in the report file: " << firstCase; + + SUCCEED(); +} + +GTEST_API_ int main(int argc, char **argv) { + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} -- Gitee