xref: /llvm-project/llvm/unittests/ADT/DenseMapTest.cpp (revision 9e932e08a8300f3366ace04ba8fda4946db406b9)
1 //===- llvm/unittest/ADT/DenseMapMap.cpp - DenseMap unit tests --*- C++ -*-===//
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 "llvm/ADT/DenseMap.h"
10 #include "llvm/ADT/DenseMapInfo.h"
11 #include "gmock/gmock.h"
12 #include "gtest/gtest.h"
13 #include <map>
14 #include <set>
15 #include <utility>
16 #include <variant>
17 
18 using namespace llvm;
19 
20 namespace {
21 
22 uint32_t getTestKey(int i, uint32_t *) { return i; }
23 uint32_t getTestValue(int i, uint32_t *) { return 42 + i; }
24 
25 uint32_t *getTestKey(int i, uint32_t **) {
26   static uint32_t dummy_arr1[8192];
27   assert(i < 8192 && "Only support 8192 dummy keys.");
28   return &dummy_arr1[i];
29 }
30 uint32_t *getTestValue(int i, uint32_t **) {
31   static uint32_t dummy_arr1[8192];
32   assert(i < 8192 && "Only support 8192 dummy keys.");
33   return &dummy_arr1[i];
34 }
35 
36 /// A test class that tries to check that construction and destruction
37 /// occur correctly.
38 class CtorTester {
39   static std::set<CtorTester *> Constructed;
40   int Value;
41 
42 public:
43   explicit CtorTester(int Value = 0) : Value(Value) {
44     EXPECT_TRUE(Constructed.insert(this).second);
45   }
46   CtorTester(uint32_t Value) : Value(Value) {
47     EXPECT_TRUE(Constructed.insert(this).second);
48   }
49   CtorTester(const CtorTester &Arg) : Value(Arg.Value) {
50     EXPECT_TRUE(Constructed.insert(this).second);
51   }
52   CtorTester &operator=(const CtorTester &) = default;
53   ~CtorTester() {
54     EXPECT_EQ(1u, Constructed.erase(this));
55   }
56   operator uint32_t() const { return Value; }
57 
58   int getValue() const { return Value; }
59   bool operator==(const CtorTester &RHS) const { return Value == RHS.Value; }
60 };
61 
62 std::set<CtorTester *> CtorTester::Constructed;
63 
64 struct CtorTesterMapInfo {
65   static inline CtorTester getEmptyKey() { return CtorTester(-1); }
66   static inline CtorTester getTombstoneKey() { return CtorTester(-2); }
67   static unsigned getHashValue(const CtorTester &Val) {
68     return Val.getValue() * 37u;
69   }
70   static bool isEqual(const CtorTester &LHS, const CtorTester &RHS) {
71     return LHS == RHS;
72   }
73 };
74 
75 CtorTester getTestKey(int i, CtorTester *) { return CtorTester(i); }
76 CtorTester getTestValue(int i, CtorTester *) { return CtorTester(42 + i); }
77 
78 // Test fixture, with helper functions implemented by forwarding to global
79 // function overloads selected by component types of the type parameter. This
80 // allows all of the map implementations to be tested with shared
81 // implementations of helper routines.
82 template <typename T>
83 class DenseMapTest : public ::testing::Test {
84 protected:
85   T Map;
86 
87   static typename T::key_type *const dummy_key_ptr;
88   static typename T::mapped_type *const dummy_value_ptr;
89 
90   typename T::key_type getKey(int i = 0) {
91     return getTestKey(i, dummy_key_ptr);
92   }
93   typename T::mapped_type getValue(int i = 0) {
94     return getTestValue(i, dummy_value_ptr);
95   }
96 };
97 
98 template <typename T>
99 typename T::key_type *const DenseMapTest<T>::dummy_key_ptr = nullptr;
100 template <typename T>
101 typename T::mapped_type *const DenseMapTest<T>::dummy_value_ptr = nullptr;
102 
103 // Register these types for testing.
104 typedef ::testing::Types<DenseMap<uint32_t, uint32_t>,
105                          DenseMap<uint32_t *, uint32_t *>,
106                          DenseMap<CtorTester, CtorTester, CtorTesterMapInfo>,
107                          SmallDenseMap<uint32_t, uint32_t>,
108                          SmallDenseMap<uint32_t *, uint32_t *>,
109                          SmallDenseMap<CtorTester, CtorTester, 4,
110                                        CtorTesterMapInfo>
111                          > DenseMapTestTypes;
112 TYPED_TEST_SUITE(DenseMapTest, DenseMapTestTypes, );
113 
114 // Empty map tests
115 TYPED_TEST(DenseMapTest, EmptyIntMapTest) {
116   // Size tests
117   EXPECT_EQ(0u, this->Map.size());
118   EXPECT_TRUE(this->Map.empty());
119 
120   // Iterator tests
121   EXPECT_TRUE(this->Map.begin() == this->Map.end());
122 
123   // Lookup tests
124   EXPECT_FALSE(this->Map.count(this->getKey()));
125   EXPECT_FALSE(this->Map.contains(this->getKey()));
126   EXPECT_TRUE(this->Map.find(this->getKey()) == this->Map.end());
127   EXPECT_EQ(typename TypeParam::mapped_type(),
128             this->Map.lookup(this->getKey()));
129 }
130 
131 // Constant map tests
132 TYPED_TEST(DenseMapTest, ConstEmptyMapTest) {
133   const TypeParam &ConstMap = this->Map;
134   EXPECT_EQ(0u, ConstMap.size());
135   EXPECT_TRUE(ConstMap.empty());
136   EXPECT_TRUE(ConstMap.begin() == ConstMap.end());
137 }
138 
139 // A map with a single entry
140 TYPED_TEST(DenseMapTest, SingleEntryMapTest) {
141   this->Map[this->getKey()] = this->getValue();
142 
143   // Size tests
144   EXPECT_EQ(1u, this->Map.size());
145   EXPECT_FALSE(this->Map.begin() == this->Map.end());
146   EXPECT_FALSE(this->Map.empty());
147 
148   // Iterator tests
149   typename TypeParam::iterator it = this->Map.begin();
150   EXPECT_EQ(this->getKey(), it->first);
151   EXPECT_EQ(this->getValue(), it->second);
152   ++it;
153   EXPECT_TRUE(it == this->Map.end());
154 
155   // Lookup tests
156   EXPECT_TRUE(this->Map.count(this->getKey()));
157   EXPECT_TRUE(this->Map.contains(this->getKey()));
158   EXPECT_TRUE(this->Map.find(this->getKey()) == this->Map.begin());
159   EXPECT_EQ(this->getValue(), this->Map.lookup(this->getKey()));
160   EXPECT_EQ(this->getValue(), this->Map[this->getKey()]);
161 }
162 
163 TYPED_TEST(DenseMapTest, AtTest) {
164   this->Map[this->getKey(0)] = this->getValue(0);
165   this->Map[this->getKey(1)] = this->getValue(1);
166   this->Map[this->getKey(2)] = this->getValue(2);
167   EXPECT_EQ(this->getValue(0), this->Map.at(this->getKey(0)));
168   EXPECT_EQ(this->getValue(1), this->Map.at(this->getKey(1)));
169   EXPECT_EQ(this->getValue(2), this->Map.at(this->getKey(2)));
170 }
171 
172 // Test clear() method
173 TYPED_TEST(DenseMapTest, ClearTest) {
174   this->Map[this->getKey()] = this->getValue();
175   this->Map.clear();
176 
177   EXPECT_EQ(0u, this->Map.size());
178   EXPECT_TRUE(this->Map.empty());
179   EXPECT_TRUE(this->Map.begin() == this->Map.end());
180 }
181 
182 // Test erase(iterator) method
183 TYPED_TEST(DenseMapTest, EraseTest) {
184   this->Map[this->getKey()] = this->getValue();
185   this->Map.erase(this->Map.begin());
186 
187   EXPECT_EQ(0u, this->Map.size());
188   EXPECT_TRUE(this->Map.empty());
189   EXPECT_TRUE(this->Map.begin() == this->Map.end());
190 }
191 
192 // Test erase(value) method
193 TYPED_TEST(DenseMapTest, EraseTest2) {
194   this->Map[this->getKey()] = this->getValue();
195   this->Map.erase(this->getKey());
196 
197   EXPECT_EQ(0u, this->Map.size());
198   EXPECT_TRUE(this->Map.empty());
199   EXPECT_TRUE(this->Map.begin() == this->Map.end());
200 }
201 
202 // Test insert() method
203 TYPED_TEST(DenseMapTest, InsertTest) {
204   this->Map.insert(std::make_pair(this->getKey(), this->getValue()));
205   EXPECT_EQ(1u, this->Map.size());
206   EXPECT_EQ(this->getValue(), this->Map[this->getKey()]);
207 }
208 
209 // Test copy constructor method
210 TYPED_TEST(DenseMapTest, CopyConstructorTest) {
211   this->Map[this->getKey()] = this->getValue();
212   TypeParam copyMap(this->Map);
213 
214   EXPECT_EQ(1u, copyMap.size());
215   EXPECT_EQ(this->getValue(), copyMap[this->getKey()]);
216 }
217 
218 // Test copy constructor method where SmallDenseMap isn't small.
219 TYPED_TEST(DenseMapTest, CopyConstructorNotSmallTest) {
220   for (int Key = 0; Key < 5; ++Key)
221     this->Map[this->getKey(Key)] = this->getValue(Key);
222   TypeParam copyMap(this->Map);
223 
224   EXPECT_EQ(5u, copyMap.size());
225   for (int Key = 0; Key < 5; ++Key)
226     EXPECT_EQ(this->getValue(Key), copyMap[this->getKey(Key)]);
227 }
228 
229 // Test copying from a default-constructed map.
230 TYPED_TEST(DenseMapTest, CopyConstructorFromDefaultTest) {
231   TypeParam copyMap(this->Map);
232 
233   EXPECT_TRUE(copyMap.empty());
234 }
235 
236 // Test copying from an empty map where SmallDenseMap isn't small.
237 TYPED_TEST(DenseMapTest, CopyConstructorFromEmptyTest) {
238   for (int Key = 0; Key < 5; ++Key)
239     this->Map[this->getKey(Key)] = this->getValue(Key);
240   this->Map.clear();
241   TypeParam copyMap(this->Map);
242 
243   EXPECT_TRUE(copyMap.empty());
244 }
245 
246 // Test assignment operator method
247 TYPED_TEST(DenseMapTest, AssignmentTest) {
248   this->Map[this->getKey()] = this->getValue();
249   TypeParam copyMap = this->Map;
250 
251   EXPECT_EQ(1u, copyMap.size());
252   EXPECT_EQ(this->getValue(), copyMap[this->getKey()]);
253 
254   // test self-assignment.
255   copyMap = static_cast<TypeParam &>(copyMap);
256   EXPECT_EQ(1u, copyMap.size());
257   EXPECT_EQ(this->getValue(), copyMap[this->getKey()]);
258 }
259 
260 TYPED_TEST(DenseMapTest, AssignmentTestNotSmall) {
261   for (int Key = 0; Key < 5; ++Key)
262     this->Map[this->getKey(Key)] = this->getValue(Key);
263   TypeParam copyMap = this->Map;
264 
265   EXPECT_EQ(5u, copyMap.size());
266   for (int Key = 0; Key < 5; ++Key)
267     EXPECT_EQ(this->getValue(Key), copyMap[this->getKey(Key)]);
268 
269   // test self-assignment.
270   copyMap = static_cast<TypeParam &>(copyMap);
271   EXPECT_EQ(5u, copyMap.size());
272   for (int Key = 0; Key < 5; ++Key)
273     EXPECT_EQ(this->getValue(Key), copyMap[this->getKey(Key)]);
274 }
275 
276 // Test swap method
277 TYPED_TEST(DenseMapTest, SwapTest) {
278   this->Map[this->getKey()] = this->getValue();
279   TypeParam otherMap;
280 
281   this->Map.swap(otherMap);
282   EXPECT_EQ(0u, this->Map.size());
283   EXPECT_TRUE(this->Map.empty());
284   EXPECT_EQ(1u, otherMap.size());
285   EXPECT_EQ(this->getValue(), otherMap[this->getKey()]);
286 
287   this->Map.swap(otherMap);
288   EXPECT_EQ(0u, otherMap.size());
289   EXPECT_TRUE(otherMap.empty());
290   EXPECT_EQ(1u, this->Map.size());
291   EXPECT_EQ(this->getValue(), this->Map[this->getKey()]);
292 
293   // Make this more interesting by inserting 100 numbers into the map.
294   for (int i = 0; i < 100; ++i)
295     this->Map[this->getKey(i)] = this->getValue(i);
296 
297   this->Map.swap(otherMap);
298   EXPECT_EQ(0u, this->Map.size());
299   EXPECT_TRUE(this->Map.empty());
300   EXPECT_EQ(100u, otherMap.size());
301   for (int i = 0; i < 100; ++i)
302     EXPECT_EQ(this->getValue(i), otherMap[this->getKey(i)]);
303 
304   this->Map.swap(otherMap);
305   EXPECT_EQ(0u, otherMap.size());
306   EXPECT_TRUE(otherMap.empty());
307   EXPECT_EQ(100u, this->Map.size());
308   for (int i = 0; i < 100; ++i)
309     EXPECT_EQ(this->getValue(i), this->Map[this->getKey(i)]);
310 }
311 
312 // A more complex iteration test
313 TYPED_TEST(DenseMapTest, IterationTest) {
314   bool visited[100];
315   std::map<typename TypeParam::key_type, unsigned> visitedIndex;
316 
317   // Insert 100 numbers into the map
318   for (int i = 0; i < 100; ++i) {
319     visited[i] = false;
320     visitedIndex[this->getKey(i)] = i;
321 
322     this->Map[this->getKey(i)] = this->getValue(i);
323   }
324 
325   // Iterate over all numbers and mark each one found.
326   for (typename TypeParam::iterator it = this->Map.begin();
327        it != this->Map.end(); ++it)
328     visited[visitedIndex[it->first]] = true;
329 
330   // Ensure every number was visited.
331   for (int i = 0; i < 100; ++i)
332     ASSERT_TRUE(visited[i]) << "Entry #" << i << " was never visited";
333 }
334 
335 // const_iterator test
336 TYPED_TEST(DenseMapTest, ConstIteratorTest) {
337   // Check conversion from iterator to const_iterator.
338   typename TypeParam::iterator it = this->Map.begin();
339   typename TypeParam::const_iterator cit(it);
340   EXPECT_TRUE(it == cit);
341 
342   // Check copying of const_iterators.
343   typename TypeParam::const_iterator cit2(cit);
344   EXPECT_TRUE(cit == cit2);
345 }
346 
347 namespace {
348 // Simple class that counts how many moves and copy happens when growing a map
349 struct CountCopyAndMove {
350   static int Move;
351   static int Copy;
352   CountCopyAndMove() {}
353 
354   CountCopyAndMove(const CountCopyAndMove &) { Copy++; }
355   CountCopyAndMove &operator=(const CountCopyAndMove &) {
356     Copy++;
357     return *this;
358   }
359   CountCopyAndMove(CountCopyAndMove &&) { Move++; }
360   CountCopyAndMove &operator=(const CountCopyAndMove &&) {
361     Move++;
362     return *this;
363   }
364 };
365 int CountCopyAndMove::Copy = 0;
366 int CountCopyAndMove::Move = 0;
367 
368 } // anonymous namespace
369 
370 // Test initializer list construction.
371 TEST(DenseMapCustomTest, InitializerList) {
372   DenseMap<int, int> M({{0, 0}, {0, 1}, {1, 2}});
373   EXPECT_EQ(2u, M.size());
374   EXPECT_EQ(1u, M.count(0));
375   EXPECT_EQ(0, M[0]);
376   EXPECT_EQ(1u, M.count(1));
377   EXPECT_EQ(2, M[1]);
378 }
379 
380 // Test initializer list construction.
381 TEST(DenseMapCustomTest, EqualityComparison) {
382   DenseMap<int, int> M1({{0, 0}, {1, 2}});
383   DenseMap<int, int> M2({{0, 0}, {1, 2}});
384   DenseMap<int, int> M3({{0, 0}, {1, 3}});
385 
386   EXPECT_EQ(M1, M2);
387   EXPECT_NE(M1, M3);
388 }
389 
390 // Test for the default minimum size of a DenseMap
391 TEST(DenseMapCustomTest, DefaultMinReservedSizeTest) {
392   // IF THIS VALUE CHANGE, please update InitialSizeTest, InitFromIterator, and
393   // ReserveTest as well!
394   const int ExpectedInitialBucketCount = 64;
395   // Formula from DenseMap::getMinBucketToReserveForEntries()
396   const int ExpectedMaxInitialEntries = ExpectedInitialBucketCount * 3 / 4 - 1;
397 
398   DenseMap<int, CountCopyAndMove> Map;
399   // Will allocate 64 buckets
400   Map.reserve(1);
401   unsigned MemorySize = Map.getMemorySize();
402   CountCopyAndMove::Copy = 0;
403   CountCopyAndMove::Move = 0;
404   for (int i = 0; i < ExpectedMaxInitialEntries; ++i)
405     Map.insert(std::pair<int, CountCopyAndMove>(std::piecewise_construct,
406                                                 std::forward_as_tuple(i),
407                                                 std::forward_as_tuple()));
408   // Check that we didn't grow
409   EXPECT_EQ(MemorySize, Map.getMemorySize());
410   // Check that move was called the expected number of times
411   EXPECT_EQ(ExpectedMaxInitialEntries, CountCopyAndMove::Move);
412   // Check that no copy occurred
413   EXPECT_EQ(0, CountCopyAndMove::Copy);
414 
415   // Adding one extra element should grow the map
416   Map.insert(std::pair<int, CountCopyAndMove>(
417       std::piecewise_construct,
418       std::forward_as_tuple(ExpectedMaxInitialEntries),
419       std::forward_as_tuple()));
420   // Check that we grew
421   EXPECT_NE(MemorySize, Map.getMemorySize());
422   // Check that move was called the expected number of times
423   //  This relies on move-construction elision, and cannot be reliably tested.
424   //   EXPECT_EQ(ExpectedMaxInitialEntries + 2, CountCopyAndMove::Move);
425   // Check that no copy occurred
426   EXPECT_EQ(0, CountCopyAndMove::Copy);
427 }
428 
429 // Make sure creating the map with an initial size of N actually gives us enough
430 // buckets to insert N items without increasing allocation size.
431 TEST(DenseMapCustomTest, InitialSizeTest) {
432   // Test a few different sizes, 48 is *not* a random choice: we need a value
433   // that is 2/3 of a power of two to stress the grow() condition, and the power
434   // of two has to be at least 64 because of minimum size allocation in the
435   // DenseMap (see DefaultMinReservedSizeTest). 66 is a value just above the
436   // 64 default init.
437   for (auto Size : {1, 2, 48, 66}) {
438     DenseMap<int, CountCopyAndMove> Map(Size);
439     unsigned MemorySize = Map.getMemorySize();
440     CountCopyAndMove::Copy = 0;
441     CountCopyAndMove::Move = 0;
442     for (int i = 0; i < Size; ++i)
443       Map.insert(std::pair<int, CountCopyAndMove>(std::piecewise_construct,
444                                                   std::forward_as_tuple(i),
445                                                   std::forward_as_tuple()));
446     // Check that we didn't grow
447     EXPECT_EQ(MemorySize, Map.getMemorySize());
448     // Check that move was called the expected number of times
449     EXPECT_EQ(Size, CountCopyAndMove::Move);
450     // Check that no copy occurred
451     EXPECT_EQ(0, CountCopyAndMove::Copy);
452   }
453 }
454 
455 // Make sure creating the map with a iterator range does not trigger grow()
456 TEST(DenseMapCustomTest, InitFromIterator) {
457   std::vector<std::pair<int, CountCopyAndMove>> Values;
458   // The size is a random value greater than 64 (hardcoded DenseMap min init)
459   const int Count = 65;
460   Values.reserve(Count);
461   for (int i = 0; i < Count; i++)
462     Values.emplace_back(i, CountCopyAndMove());
463 
464   CountCopyAndMove::Move = 0;
465   CountCopyAndMove::Copy = 0;
466   DenseMap<int, CountCopyAndMove> Map(Values.begin(), Values.end());
467   // Check that no move occurred
468   EXPECT_EQ(0, CountCopyAndMove::Move);
469   // Check that copy was called the expected number of times
470   EXPECT_EQ(Count, CountCopyAndMove::Copy);
471 }
472 
473 // Make sure reserve actually gives us enough buckets to insert N items
474 // without increasing allocation size.
475 TEST(DenseMapCustomTest, ReserveTest) {
476   // Test a few different size, 48 is *not* a random choice: we need a value
477   // that is 2/3 of a power of two to stress the grow() condition, and the power
478   // of two has to be at least 64 because of minimum size allocation in the
479   // DenseMap (see DefaultMinReservedSizeTest). 66 is a value just above the
480   // 64 default init.
481   for (auto Size : {1, 2, 48, 66}) {
482     DenseMap<int, CountCopyAndMove> Map;
483     Map.reserve(Size);
484     unsigned MemorySize = Map.getMemorySize();
485     CountCopyAndMove::Copy = 0;
486     CountCopyAndMove::Move = 0;
487     for (int i = 0; i < Size; ++i)
488       Map.insert(std::pair<int, CountCopyAndMove>(std::piecewise_construct,
489                                                   std::forward_as_tuple(i),
490                                                   std::forward_as_tuple()));
491     // Check that we didn't grow
492     EXPECT_EQ(MemorySize, Map.getMemorySize());
493     // Check that move was called the expected number of times
494     EXPECT_EQ(Size, CountCopyAndMove::Move);
495     // Check that no copy occurred
496     EXPECT_EQ(0, CountCopyAndMove::Copy);
497   }
498 }
499 
500 // Make sure DenseMap works with StringRef keys.
501 TEST(DenseMapCustomTest, StringRefTest) {
502   DenseMap<StringRef, int> M;
503 
504   M["a"] = 1;
505   M["b"] = 2;
506   M["c"] = 3;
507 
508   EXPECT_EQ(3u, M.size());
509   EXPECT_EQ(1, M.lookup("a"));
510   EXPECT_EQ(2, M.lookup("b"));
511   EXPECT_EQ(3, M.lookup("c"));
512 
513   EXPECT_EQ(0, M.lookup("q"));
514 
515   // Test the empty string, spelled various ways.
516   EXPECT_EQ(0, M.lookup(""));
517   EXPECT_EQ(0, M.lookup(StringRef()));
518   EXPECT_EQ(0, M.lookup(StringRef("a", 0)));
519   M[""] = 42;
520   EXPECT_EQ(42, M.lookup(""));
521   EXPECT_EQ(42, M.lookup(StringRef()));
522   EXPECT_EQ(42, M.lookup(StringRef("a", 0)));
523 }
524 
525 // Key traits that allows lookup with either an unsigned or char* key;
526 // In the latter case, "a" == 0, "b" == 1 and so on.
527 struct TestDenseMapInfo {
528   static inline unsigned getEmptyKey() { return ~0; }
529   static inline unsigned getTombstoneKey() { return ~0U - 1; }
530   static unsigned getHashValue(const unsigned& Val) { return Val * 37U; }
531   static unsigned getHashValue(const char* Val) {
532     return (unsigned)(Val[0] - 'a') * 37U;
533   }
534   static bool isEqual(const unsigned& LHS, const unsigned& RHS) {
535     return LHS == RHS;
536   }
537   static bool isEqual(const char* LHS, const unsigned& RHS) {
538     return (unsigned)(LHS[0] - 'a') == RHS;
539   }
540 };
541 
542 // find_as() tests
543 TEST(DenseMapCustomTest, FindAsTest) {
544   DenseMap<unsigned, unsigned, TestDenseMapInfo> map;
545   map[0] = 1;
546   map[1] = 2;
547   map[2] = 3;
548 
549   // Size tests
550   EXPECT_EQ(3u, map.size());
551 
552   // Normal lookup tests
553   EXPECT_EQ(1u, map.count(1));
554   EXPECT_EQ(1u, map.find(0)->second);
555   EXPECT_EQ(2u, map.find(1)->second);
556   EXPECT_EQ(3u, map.find(2)->second);
557   EXPECT_TRUE(map.find(3) == map.end());
558 
559   // find_as() tests
560   EXPECT_EQ(1u, map.find_as("a")->second);
561   EXPECT_EQ(2u, map.find_as("b")->second);
562   EXPECT_EQ(3u, map.find_as("c")->second);
563   EXPECT_TRUE(map.find_as("d") == map.end());
564 }
565 
566 TEST(DenseMapCustomTest, SmallDenseMapInitializerList) {
567   SmallDenseMap<int, int> M = {{0, 0}, {0, 1}, {1, 2}};
568   EXPECT_EQ(2u, M.size());
569   EXPECT_EQ(1u, M.count(0));
570   EXPECT_EQ(0, M[0]);
571   EXPECT_EQ(1u, M.count(1));
572   EXPECT_EQ(2, M[1]);
573 }
574 
575 struct ContiguousDenseMapInfo {
576   static inline unsigned getEmptyKey() { return ~0; }
577   static inline unsigned getTombstoneKey() { return ~0U - 1; }
578   static unsigned getHashValue(const unsigned& Val) { return Val; }
579   static bool isEqual(const unsigned& LHS, const unsigned& RHS) {
580     return LHS == RHS;
581   }
582 };
583 
584 // Test that filling a small dense map with exactly the number of elements in
585 // the map grows to have enough space for an empty bucket.
586 TEST(DenseMapCustomTest, SmallDenseMapGrowTest) {
587   SmallDenseMap<unsigned, unsigned, 32, ContiguousDenseMapInfo> map;
588   // Add some number of elements, then delete a few to leave us some tombstones.
589   // If we just filled the map with 32 elements we'd grow because of not enough
590   // tombstones which masks the issue here.
591   for (unsigned i = 0; i < 20; ++i)
592     map[i] = i + 1;
593   for (unsigned i = 0; i < 10; ++i)
594     map.erase(i);
595   for (unsigned i = 20; i < 32; ++i)
596     map[i] = i + 1;
597 
598   // Size tests
599   EXPECT_EQ(22u, map.size());
600 
601   // Try to find an element which doesn't exist.  There was a bug in
602   // SmallDenseMap which led to a map with num elements == small capacity not
603   // having an empty bucket any more.  Finding an element not in the map would
604   // therefore never terminate.
605   EXPECT_TRUE(map.find(32) == map.end());
606 }
607 
608 TEST(DenseMapCustomTest, LargeSmallDenseMapCompaction) {
609   SmallDenseMap<unsigned, unsigned, 128, ContiguousDenseMapInfo> map;
610   // Fill to < 3/4 load.
611   for (unsigned i = 0; i < 95; ++i)
612     map[i] = i;
613   // And erase, leaving behind tombstones.
614   for (unsigned i = 0; i < 95; ++i)
615     map.erase(i);
616   // Fill further, so that less than 1/8 are empty, but still below 3/4 load.
617   for (unsigned i = 95; i < 128; ++i)
618     map[i] = i;
619 
620   EXPECT_EQ(33u, map.size());
621   // Similar to the previous test, check for a non-existing element, as an
622   // indirect check that tombstones have been removed.
623   EXPECT_TRUE(map.find(0) == map.end());
624 }
625 
626 TEST(DenseMapCustomTest, SmallDenseMapWithNumBucketsNonPowerOf2) {
627   // Is not power of 2.
628   const unsigned NumInitBuckets = 33;
629   // Power of 2 less then NumInitBuckets.
630   constexpr unsigned InlineBuckets = 4;
631   // Constructor should not trigger assert.
632   SmallDenseMap<int, int, InlineBuckets> map(NumInitBuckets);
633 }
634 
635 TEST(DenseMapCustomTest, TryEmplaceTest) {
636   DenseMap<int, std::unique_ptr<int>> Map;
637   std::unique_ptr<int> P(new int(2));
638   auto Try1 = Map.try_emplace(0, new int(1));
639   EXPECT_TRUE(Try1.second);
640   auto Try2 = Map.try_emplace(0, std::move(P));
641   EXPECT_FALSE(Try2.second);
642   EXPECT_EQ(Try1.first, Try2.first);
643   EXPECT_NE(nullptr, P);
644 }
645 
646 TEST(DenseMapCustomTest, ConstTest) {
647   // Test that const pointers work okay for count and find, even when the
648   // underlying map is a non-const pointer.
649   DenseMap<int *, int> Map;
650   int A;
651   int *B = &A;
652   const int *C = &A;
653   Map.insert({B, 0});
654   EXPECT_EQ(Map.count(B), 1u);
655   EXPECT_EQ(Map.count(C), 1u);
656   EXPECT_NE(Map.find(B), Map.end());
657   EXPECT_NE(Map.find(C), Map.end());
658 }
659 
660 struct IncompleteStruct;
661 
662 TEST(DenseMapCustomTest, OpaquePointerKey) {
663   // Test that we can use a pointer to an incomplete type as a DenseMap key.
664   // This is an important build time optimization, since many classes have
665   // DenseMap members.
666   DenseMap<IncompleteStruct *, int> Map;
667   int Keys[3] = {0, 0, 0};
668   IncompleteStruct *K1 = reinterpret_cast<IncompleteStruct *>(&Keys[0]);
669   IncompleteStruct *K2 = reinterpret_cast<IncompleteStruct *>(&Keys[1]);
670   IncompleteStruct *K3 = reinterpret_cast<IncompleteStruct *>(&Keys[2]);
671   Map.insert({K1, 1});
672   Map.insert({K2, 2});
673   Map.insert({K3, 3});
674   EXPECT_EQ(Map.count(K1), 1u);
675   EXPECT_EQ(Map[K1], 1);
676   EXPECT_EQ(Map[K2], 2);
677   EXPECT_EQ(Map[K3], 3);
678   Map.clear();
679   EXPECT_EQ(Map.find(K1), Map.end());
680   EXPECT_EQ(Map.find(K2), Map.end());
681   EXPECT_EQ(Map.find(K3), Map.end());
682 }
683 } // namespace
684 
685 namespace {
686 struct A {
687   A(int value) : value(value) {}
688   int value;
689 };
690 struct B : public A {
691   using A::A;
692 };
693 
694 struct AlwaysEqType {
695   bool operator==(const AlwaysEqType &RHS) const { return true; }
696 };
697 } // namespace
698 
699 namespace llvm {
700 template <typename T>
701 struct DenseMapInfo<T, std::enable_if_t<std::is_base_of_v<A, T>>> {
702   static inline T getEmptyKey() { return {static_cast<int>(~0)}; }
703   static inline T getTombstoneKey() { return {static_cast<int>(~0U - 1)}; }
704   static unsigned getHashValue(const T &Val) { return Val.value; }
705   static bool isEqual(const T &LHS, const T &RHS) {
706     return LHS.value == RHS.value;
707   }
708 };
709 
710 template <> struct DenseMapInfo<AlwaysEqType> {
711   using T = AlwaysEqType;
712   static inline T getEmptyKey() { return {}; }
713   static inline T getTombstoneKey() { return {}; }
714   static unsigned getHashValue(const T &Val) { return 0; }
715   static bool isEqual(const T &LHS, const T &RHS) {
716     return false;
717   }
718 };
719 } // namespace llvm
720 
721 namespace {
722 TEST(DenseMapCustomTest, SFINAEMapInfo) {
723   // Test that we can use a pointer to an incomplete type as a DenseMap key.
724   // This is an important build time optimization, since many classes have
725   // DenseMap members.
726   DenseMap<B, int> Map;
727   B Keys[3] = {{0}, {1}, {2}};
728   Map.insert({Keys[0], 1});
729   Map.insert({Keys[1], 2});
730   Map.insert({Keys[2], 3});
731   EXPECT_EQ(Map.count(Keys[0]), 1u);
732   EXPECT_EQ(Map[Keys[0]], 1);
733   EXPECT_EQ(Map[Keys[1]], 2);
734   EXPECT_EQ(Map[Keys[2]], 3);
735   Map.clear();
736   EXPECT_EQ(Map.find(Keys[0]), Map.end());
737   EXPECT_EQ(Map.find(Keys[1]), Map.end());
738   EXPECT_EQ(Map.find(Keys[2]), Map.end());
739 }
740 
741 TEST(DenseMapCustomTest, VariantSupport) {
742   using variant = std::variant<int, int, AlwaysEqType>;
743   DenseMap<variant, int> Map;
744   variant Keys[] = {
745       variant(std::in_place_index<0>, 1),
746       variant(std::in_place_index<1>, 1),
747       variant(std::in_place_index<2>),
748   };
749   Map.try_emplace(Keys[0], 0);
750   Map.try_emplace(Keys[1], 1);
751   EXPECT_THAT(Map, testing::SizeIs(2));
752   EXPECT_NE(DenseMapInfo<variant>::getHashValue(Keys[0]),
753             DenseMapInfo<variant>::getHashValue(Keys[1]));
754   // Check that isEqual dispatches to isEqual of underlying type, and not to
755   // operator==.
756   EXPECT_FALSE(DenseMapInfo<variant>::isEqual(Keys[2], Keys[2]));
757 }
758 } // namespace
759