diff options
Diffstat (limited to 'lib/sanitizer_common/tests')
6 files changed, 209 insertions, 8 deletions
diff --git a/lib/sanitizer_common/tests/CMakeLists.txt b/lib/sanitizer_common/tests/CMakeLists.txt index 20698b9a8a96a..b310f93743acf 100644 --- a/lib/sanitizer_common/tests/CMakeLists.txt +++ b/lib/sanitizer_common/tests/CMakeLists.txt @@ -26,6 +26,7 @@ set(SANITIZER_UNITTESTS sanitizer_posix_test.cc sanitizer_printf_test.cc sanitizer_procmaps_test.cc + sanitizer_quarantine_test.cc sanitizer_stackdepot_test.cc sanitizer_stacktrace_printer_test.cc sanitizer_stacktrace_test.cc diff --git a/lib/sanitizer_common/tests/sanitizer_allocator_test.cc b/lib/sanitizer_common/tests/sanitizer_allocator_test.cc index 8df5efda674ee..e14517fca518f 100644 --- a/lib/sanitizer_common/tests/sanitizer_allocator_test.cc +++ b/lib/sanitizer_common/tests/sanitizer_allocator_test.cc @@ -23,6 +23,7 @@ #include <stdlib.h> #include <algorithm> #include <vector> +#include <random> #include <set> using namespace __sanitizer; @@ -539,6 +540,7 @@ void TestCombinedAllocator() { Allocator; Allocator *a = new Allocator; a->Init(/* may_return_null */ true, kReleaseToOSIntervalNever); + std::mt19937 r; AllocatorCache cache; memset(&cache, 0, sizeof(cache)); @@ -570,7 +572,7 @@ void TestCombinedAllocator() { allocated.push_back(x); } - random_shuffle(allocated.begin(), allocated.end()); + std::shuffle(allocated.begin(), allocated.end(), r); for (uptr i = 0; i < kNumAllocs; i++) { void *x = allocated[i]; diff --git a/lib/sanitizer_common/tests/sanitizer_bitvector_test.cc b/lib/sanitizer_common/tests/sanitizer_bitvector_test.cc index 706b4c58968ea..dec5459b25155 100644 --- a/lib/sanitizer_common/tests/sanitizer_bitvector_test.cc +++ b/lib/sanitizer_common/tests/sanitizer_bitvector_test.cc @@ -19,6 +19,7 @@ #include <algorithm> #include <vector> +#include <random> #include <set> using namespace __sanitizer; @@ -75,6 +76,7 @@ void Print(const set<uptr> &s) { template <class BV> void TestBitVector(uptr expected_size) { + std::mt19937 r; BV bv, bv1, t_bv; EXPECT_EQ(expected_size, BV::kSize); bv.clear(); @@ -112,7 +114,7 @@ void TestBitVector(uptr expected_size) { for (uptr it = 0; it < 30; it++) { // iota for (size_t j = 0; j < bits.size(); j++) bits[j] = j; - random_shuffle(bits.begin(), bits.end()); + std::shuffle(bits.begin(), bits.end(), r); set<uptr> s, s1, t_s; bv.clear(); bv1.clear(); diff --git a/lib/sanitizer_common/tests/sanitizer_list_test.cc b/lib/sanitizer_common/tests/sanitizer_list_test.cc index fbe53c0375c05..ede9771cb2496 100644 --- a/lib/sanitizer_common/tests/sanitizer_list_test.cc +++ b/lib/sanitizer_common/tests/sanitizer_list_test.cc @@ -125,6 +125,22 @@ TEST(SanitizerCommon, IntrusiveList) { CHECK(l.empty()); l.CheckConsistency(); + l.push_back(x); + l.push_back(y); + l.push_back(z); + l.extract(x, y); + CHECK_EQ(l.size(), 2); + CHECK_EQ(l.front(), x); + CHECK_EQ(l.back(), z); + l.CheckConsistency(); + l.extract(x, z); + CHECK_EQ(l.size(), 1); + CHECK_EQ(l.front(), x); + CHECK_EQ(l.back(), x); + l.CheckConsistency(); + l.pop_front(); + CHECK(l.empty()); + List l1, l2; l1.clear(); l2.clear(); diff --git a/lib/sanitizer_common/tests/sanitizer_quarantine_test.cc b/lib/sanitizer_common/tests/sanitizer_quarantine_test.cc new file mode 100644 index 0000000000000..23ed5f97ae27f --- /dev/null +++ b/lib/sanitizer_common/tests/sanitizer_quarantine_test.cc @@ -0,0 +1,180 @@ +//===-- sanitizer_quarantine_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/AddressSanitizer runtime. +// +//===----------------------------------------------------------------------===// +#include "sanitizer_common/sanitizer_common.h" +#include "sanitizer_common/sanitizer_quarantine.h" +#include "gtest/gtest.h" + +#include <stdlib.h> + +namespace __sanitizer { + +struct QuarantineCallback { + void Recycle(void *m) {} + void *Allocate(uptr size) { + return malloc(size); + } + void Deallocate(void *p) { + free(p); + } +}; + +typedef QuarantineCache<QuarantineCallback> Cache; + +static void* kFakePtr = reinterpret_cast<void*>(0xFA83FA83); +static const size_t kBlockSize = 8; + +static QuarantineCallback cb; + +static void DeallocateCache(Cache *cache) { + while (QuarantineBatch *batch = cache->DequeueBatch()) + cb.Deallocate(batch); +} + +TEST(SanitizerCommon, QuarantineBatchMerge) { + // Verify the trivial case. + QuarantineBatch into; + into.init(kFakePtr, 4UL); + QuarantineBatch from; + from.init(kFakePtr, 8UL); + + into.merge(&from); + + ASSERT_EQ(into.count, 2UL); + ASSERT_EQ(into.batch[0], kFakePtr); + ASSERT_EQ(into.batch[1], kFakePtr); + ASSERT_EQ(into.size, 12UL + sizeof(QuarantineBatch)); + ASSERT_EQ(into.quarantined_size(), 12UL); + + ASSERT_EQ(from.count, 0UL); + ASSERT_EQ(from.size, sizeof(QuarantineBatch)); + ASSERT_EQ(from.quarantined_size(), 0UL); + + // Merge the batch to the limit. + for (uptr i = 2; i < QuarantineBatch::kSize; ++i) + from.push_back(kFakePtr, 8UL); + ASSERT_TRUE(into.count + from.count == QuarantineBatch::kSize); + ASSERT_TRUE(into.can_merge(&from)); + + into.merge(&from); + ASSERT_TRUE(into.count == QuarantineBatch::kSize); + + // No more space, not even for one element. + from.init(kFakePtr, 8UL); + + ASSERT_FALSE(into.can_merge(&from)); +} + +TEST(SanitizerCommon, QuarantineCacheMergeBatchesEmpty) { + Cache cache; + Cache to_deallocate; + cache.MergeBatches(&to_deallocate); + + ASSERT_EQ(to_deallocate.Size(), 0UL); + ASSERT_EQ(to_deallocate.DequeueBatch(), nullptr); +} + +TEST(SanitizerCommon, QuarantineCacheMergeBatchesOneBatch) { + Cache cache; + cache.Enqueue(cb, kFakePtr, kBlockSize); + ASSERT_EQ(kBlockSize + sizeof(QuarantineBatch), cache.Size()); + + Cache to_deallocate; + cache.MergeBatches(&to_deallocate); + + // Nothing to merge, nothing to deallocate. + ASSERT_EQ(kBlockSize + sizeof(QuarantineBatch), cache.Size()); + + ASSERT_EQ(to_deallocate.Size(), 0UL); + ASSERT_EQ(to_deallocate.DequeueBatch(), nullptr); + + DeallocateCache(&cache); +} + +TEST(SanitizerCommon, QuarantineCacheMergeBatchesSmallBatches) { + // Make a cache with two batches small enough to merge. + Cache from; + from.Enqueue(cb, kFakePtr, kBlockSize); + Cache cache; + cache.Enqueue(cb, kFakePtr, kBlockSize); + + cache.Transfer(&from); + ASSERT_EQ(kBlockSize * 2 + sizeof(QuarantineBatch) * 2, cache.Size()); + + Cache to_deallocate; + cache.MergeBatches(&to_deallocate); + + // Batches merged, one batch to deallocate. + ASSERT_EQ(kBlockSize * 2 + sizeof(QuarantineBatch), cache.Size()); + ASSERT_EQ(to_deallocate.Size(), sizeof(QuarantineBatch)); + + DeallocateCache(&cache); + DeallocateCache(&to_deallocate); +} + +TEST(SanitizerCommon, QuarantineCacheMergeBatchesTooBigToMerge) { + const uptr kNumBlocks = QuarantineBatch::kSize - 1; + + // Make a cache with two batches small enough to merge. + Cache from; + Cache cache; + for (uptr i = 0; i < kNumBlocks; ++i) { + from.Enqueue(cb, kFakePtr, kBlockSize); + cache.Enqueue(cb, kFakePtr, kBlockSize); + } + cache.Transfer(&from); + ASSERT_EQ(kBlockSize * kNumBlocks * 2 + + sizeof(QuarantineBatch) * 2, cache.Size()); + + Cache to_deallocate; + cache.MergeBatches(&to_deallocate); + + // Batches cannot be merged. + ASSERT_EQ(kBlockSize * kNumBlocks * 2 + + sizeof(QuarantineBatch) * 2, cache.Size()); + ASSERT_EQ(to_deallocate.Size(), 0UL); + + DeallocateCache(&cache); +} + +TEST(SanitizerCommon, QuarantineCacheMergeBatchesALotOfBatches) { + const uptr kNumBatchesAfterMerge = 3; + const uptr kNumBlocks = QuarantineBatch::kSize * kNumBatchesAfterMerge; + const uptr kNumBatchesBeforeMerge = kNumBlocks; + + // Make a cache with many small batches. + Cache cache; + for (uptr i = 0; i < kNumBlocks; ++i) { + Cache from; + from.Enqueue(cb, kFakePtr, kBlockSize); + cache.Transfer(&from); + } + + ASSERT_EQ(kBlockSize * kNumBlocks + + sizeof(QuarantineBatch) * kNumBatchesBeforeMerge, cache.Size()); + + Cache to_deallocate; + cache.MergeBatches(&to_deallocate); + + // All blocks should fit into 3 batches. + ASSERT_EQ(kBlockSize * kNumBlocks + + sizeof(QuarantineBatch) * kNumBatchesAfterMerge, cache.Size()); + + ASSERT_EQ(to_deallocate.Size(), + sizeof(QuarantineBatch) * + (kNumBatchesBeforeMerge - kNumBatchesAfterMerge)); + + DeallocateCache(&cache); + DeallocateCache(&to_deallocate); +} + +} // namespace __sanitizer diff --git a/lib/sanitizer_common/tests/sanitizer_thread_registry_test.cc b/lib/sanitizer_common/tests/sanitizer_thread_registry_test.cc index 1132bfdf62e32..f8b8c12d4ac34 100644 --- a/lib/sanitizer_common/tests/sanitizer_thread_registry_test.cc +++ b/lib/sanitizer_common/tests/sanitizer_thread_registry_test.cc @@ -67,7 +67,7 @@ static void MarkUidAsPresent(ThreadContextBase *tctx, void *arg) { static void TestRegistry(ThreadRegistry *registry, bool has_quarantine) { // Create and start a main thread. EXPECT_EQ(0U, registry->CreateThread(get_uid(0), true, -1, 0)); - registry->StartThread(0, 0, 0); + registry->StartThread(0, 0, false, 0); // Create a bunch of threads. for (u32 i = 1; i <= 10; i++) { EXPECT_EQ(i, registry->CreateThread(get_uid(i), is_detached(i), 0, 0)); @@ -75,7 +75,7 @@ static void TestRegistry(ThreadRegistry *registry, bool has_quarantine) { CheckThreadQuantity(registry, 11, 1, 11); // Start some of them. for (u32 i = 1; i <= 5; i++) { - registry->StartThread(i, 0, 0); + registry->StartThread(i, 0, false, 0); } CheckThreadQuantity(registry, 11, 6, 11); // Finish, create and start more threads. @@ -85,7 +85,7 @@ static void TestRegistry(ThreadRegistry *registry, bool has_quarantine) { registry->JoinThread(i, 0); } for (u32 i = 6; i <= 10; i++) { - registry->StartThread(i, 0, 0); + registry->StartThread(i, 0, false, 0); } std::vector<u32> new_tids; for (u32 i = 11; i <= 15; i++) { @@ -112,7 +112,7 @@ static void TestRegistry(ThreadRegistry *registry, bool has_quarantine) { } for (u32 i = 0; i < new_tids.size(); i++) { u32 tid = new_tids[i]; - registry->StartThread(tid, 0, 0); + registry->StartThread(tid, 0, false, 0); registry->DetachThread(tid, 0); registry->FinishThread(tid); } @@ -189,7 +189,7 @@ void *RunThread(void *arg) { tids.push_back( args->registry->CreateThread(0, false, 0, (void*)args->shard)); for (int i = 0; i < kThreadsPerShard; i++) - args->registry->StartThread(tids[i], 0, (void*)args->shard); + args->registry->StartThread(tids[i], 0, false, (void*)args->shard); for (int i = 0; i < kThreadsPerShard; i++) args->registry->FinishThread(tids[i]); for (int i = 0; i < kThreadsPerShard; i++) @@ -200,7 +200,7 @@ void *RunThread(void *arg) { static void ThreadedTestRegistry(ThreadRegistry *registry) { // Create and start a main thread. EXPECT_EQ(0U, registry->CreateThread(0, true, -1, 0)); - registry->StartThread(0, 0, 0); + registry->StartThread(0, 0, false, 0); pthread_t threads[kNumShards]; RunThreadArgs args[kNumShards]; for (int i = 0; i < kNumShards; i++) { |