diff options
Diffstat (limited to 'lib/tsan/unit_tests')
-rw-r--r-- | lib/tsan/unit_tests/tsan_clock_test.cc | 123 | ||||
-rw-r--r-- | lib/tsan/unit_tests/tsan_flags_test.cc | 38 | ||||
-rw-r--r-- | lib/tsan/unit_tests/tsan_mman_test.cc | 109 | ||||
-rw-r--r-- | lib/tsan/unit_tests/tsan_mutex_test.cc | 126 | ||||
-rw-r--r-- | lib/tsan/unit_tests/tsan_platform_test.cc | 88 | ||||
-rw-r--r-- | lib/tsan/unit_tests/tsan_printf_test.cc | 106 | ||||
-rw-r--r-- | lib/tsan/unit_tests/tsan_shadow_test.cc | 47 | ||||
-rw-r--r-- | lib/tsan/unit_tests/tsan_suppressions_test.cc | 128 | ||||
-rw-r--r-- | lib/tsan/unit_tests/tsan_sync_test.cc | 65 | ||||
-rw-r--r-- | lib/tsan/unit_tests/tsan_vector_test.cc | 45 |
10 files changed, 875 insertions, 0 deletions
diff --git a/lib/tsan/unit_tests/tsan_clock_test.cc b/lib/tsan/unit_tests/tsan_clock_test.cc new file mode 100644 index 0000000..fe886e1 --- /dev/null +++ b/lib/tsan/unit_tests/tsan_clock_test.cc @@ -0,0 +1,123 @@ +//===-- tsan_clock_test.cc ------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of ThreadSanitizer (TSan), a race detector. +// +//===----------------------------------------------------------------------===// +#include "tsan_clock.h" +#include "tsan_rtl.h" +#include "gtest/gtest.h" + +namespace __tsan { + +TEST(Clock, VectorBasic) { + ScopedInRtl in_rtl; + ThreadClock clk; + CHECK_EQ(clk.size(), 0); + clk.tick(0); + CHECK_EQ(clk.size(), 1); + CHECK_EQ(clk.get(0), 1); + clk.tick(3); + CHECK_EQ(clk.size(), 4); + CHECK_EQ(clk.get(0), 1); + CHECK_EQ(clk.get(1), 0); + CHECK_EQ(clk.get(2), 0); + CHECK_EQ(clk.get(3), 1); + clk.tick(3); + CHECK_EQ(clk.get(3), 2); +} + +TEST(Clock, ChunkedBasic) { + ScopedInRtl in_rtl; + ThreadClock vector; + SyncClock chunked; + CHECK_EQ(vector.size(), 0); + CHECK_EQ(chunked.size(), 0); + vector.acquire(&chunked); + CHECK_EQ(vector.size(), 0); + CHECK_EQ(chunked.size(), 0); + vector.release(&chunked); + CHECK_EQ(vector.size(), 0); + CHECK_EQ(chunked.size(), 0); + vector.acq_rel(&chunked); + CHECK_EQ(vector.size(), 0); + CHECK_EQ(chunked.size(), 0); +} + +TEST(Clock, AcquireRelease) { + ScopedInRtl in_rtl; + ThreadClock vector1; + vector1.tick(100); + SyncClock chunked; + vector1.release(&chunked); + CHECK_EQ(chunked.size(), 101); + ThreadClock vector2; + vector2.acquire(&chunked); + CHECK_EQ(vector2.size(), 101); + CHECK_EQ(vector2.get(0), 0); + CHECK_EQ(vector2.get(1), 0); + CHECK_EQ(vector2.get(99), 0); + CHECK_EQ(vector2.get(100), 1); +} + +TEST(Clock, ManyThreads) { + ScopedInRtl in_rtl; + SyncClock chunked; + for (int i = 0; i < 100; i++) { + ThreadClock vector; + vector.tick(i); + vector.release(&chunked); + CHECK_EQ(chunked.size(), i + 1); + vector.acquire(&chunked); + CHECK_EQ(vector.size(), i + 1); + } + ThreadClock vector; + vector.acquire(&chunked); + CHECK_EQ(vector.size(), 100); + for (int i = 0; i < 100; i++) + CHECK_EQ(vector.get(i), 1); +} + +TEST(Clock, DifferentSizes) { + ScopedInRtl in_rtl; + { + ThreadClock vector1; + vector1.tick(10); + ThreadClock vector2; + vector2.tick(20); + { + SyncClock chunked; + vector1.release(&chunked); + CHECK_EQ(chunked.size(), 11); + vector2.release(&chunked); + CHECK_EQ(chunked.size(), 21); + } + { + SyncClock chunked; + vector2.release(&chunked); + CHECK_EQ(chunked.size(), 21); + vector1.release(&chunked); + CHECK_EQ(chunked.size(), 21); + } + { + SyncClock chunked; + vector1.release(&chunked); + vector2.acquire(&chunked); + CHECK_EQ(vector2.size(), 21); + } + { + SyncClock chunked; + vector2.release(&chunked); + vector1.acquire(&chunked); + CHECK_EQ(vector1.size(), 21); + } + } +} + +} // namespace __tsan diff --git a/lib/tsan/unit_tests/tsan_flags_test.cc b/lib/tsan/unit_tests/tsan_flags_test.cc new file mode 100644 index 0000000..d344cb5 --- /dev/null +++ b/lib/tsan/unit_tests/tsan_flags_test.cc @@ -0,0 +1,38 @@ +//===-- tsan_flags_test.cc ------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of ThreadSanitizer (TSan), a race detector. +// +//===----------------------------------------------------------------------===// +#include "tsan_flags.h" +#include "tsan_rtl.h" +#include "gtest/gtest.h" + +namespace __tsan { + +TEST(Flags, Basic) { + ScopedInRtl in_rtl; + // At least should not crash. + Flags f = {}; + InitializeFlags(&f, 0); + InitializeFlags(&f, ""); +} + +TEST(Flags, DefaultValues) { + ScopedInRtl in_rtl; + Flags f = {}; + + f.enable_annotations = false; + f.exitcode = -11; + InitializeFlags(&f, ""); + EXPECT_EQ(66, f.exitcode); + EXPECT_EQ(true, f.enable_annotations); +} + +} // namespace __tsan diff --git a/lib/tsan/unit_tests/tsan_mman_test.cc b/lib/tsan/unit_tests/tsan_mman_test.cc new file mode 100644 index 0000000..1a9a88f --- /dev/null +++ b/lib/tsan/unit_tests/tsan_mman_test.cc @@ -0,0 +1,109 @@ +//===-- tsan_mman_test.cc -------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of ThreadSanitizer (TSan), a race detector. +// +//===----------------------------------------------------------------------===// +#include "tsan_mman.h" +#include "tsan_rtl.h" +#include "gtest/gtest.h" + +namespace __tsan { + +TEST(Mman, Internal) { + ScopedInRtl in_rtl; + char *p = (char*)internal_alloc(MBlockScopedBuf, 10); + EXPECT_NE(p, (char*)0); + char *p2 = (char*)internal_alloc(MBlockScopedBuf, 20); + EXPECT_NE(p2, (char*)0); + EXPECT_NE(p2, p); + for (int i = 0; i < 10; i++) { + p[i] = 42; + } + for (int i = 0; i < 20; i++) { + ((char*)p2)[i] = 42; + } + internal_free(p); + internal_free(p2); +} + +TEST(Mman, User) { + ScopedInRtl in_rtl; + ThreadState *thr = cur_thread(); + uptr pc = 0; + char *p = (char*)user_alloc(thr, pc, 10); + EXPECT_NE(p, (char*)0); + char *p2 = (char*)user_alloc(thr, pc, 20); + EXPECT_NE(p2, (char*)0); + EXPECT_NE(p2, p); + MBlock *b = user_mblock(thr, p); + EXPECT_NE(b, (MBlock*)0); + EXPECT_EQ(b->size, (uptr)10); + MBlock *b2 = user_mblock(thr, p2); + EXPECT_NE(b2, (MBlock*)0); + EXPECT_EQ(b2->size, (uptr)20); + for (int i = 0; i < 10; i++) { + p[i] = 42; + EXPECT_EQ(b, user_mblock(thr, p + i)); + } + for (int i = 0; i < 20; i++) { + ((char*)p2)[i] = 42; + EXPECT_EQ(b2, user_mblock(thr, p2 + i)); + } + user_free(thr, pc, p); + user_free(thr, pc, p2); +} + +TEST(Mman, UserRealloc) { + ScopedInRtl in_rtl; + ThreadState *thr = cur_thread(); + uptr pc = 0; + { + void *p = user_realloc(thr, pc, 0, 0); + // Strictly saying this is incorrect, realloc(NULL, N) is equivalent to + // malloc(N), thus must return non-NULL pointer. + EXPECT_EQ(p, (void*)0); + } + { + void *p = user_realloc(thr, pc, 0, 100); + EXPECT_NE(p, (void*)0); + memset(p, 0xde, 100); + user_free(thr, pc, p); + } + { + void *p = user_alloc(thr, pc, 100); + EXPECT_NE(p, (void*)0); + memset(p, 0xde, 100); + void *p2 = user_realloc(thr, pc, p, 0); + EXPECT_EQ(p2, (void*)0); + } + { + void *p = user_realloc(thr, pc, 0, 100); + EXPECT_NE(p, (void*)0); + memset(p, 0xde, 100); + void *p2 = user_realloc(thr, pc, p, 10000); + EXPECT_NE(p2, (void*)0); + for (int i = 0; i < 100; i++) + EXPECT_EQ(((char*)p2)[i], (char)0xde); + memset(p2, 0xde, 10000); + user_free(thr, pc, p2); + } + { + void *p = user_realloc(thr, pc, 0, 10000); + EXPECT_NE(p, (void*)0); + memset(p, 0xde, 10000); + void *p2 = user_realloc(thr, pc, p, 10); + EXPECT_NE(p2, (void*)0); + for (int i = 0; i < 10; i++) + EXPECT_EQ(((char*)p2)[i], (char)0xde); + user_free(thr, pc, p2); + } +} + +} // namespace __tsan diff --git a/lib/tsan/unit_tests/tsan_mutex_test.cc b/lib/tsan/unit_tests/tsan_mutex_test.cc new file mode 100644 index 0000000..c39841d --- /dev/null +++ b/lib/tsan/unit_tests/tsan_mutex_test.cc @@ -0,0 +1,126 @@ +//===-- tsan_mutex_test.cc ------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of ThreadSanitizer (TSan), a race detector. +// +//===----------------------------------------------------------------------===// +#include "sanitizer_common/sanitizer_internal_defs.h" +#include "sanitizer_common/sanitizer_atomic.h" +#include "sanitizer_common/sanitizer_common.h" +#include "sanitizer_common/sanitizer_mutex.h" +#include "tsan_mutex.h" +#include "gtest/gtest.h" + +namespace __tsan { + +template<typename MutexType> +class TestData { + public: + explicit TestData(MutexType *mtx) + : mtx_(mtx) { + for (int i = 0; i < kSize; i++) + data_[i] = 0; + } + + void Write() { + Lock l(mtx_); + T v0 = data_[0]; + for (int i = 0; i < kSize; i++) { + CHECK_EQ(data_[i], v0); + data_[i]++; + } + } + + void Read() { + ReadLock l(mtx_); + T v0 = data_[0]; + for (int i = 0; i < kSize; i++) { + CHECK_EQ(data_[i], v0); + } + } + + void Backoff() { + volatile T data[kSize] = {}; + for (int i = 0; i < kSize; i++) { + data[i]++; + CHECK_EQ(data[i], 1); + } + } + + private: + typedef GenericScopedLock<MutexType> Lock; + static const int kSize = 64; + typedef u64 T; + MutexType *mtx_; + char pad_[kCacheLineSize]; + T data_[kSize]; +}; + +const int kThreads = 8; +const int kWriteRate = 1024; +#if TSAN_DEBUG +const int kIters = 16*1024; +#else +const int kIters = 64*1024; +#endif + +template<typename MutexType> +static void *write_mutex_thread(void *param) { + TestData<MutexType> *data = (TestData<MutexType>*)param; + for (int i = 0; i < kIters; i++) { + data->Write(); + data->Backoff(); + } + return 0; +} + +template<typename MutexType> +static void *read_mutex_thread(void *param) { + TestData<MutexType> *data = (TestData<MutexType>*)param; + for (int i = 0; i < kIters; i++) { + if ((i % kWriteRate) == 0) + data->Write(); + else + data->Read(); + data->Backoff(); + } + return 0; +} + +TEST(Mutex, Write) { + Mutex mtx(MutexTypeAnnotations, StatMtxAnnotations); + TestData<Mutex> data(&mtx); + pthread_t threads[kThreads]; + for (int i = 0; i < kThreads; i++) + pthread_create(&threads[i], 0, write_mutex_thread<Mutex>, &data); + for (int i = 0; i < kThreads; i++) + pthread_join(threads[i], 0); +} + +TEST(Mutex, ReadWrite) { + Mutex mtx(MutexTypeAnnotations, StatMtxAnnotations); + TestData<Mutex> data(&mtx); + pthread_t threads[kThreads]; + for (int i = 0; i < kThreads; i++) + pthread_create(&threads[i], 0, read_mutex_thread<Mutex>, &data); + for (int i = 0; i < kThreads; i++) + pthread_join(threads[i], 0); +} + +TEST(Mutex, SpinWrite) { + SpinMutex mtx; + TestData<SpinMutex> data(&mtx); + pthread_t threads[kThreads]; + for (int i = 0; i < kThreads; i++) + pthread_create(&threads[i], 0, write_mutex_thread<SpinMutex>, &data); + for (int i = 0; i < kThreads; i++) + pthread_join(threads[i], 0); +} + +} // namespace __tsan diff --git a/lib/tsan/unit_tests/tsan_platform_test.cc b/lib/tsan/unit_tests/tsan_platform_test.cc new file mode 100644 index 0000000..64c4499 --- /dev/null +++ b/lib/tsan/unit_tests/tsan_platform_test.cc @@ -0,0 +1,88 @@ +//===-- tsan_platform_test.cc ---------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of ThreadSanitizer (TSan), a race detector. +// +//===----------------------------------------------------------------------===// +#include "sanitizer_common/sanitizer_libc.h" +#include "tsan_platform.h" +#include "gtest/gtest.h" + +namespace __tsan { + +static void TestThreadInfo(bool main) { + ScopedInRtl in_rtl; + uptr stk_addr = 0; + uptr stk_size = 0; + uptr tls_addr = 0; + uptr tls_size = 0; + GetThreadStackAndTls(main, &stk_addr, &stk_size, &tls_addr, &tls_size); + // Printf("stk=%zx-%zx(%zu)\n", stk_addr, stk_addr + stk_size, stk_size); + // Printf("tls=%zx-%zx(%zu)\n", tls_addr, tls_addr + tls_size, tls_size); + + int stack_var; + EXPECT_NE(stk_addr, (uptr)0); + EXPECT_NE(stk_size, (uptr)0); + EXPECT_GT((uptr)&stack_var, stk_addr); + EXPECT_LT((uptr)&stack_var, stk_addr + stk_size); + + static __thread int thread_var; + EXPECT_NE(tls_addr, (uptr)0); + EXPECT_NE(tls_size, (uptr)0); + EXPECT_GT((uptr)&thread_var, tls_addr); + EXPECT_LT((uptr)&thread_var, tls_addr + tls_size); + + // Ensure that tls and stack do not intersect. + uptr tls_end = tls_addr + tls_size; + EXPECT_TRUE(tls_addr < stk_addr || tls_addr >= stk_addr + stk_size); + EXPECT_TRUE(tls_end < stk_addr || tls_end >= stk_addr + stk_size); + EXPECT_TRUE((tls_addr < stk_addr) == (tls_end < stk_addr)); +} + +static void *WorkerThread(void *arg) { + TestThreadInfo(false); + return 0; +} + +TEST(Platform, ThreadInfoMain) { + TestThreadInfo(true); +} + +TEST(Platform, ThreadInfoWorker) { + pthread_t t; + pthread_create(&t, 0, WorkerThread, 0); + pthread_join(t, 0); +} + +TEST(Platform, FileOps) { + const char *str1 = "qwerty"; + uptr len1 = internal_strlen(str1); + const char *str2 = "zxcv"; + uptr len2 = internal_strlen(str2); + + fd_t fd = internal_open("./tsan_test.tmp", true); + EXPECT_NE(fd, kInvalidFd); + EXPECT_EQ(len1, internal_write(fd, str1, len1)); + EXPECT_EQ(len2, internal_write(fd, str2, len2)); + internal_close(fd); + + fd = internal_open("./tsan_test.tmp", false); + EXPECT_NE(fd, kInvalidFd); + EXPECT_EQ(len1 + len2, internal_filesize(fd)); + char buf[64] = {}; + EXPECT_EQ(len1, internal_read(fd, buf, len1)); + EXPECT_EQ(0, internal_memcmp(buf, str1, len1)); + EXPECT_EQ((char)0, buf[len1 + 1]); + internal_memset(buf, 0, len1); + EXPECT_EQ(len2, internal_read(fd, buf, len2)); + EXPECT_EQ(0, internal_memcmp(buf, str2, len2)); + internal_close(fd); +} + +} // namespace __tsan diff --git a/lib/tsan/unit_tests/tsan_printf_test.cc b/lib/tsan/unit_tests/tsan_printf_test.cc new file mode 100644 index 0000000..0dfd1d2 --- /dev/null +++ b/lib/tsan/unit_tests/tsan_printf_test.cc @@ -0,0 +1,106 @@ +//===-- tsan_printf_test.cc -----------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of ThreadSanitizer (TSan), a race detector. +// +//===----------------------------------------------------------------------===// +#include "tsan_rtl.h" +#include "gtest/gtest.h" + +#include <string.h> +#include <limits.h> + +namespace __tsan { + +TEST(Printf, Basic) { + char buf[1024]; + uptr len = internal_snprintf(buf, sizeof(buf), + "a%db%zdc%ue%zuf%xh%zxq%pe%sr", + (int)-1, (long)-2, // NOLINT + (unsigned)-4, (unsigned long)5, // NOLINT + (unsigned)10, (unsigned long)11, // NOLINT + (void*)0x123, "_string_"); + EXPECT_EQ(len, strlen(buf)); + EXPECT_EQ(0, strcmp(buf, "a-1b-2c4294967292e5fahbq" + "0x000000000123e_string_r")); +} + +TEST(Printf, OverflowStr) { + char buf[] = "123456789"; + uptr len = internal_snprintf(buf, 4, "%s", "abcdef"); // NOLINT + EXPECT_EQ(len, (uptr)6); + EXPECT_EQ(0, strcmp(buf, "abc")); + EXPECT_EQ(buf[3], 0); + EXPECT_EQ(buf[4], '5'); + EXPECT_EQ(buf[5], '6'); + EXPECT_EQ(buf[6], '7'); + EXPECT_EQ(buf[7], '8'); + EXPECT_EQ(buf[8], '9'); + EXPECT_EQ(buf[9], 0); +} + +TEST(Printf, OverflowInt) { + char buf[] = "123456789"; + internal_snprintf(buf, 4, "%d", -123456789); // NOLINT + EXPECT_EQ(0, strcmp(buf, "-12")); + EXPECT_EQ(buf[3], 0); + EXPECT_EQ(buf[4], '5'); + EXPECT_EQ(buf[5], '6'); + EXPECT_EQ(buf[6], '7'); + EXPECT_EQ(buf[7], '8'); + EXPECT_EQ(buf[8], '9'); + EXPECT_EQ(buf[9], 0); +} + +TEST(Printf, OverflowUint) { + char buf[] = "123456789"; + internal_snprintf(buf, 4, "a%zx", (unsigned long)0x123456789); // NOLINT + EXPECT_EQ(0, strcmp(buf, "a12")); + EXPECT_EQ(buf[3], 0); + EXPECT_EQ(buf[4], '5'); + EXPECT_EQ(buf[5], '6'); + EXPECT_EQ(buf[6], '7'); + EXPECT_EQ(buf[7], '8'); + EXPECT_EQ(buf[8], '9'); + EXPECT_EQ(buf[9], 0); +} + +TEST(Printf, OverflowPtr) { + char buf[] = "123456789"; + internal_snprintf(buf, 4, "%p", (void*)0x123456789); // NOLINT + EXPECT_EQ(0, strcmp(buf, "0x0")); + EXPECT_EQ(buf[3], 0); + EXPECT_EQ(buf[4], '5'); + EXPECT_EQ(buf[5], '6'); + EXPECT_EQ(buf[6], '7'); + EXPECT_EQ(buf[7], '8'); + EXPECT_EQ(buf[8], '9'); + EXPECT_EQ(buf[9], 0); +} + +template<typename T> +static void TestMinMax(const char *fmt, T min, T max) { + char buf[1024]; + uptr len = internal_snprintf(buf, sizeof(buf), fmt, min, max); + char buf2[1024]; + snprintf(buf2, sizeof(buf2), fmt, min, max); + EXPECT_EQ(len, strlen(buf)); + EXPECT_EQ(0, strcmp(buf, buf2)); +} + +TEST(Printf, MinMax) { + TestMinMax<int>("%d-%d", INT_MIN, INT_MAX); // NOLINT + TestMinMax<long>("%zd-%zd", LONG_MIN, LONG_MAX); // NOLINT + TestMinMax<unsigned>("%u-%u", 0, UINT_MAX); // NOLINT + TestMinMax<unsigned long>("%zu-%zu", 0, ULONG_MAX); // NOLINT + TestMinMax<unsigned>("%x-%x", 0, UINT_MAX); // NOLINT + TestMinMax<unsigned long>("%zx-%zx", 0, ULONG_MAX); // NOLINT +} + +} // namespace __tsan diff --git a/lib/tsan/unit_tests/tsan_shadow_test.cc b/lib/tsan/unit_tests/tsan_shadow_test.cc new file mode 100644 index 0000000..41f9121 --- /dev/null +++ b/lib/tsan/unit_tests/tsan_shadow_test.cc @@ -0,0 +1,47 @@ +//===-- tsan_shadow_test.cc -----------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of ThreadSanitizer (TSan), a race detector. +// +//===----------------------------------------------------------------------===// +#include "tsan_platform.h" +#include "gtest/gtest.h" + +namespace __tsan { + +TEST(Shadow, Mapping) { + static int global; + int stack; + void *heap = malloc(0); + free(heap); + + CHECK(IsAppMem((uptr)&global)); + CHECK(IsAppMem((uptr)&stack)); + CHECK(IsAppMem((uptr)heap)); + + CHECK(IsShadowMem(MemToShadow((uptr)&global))); + CHECK(IsShadowMem(MemToShadow((uptr)&stack))); + CHECK(IsShadowMem(MemToShadow((uptr)heap))); +} + +TEST(Shadow, Celling) { + u64 aligned_data[4]; + char *data = (char*)aligned_data; + CHECK_EQ((uptr)data % kShadowSize, 0); + uptr s0 = MemToShadow((uptr)&data[0]); + CHECK_EQ(s0 % kShadowSize, 0); + for (unsigned i = 1; i < kShadowCell; i++) + CHECK_EQ(s0, MemToShadow((uptr)&data[i])); + for (unsigned i = kShadowCell; i < 2*kShadowCell; i++) + CHECK_EQ(s0 + kShadowSize*kShadowCnt, MemToShadow((uptr)&data[i])); + for (unsigned i = 2*kShadowCell; i < 3*kShadowCell; i++) + CHECK_EQ(s0 + 2*kShadowSize*kShadowCnt, MemToShadow((uptr)&data[i])); +} + +} // namespace __tsan diff --git a/lib/tsan/unit_tests/tsan_suppressions_test.cc b/lib/tsan/unit_tests/tsan_suppressions_test.cc new file mode 100644 index 0000000..e1e0c12 --- /dev/null +++ b/lib/tsan/unit_tests/tsan_suppressions_test.cc @@ -0,0 +1,128 @@ +//===-- tsan_suppressions_test.cc -----------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of ThreadSanitizer (TSan), a race detector. +// +//===----------------------------------------------------------------------===// +#include "tsan_suppressions.h" +#include "tsan_rtl.h" +#include "gtest/gtest.h" + +#include <string.h> + +namespace __tsan { + +TEST(Suppressions, Parse) { + ScopedInRtl in_rtl; + Suppression *supp0 = SuppressionParse( + "race:foo\n" + " race:bar\n" // NOLINT + "race:baz \n" // NOLINT + "# a comment\n" + "race:quz\n" + ); // NOLINT + Suppression *supp = supp0; + EXPECT_EQ(supp->type, SuppressionRace); + EXPECT_EQ(0, strcmp(supp->templ, "quz")); + supp = supp->next; + EXPECT_EQ(supp->type, SuppressionRace); + EXPECT_EQ(0, strcmp(supp->templ, "baz")); + supp = supp->next; + EXPECT_EQ(supp->type, SuppressionRace); + EXPECT_EQ(0, strcmp(supp->templ, "bar")); + supp = supp->next; + EXPECT_EQ(supp->type, SuppressionRace); + EXPECT_EQ(0, strcmp(supp->templ, "foo")); + supp = supp->next; + EXPECT_EQ((Suppression*)0, supp); +} + +TEST(Suppressions, Parse2) { + ScopedInRtl in_rtl; + Suppression *supp0 = SuppressionParse( + " # first line comment\n" // NOLINT + " race:bar \n" // NOLINT + "race:baz* *baz\n" + "# a comment\n" + "# last line comment\n" + ); // NOLINT + Suppression *supp = supp0; + EXPECT_EQ(supp->type, SuppressionRace); + EXPECT_EQ(0, strcmp(supp->templ, "baz* *baz")); + supp = supp->next; + EXPECT_EQ(supp->type, SuppressionRace); + EXPECT_EQ(0, strcmp(supp->templ, "bar")); + supp = supp->next; + EXPECT_EQ((Suppression*)0, supp); +} + +TEST(Suppressions, Parse3) { + ScopedInRtl in_rtl; + Suppression *supp0 = SuppressionParse( + "# last suppression w/o line-feed\n" + "race:foo\n" + "race:bar" + ); // NOLINT + Suppression *supp = supp0; + EXPECT_EQ(supp->type, SuppressionRace); + EXPECT_EQ(0, strcmp(supp->templ, "bar")); + supp = supp->next; + EXPECT_EQ(supp->type, SuppressionRace); + EXPECT_EQ(0, strcmp(supp->templ, "foo")); + supp = supp->next; + EXPECT_EQ((Suppression*)0, supp); +} + +TEST(Suppressions, ParseType) { + ScopedInRtl in_rtl; + Suppression *supp0 = SuppressionParse( + "race:foo\n" + "thread:bar\n" + "mutex:baz\n" + "signal:quz\n" + ); // NOLINT + Suppression *supp = supp0; + EXPECT_EQ(supp->type, SuppressionSignal); + EXPECT_EQ(0, strcmp(supp->templ, "quz")); + supp = supp->next; + EXPECT_EQ(supp->type, SuppressionMutex); + EXPECT_EQ(0, strcmp(supp->templ, "baz")); + supp = supp->next; + EXPECT_EQ(supp->type, SuppressionThread); + EXPECT_EQ(0, strcmp(supp->templ, "bar")); + supp = supp->next; + EXPECT_EQ(supp->type, SuppressionRace); + EXPECT_EQ(0, strcmp(supp->templ, "foo")); + supp = supp->next; + EXPECT_EQ((Suppression*)0, supp); +} + +static bool MyMatch(const char *templ, const char *func) { + char tmp[1024]; + strcpy(tmp, templ); // NOLINT + return SuppressionMatch(tmp, func); +} + +TEST(Suppressions, Match) { + EXPECT_TRUE(MyMatch("foobar", "foobar")); + EXPECT_TRUE(MyMatch("foobar", "prefix_foobar_postfix")); + EXPECT_TRUE(MyMatch("*foobar*", "prefix_foobar_postfix")); + EXPECT_TRUE(MyMatch("foo*bar", "foo_middle_bar")); + EXPECT_TRUE(MyMatch("foo*bar", "foobar")); + EXPECT_TRUE(MyMatch("foo*bar*baz", "foo_middle_bar_another_baz")); + EXPECT_TRUE(MyMatch("foo*bar*baz", "foo_middle_barbaz")); + + EXPECT_FALSE(MyMatch("foo", "baz")); + EXPECT_FALSE(MyMatch("foobarbaz", "foobar")); + EXPECT_FALSE(MyMatch("foobarbaz", "barbaz")); + EXPECT_FALSE(MyMatch("foo*bar", "foobaz")); + EXPECT_FALSE(MyMatch("foo*bar", "foo_baz")); +} + +} // namespace __tsan diff --git a/lib/tsan/unit_tests/tsan_sync_test.cc b/lib/tsan/unit_tests/tsan_sync_test.cc new file mode 100644 index 0000000..b7605a5 --- /dev/null +++ b/lib/tsan/unit_tests/tsan_sync_test.cc @@ -0,0 +1,65 @@ +//===-- tsan_sync_test.cc -------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of ThreadSanitizer (TSan), a race detector. +// +//===----------------------------------------------------------------------===// +#include "tsan_sync.h" +#include "tsan_rtl.h" +#include "tsan_mman.h" +#include "gtest/gtest.h" + +#include <stdlib.h> +#include <stdint.h> +#include <map> + +namespace __tsan { + +TEST(Sync, Table) { + const uintptr_t kIters = 512*1024; + const uintptr_t kRange = 10000; + + ScopedInRtl in_rtl; + ThreadState *thr = cur_thread(); + uptr pc = 0; + + SyncTab tab; + SyncVar *golden[kRange] = {}; + unsigned seed = 0; + for (uintptr_t i = 0; i < kIters; i++) { + uintptr_t addr = rand_r(&seed) % (kRange - 1) + 1; + if (rand_r(&seed) % 2) { + // Get or add. + SyncVar *v = tab.GetAndLock(thr, pc, addr, true); + EXPECT_TRUE(golden[addr] == 0 || golden[addr] == v); + EXPECT_EQ(v->addr, addr); + golden[addr] = v; + v->mtx.Unlock(); + } else { + // Remove. + SyncVar *v = tab.GetAndRemove(thr, pc, addr); + EXPECT_EQ(golden[addr], v); + if (v) { + EXPECT_EQ(v->addr, addr); + golden[addr] = 0; + DestroyAndFree(v); + } + } + } + for (uintptr_t addr = 0; addr < kRange; addr++) { + if (golden[addr] == 0) + continue; + SyncVar *v = tab.GetAndRemove(thr, pc, addr); + EXPECT_EQ(v, golden[addr]); + EXPECT_EQ(v->addr, addr); + DestroyAndFree(v); + } +} + +} // namespace __tsan diff --git a/lib/tsan/unit_tests/tsan_vector_test.cc b/lib/tsan/unit_tests/tsan_vector_test.cc new file mode 100644 index 0000000..cfef6e5 --- /dev/null +++ b/lib/tsan/unit_tests/tsan_vector_test.cc @@ -0,0 +1,45 @@ +//===-- tsan_vector_test.cc -----------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of ThreadSanitizer (TSan), a race detector. +// +//===----------------------------------------------------------------------===// +#include "tsan_vector.h" +#include "tsan_rtl.h" +#include "gtest/gtest.h" + +namespace __tsan { + +TEST(Vector, Basic) { + ScopedInRtl in_rtl; + Vector<int> v(MBlockScopedBuf); + EXPECT_EQ(v.Size(), (uptr)0); + v.PushBack(42); + EXPECT_EQ(v.Size(), (uptr)1); + EXPECT_EQ(v[0], 42); + v.PushBack(43); + EXPECT_EQ(v.Size(), (uptr)2); + EXPECT_EQ(v[0], 42); + EXPECT_EQ(v[1], 43); +} + +TEST(Vector, Stride) { + ScopedInRtl in_rtl; + Vector<int> v(MBlockScopedBuf); + for (int i = 0; i < 1000; i++) { + v.PushBack(i); + EXPECT_EQ(v.Size(), (uptr)(i + 1)); + EXPECT_EQ(v[i], i); + } + for (int i = 0; i < 1000; i++) { + EXPECT_EQ(v[i], i); + } +} + +} // namespace __tsan |