1 //===-- sanitizer_flat_map_test.cpp ---------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "sanitizer_common/sanitizer_flat_map.h" 10 11 #include "gtest/gtest.h" 12 #include "sanitizer_common/tests/sanitizer_pthread_wrappers.h" 13 14 using namespace __sanitizer; 15 16 namespace { 17 struct TestMapUnmapCallback1 { 18 static int map_count, unmap_count; 19 void OnMap(uptr p, uptr size) const { map_count++; } 20 void OnUnmap(uptr p, uptr size) const { unmap_count++; } 21 }; 22 int TestMapUnmapCallback1::map_count; 23 int TestMapUnmapCallback1::unmap_count; 24 25 struct TestStruct { 26 int data[125] = {}; 27 TestStruct(uptr v = 0) { data[11] = v; } 28 bool operator==(const TestStruct &other) const { 29 return 0 == memcmp(data, other.data, sizeof(data)); 30 } 31 }; 32 33 template <typename T> 34 class FlatMapTest : public ::testing::Test {}; 35 36 using FlatMapTestTypes = ::testing::Types<u8, u64, TestStruct>; 37 TYPED_TEST_SUITE(FlatMapTest, FlatMapTestTypes, ); 38 39 TYPED_TEST(FlatMapTest, TwoLevelByteMap) { 40 const u64 kSize1 = 1 << 6, kSize2 = 1 << 12; 41 const u64 n = kSize1 * kSize2; 42 TwoLevelMap<TypeParam, kSize1, kSize2> m; 43 m.Init(); 44 45 m[7] = {10}; 46 for (u64 i = 0; i < kSize2; ++i) { 47 EXPECT_TRUE(m.contains(i)); 48 } 49 EXPECT_FALSE(m.contains(kSize2)); 50 51 for (u64 i = 0; i < n; i += 7) { 52 m[i] = TypeParam((i % 100) + 1); 53 } 54 for (u64 j = 0; j < n; j++) { 55 EXPECT_TRUE(m.contains(j)); 56 if (j % 7) 57 EXPECT_EQ(m[j], TypeParam()); 58 else 59 EXPECT_EQ(m[j], TypeParam((j % 100) + 1)); 60 } 61 62 m.TestOnlyUnmap(); 63 } 64 65 template <typename TypeParam, typename AddressSpaceView> 66 using TestMapASVT = TwoLevelMap<TypeParam, 1 << 8, 1 << 7, AddressSpaceView, 67 TestMapUnmapCallback1>; 68 template <typename TypeParam> 69 using TestMap = TestMapASVT<TypeParam, LocalAddressSpaceView>; 70 71 template <typename TypeParam> 72 struct TestMapParam { 73 TestMap<TypeParam> *m; 74 size_t shard; 75 size_t num_shards; 76 }; 77 78 template <typename TypeParam> 79 static void *TwoLevelMapUserThread(void *param) { 80 TestMapParam<TypeParam> *p = (TestMapParam<TypeParam> *)param; 81 for (size_t i = p->shard; i < p->m->size(); i += p->num_shards) { 82 TypeParam val = (i % 100) + 1; 83 (*p->m)[i] = val; 84 EXPECT_EQ((*p->m)[i], val); 85 } 86 return 0; 87 } 88 89 TYPED_TEST(FlatMapTest, ThreadedTwoLevelByteMap) { 90 TestMap<TypeParam> m; 91 m.Init(); 92 TestMapUnmapCallback1::map_count = 0; 93 TestMapUnmapCallback1::unmap_count = 0; 94 static const int kNumThreads = 4; 95 pthread_t t[kNumThreads]; 96 TestMapParam<TypeParam> p[kNumThreads]; 97 for (int i = 0; i < kNumThreads; i++) { 98 p[i].m = &m; 99 p[i].shard = i; 100 p[i].num_shards = kNumThreads; 101 PTHREAD_CREATE(&t[i], 0, TwoLevelMapUserThread<TypeParam>, &p[i]); 102 } 103 for (int i = 0; i < kNumThreads; i++) { 104 PTHREAD_JOIN(t[i], 0); 105 } 106 EXPECT_EQ((uptr)TestMapUnmapCallback1::map_count, m.size1()); 107 EXPECT_EQ((uptr)TestMapUnmapCallback1::unmap_count, 0UL); 108 m.TestOnlyUnmap(); 109 EXPECT_EQ((uptr)TestMapUnmapCallback1::map_count, m.size1()); 110 EXPECT_EQ((uptr)TestMapUnmapCallback1::unmap_count, m.size1()); 111 } 112 113 } // namespace 114