xref: /llvm-project/llvm/unittests/ADT/StringMapTest.cpp (revision 132003603ae3453bc385ffd5ed53f5e8057ae1bc)
1 //===- llvm/unittest/ADT/StringMapMap.cpp - StringMap unit tests ----------===//
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/StringMap.h"
10 #include "llvm/ADT/STLExtras.h"
11 #include "llvm/ADT/Twine.h"
12 #include "llvm/Support/DataTypes.h"
13 #include "gtest/gtest.h"
14 #include <limits>
15 #include <tuple>
16 using namespace llvm;
17 
18 namespace {
19 
20 static_assert(sizeof(StringMap<uint32_t>) <
21                   sizeof(StringMap<uint32_t, MallocAllocator &>),
22               "Ensure empty base optimization happens with default allocator");
23 
24 // Test fixture
25 class StringMapTest : public testing::Test {
26 protected:
27   StringMap<uint32_t> testMap;
28 
29   static const char testKey[];
30   static const uint32_t testValue;
31   static const char *testKeyFirst;
32   static size_t testKeyLength;
33   static const std::string testKeyStr;
34 
35   void assertEmptyMap() {
36     // Size tests
37     EXPECT_EQ(0u, testMap.size());
38     EXPECT_TRUE(testMap.empty());
39 
40     // Iterator tests
41     EXPECT_TRUE(testMap.begin() == testMap.end());
42 
43     // Lookup tests
44     EXPECT_EQ(0u, testMap.count(testKey));
45     EXPECT_EQ(0u, testMap.count(StringRef(testKeyFirst, testKeyLength)));
46     EXPECT_EQ(0u, testMap.count(testKeyStr));
47     EXPECT_TRUE(testMap.find(testKey) == testMap.end());
48     EXPECT_TRUE(testMap.find(StringRef(testKeyFirst, testKeyLength)) ==
49                 testMap.end());
50     EXPECT_TRUE(testMap.find(testKeyStr) == testMap.end());
51   }
52 
53   void assertSingleItemMap() {
54     // Size tests
55     EXPECT_EQ(1u, testMap.size());
56     EXPECT_FALSE(testMap.begin() == testMap.end());
57     EXPECT_FALSE(testMap.empty());
58 
59     // Iterator tests
60     StringMap<uint32_t>::iterator it = testMap.begin();
61     EXPECT_STREQ(testKey, it->first().data());
62     EXPECT_EQ(testValue, it->second);
63     ++it;
64     EXPECT_TRUE(it == testMap.end());
65 
66     // Lookup tests
67     EXPECT_EQ(1u, testMap.count(testKey));
68     EXPECT_EQ(1u, testMap.count(StringRef(testKeyFirst, testKeyLength)));
69     EXPECT_EQ(1u, testMap.count(testKeyStr));
70     EXPECT_TRUE(testMap.find(testKey) == testMap.begin());
71     EXPECT_TRUE(testMap.find(StringRef(testKeyFirst, testKeyLength)) ==
72                 testMap.begin());
73     EXPECT_TRUE(testMap.find(testKeyStr) == testMap.begin());
74   }
75 };
76 
77 const char StringMapTest::testKey[] = "key";
78 const uint32_t StringMapTest::testValue = 1u;
79 const char *StringMapTest::testKeyFirst = testKey;
80 size_t StringMapTest::testKeyLength = sizeof(testKey) - 1;
81 const std::string StringMapTest::testKeyStr(testKey);
82 
83 struct CountCopyAndMove {
84   CountCopyAndMove() = default;
85   CountCopyAndMove(const CountCopyAndMove &) { copy = 1; }
86   CountCopyAndMove(CountCopyAndMove &&) { move = 1; }
87   void operator=(const CountCopyAndMove &) { ++copy; }
88   void operator=(CountCopyAndMove &&) { ++move; }
89   int copy = 0;
90   int move = 0;
91 };
92 
93 // Empty map tests.
94 TEST_F(StringMapTest, EmptyMapTest) { assertEmptyMap(); }
95 
96 // Constant map tests.
97 TEST_F(StringMapTest, ConstEmptyMapTest) {
98   const StringMap<uint32_t> &constTestMap = testMap;
99 
100   // Size tests
101   EXPECT_EQ(0u, constTestMap.size());
102   EXPECT_TRUE(constTestMap.empty());
103 
104   // Iterator tests
105   EXPECT_TRUE(constTestMap.begin() == constTestMap.end());
106 
107   // Lookup tests
108   EXPECT_EQ(0u, constTestMap.count(testKey));
109   EXPECT_EQ(0u, constTestMap.count(StringRef(testKeyFirst, testKeyLength)));
110   EXPECT_EQ(0u, constTestMap.count(testKeyStr));
111   EXPECT_TRUE(constTestMap.find(testKey) == constTestMap.end());
112   EXPECT_TRUE(constTestMap.find(StringRef(testKeyFirst, testKeyLength)) ==
113               constTestMap.end());
114   EXPECT_TRUE(constTestMap.find(testKeyStr) == constTestMap.end());
115 }
116 
117 // initializer_list ctor test; also implicitly tests initializer_list and
118 // iterator overloads of insert().
119 TEST_F(StringMapTest, InitializerListCtor) {
120   testMap = StringMap<uint32_t>({{"key", 1}});
121   assertSingleItemMap();
122 }
123 
124 // A map with a single entry.
125 TEST_F(StringMapTest, SingleEntryMapTest) {
126   testMap[testKey] = testValue;
127   assertSingleItemMap();
128 }
129 
130 // Test clear() method.
131 TEST_F(StringMapTest, ClearTest) {
132   testMap[testKey] = testValue;
133   testMap.clear();
134   assertEmptyMap();
135 }
136 
137 // Test erase(iterator) method.
138 TEST_F(StringMapTest, EraseIteratorTest) {
139   testMap[testKey] = testValue;
140   testMap.erase(testMap.begin());
141   assertEmptyMap();
142 }
143 
144 // Test erase(value) method.
145 TEST_F(StringMapTest, EraseValueTest) {
146   testMap[testKey] = testValue;
147   testMap.erase(testKey);
148   assertEmptyMap();
149 }
150 
151 // Test inserting two values and erasing one.
152 TEST_F(StringMapTest, InsertAndEraseTest) {
153   testMap[testKey] = testValue;
154   testMap["otherKey"] = 2;
155   testMap.erase("otherKey");
156   assertSingleItemMap();
157 }
158 
159 TEST_F(StringMapTest, SmallFullMapTest) {
160   // StringMap has a tricky corner case when the map is small (<8 buckets) and
161   // it fills up through a balanced pattern of inserts and erases. This can
162   // lead to inf-loops in some cases (PR13148) so we test it explicitly here.
163   llvm::StringMap<int> Map(2);
164 
165   Map["eins"] = 1;
166   Map["zwei"] = 2;
167   Map["drei"] = 3;
168   Map.erase("drei");
169   Map.erase("eins");
170   Map["veir"] = 4;
171   Map["funf"] = 5;
172 
173   EXPECT_EQ(3u, Map.size());
174   EXPECT_EQ(0, Map.lookup("eins"));
175   EXPECT_EQ(2, Map.lookup("zwei"));
176   EXPECT_EQ(0, Map.lookup("drei"));
177   EXPECT_EQ(4, Map.lookup("veir"));
178   EXPECT_EQ(5, Map.lookup("funf"));
179 }
180 
181 TEST_F(StringMapTest, CopyCtorTest) {
182   llvm::StringMap<int> Map;
183 
184   Map["eins"] = 1;
185   Map["zwei"] = 2;
186   Map["drei"] = 3;
187   Map.erase("drei");
188   Map.erase("eins");
189   Map["veir"] = 4;
190   Map["funf"] = 5;
191 
192   EXPECT_EQ(3u, Map.size());
193   EXPECT_EQ(0, Map.lookup("eins"));
194   EXPECT_EQ(2, Map.lookup("zwei"));
195   EXPECT_EQ(0, Map.lookup("drei"));
196   EXPECT_EQ(4, Map.lookup("veir"));
197   EXPECT_EQ(5, Map.lookup("funf"));
198 
199   llvm::StringMap<int> Map2(Map);
200   EXPECT_EQ(3u, Map2.size());
201   EXPECT_EQ(0, Map2.lookup("eins"));
202   EXPECT_EQ(2, Map2.lookup("zwei"));
203   EXPECT_EQ(0, Map2.lookup("drei"));
204   EXPECT_EQ(4, Map2.lookup("veir"));
205   EXPECT_EQ(5, Map2.lookup("funf"));
206 }
207 
208 TEST_F(StringMapTest, LookupOrTrapTest) {
209   llvm::StringMap<int> Map;
210 
211   // key not found on empty map
212   EXPECT_DEATH({ Map.at("a"); }, "StringMap::at failed due to a missing key");
213 
214   // keys both found and not found on non-empty map
215   Map["a"] = 1;
216   Map["b"] = 2;
217   Map["c"] = 3;
218   EXPECT_EQ(1, Map.at("a"));
219   EXPECT_EQ(2, Map.at("b"));
220   EXPECT_EQ(3, Map.at("c"));
221   EXPECT_DEATH({ Map.at("d"); }, "StringMap::at failed due to a missing key");
222 }
223 
224 // A more complex iteration test.
225 TEST_F(StringMapTest, IterationTest) {
226   bool visited[100];
227 
228   // Insert 100 numbers into the map
229   for (int i = 0; i < 100; ++i) {
230     std::stringstream ss;
231     ss << "key_" << i;
232     testMap[ss.str()] = i;
233     visited[i] = false;
234   }
235 
236   // Iterate over all numbers and mark each one found.
237   for (StringMap<uint32_t>::iterator it = testMap.begin(); it != testMap.end();
238        ++it) {
239     std::stringstream ss;
240     ss << "key_" << it->second;
241     ASSERT_STREQ(ss.str().c_str(), it->first().data());
242     visited[it->second] = true;
243   }
244 
245   // Ensure every number was visited.
246   for (int i = 0; i < 100; ++i) {
247     ASSERT_TRUE(visited[i]) << "Entry #" << i << " was never visited";
248   }
249 }
250 
251 // Test StringMapEntry::Create() method.
252 TEST_F(StringMapTest, StringMapEntryTest) {
253   MallocAllocator Allocator;
254   StringMap<uint32_t>::value_type *entry =
255       StringMap<uint32_t>::value_type::create(
256           StringRef(testKeyFirst, testKeyLength), Allocator, 1u);
257   EXPECT_STREQ(testKey, entry->first().data());
258   EXPECT_EQ(1u, entry->second);
259   entry->Destroy(Allocator);
260 }
261 
262 // Test insert() method.
263 TEST_F(StringMapTest, InsertTest) {
264   SCOPED_TRACE("InsertTest");
265   testMap.insert(StringMap<uint32_t>::value_type::create(
266       StringRef(testKeyFirst, testKeyLength), testMap.getAllocator(), 1u));
267   assertSingleItemMap();
268 }
269 
270 // Test insert(pair<K, V>) method
271 TEST_F(StringMapTest, InsertPairTest) {
272   bool Inserted;
273   StringMap<uint32_t>::iterator NewIt;
274   std::tie(NewIt, Inserted) =
275       testMap.insert(std::make_pair(testKeyFirst, testValue));
276   EXPECT_EQ(1u, testMap.size());
277   EXPECT_EQ(testValue, testMap[testKeyFirst]);
278   EXPECT_EQ(testKeyFirst, NewIt->first());
279   EXPECT_EQ(testValue, NewIt->second);
280   EXPECT_TRUE(Inserted);
281 
282   StringMap<uint32_t>::iterator ExistingIt;
283   std::tie(ExistingIt, Inserted) =
284       testMap.insert(std::make_pair(testKeyFirst, testValue + 1));
285   EXPECT_EQ(1u, testMap.size());
286   EXPECT_EQ(testValue, testMap[testKeyFirst]);
287   EXPECT_FALSE(Inserted);
288   EXPECT_EQ(NewIt, ExistingIt);
289 }
290 
291 // Test insert(pair<K, V>) method when rehashing occurs
292 TEST_F(StringMapTest, InsertRehashingPairTest) {
293   // Check that the correct iterator is returned when the inserted element is
294   // moved to a different bucket during internal rehashing. This depends on
295   // the particular key, and the implementation of StringMap and HashString.
296   // Changes to those might result in this test not actually checking that.
297   StringMap<uint32_t> t(0);
298   EXPECT_EQ(0u, t.getNumBuckets());
299 
300   StringMap<uint32_t>::iterator It =
301       t.insert(std::make_pair("abcdef", 42)).first;
302   EXPECT_EQ(16u, t.getNumBuckets());
303   EXPECT_EQ("abcdef", It->first());
304   EXPECT_EQ(42u, It->second);
305 }
306 
307 TEST_F(StringMapTest, InsertOrAssignTest) {
308   struct A : CountCopyAndMove {
309     A(int v) : v(v) {}
310     int v;
311   };
312   StringMap<A> t(0);
313 
314   auto try1 = t.insert_or_assign("A", A(1));
315   EXPECT_TRUE(try1.second);
316   EXPECT_EQ(1, try1.first->second.v);
317   EXPECT_EQ(1, try1.first->second.move);
318 
319   auto try2 = t.insert_or_assign("A", A(2));
320   EXPECT_FALSE(try2.second);
321   EXPECT_EQ(2, try2.first->second.v);
322   EXPECT_EQ(2, try1.first->second.move);
323 
324   EXPECT_EQ(try1.first, try2.first);
325   EXPECT_EQ(0, try1.first->second.copy);
326 }
327 
328 TEST_F(StringMapTest, IterMapKeysVector) {
329   StringMap<int> Map;
330   Map["A"] = 1;
331   Map["B"] = 2;
332   Map["C"] = 3;
333   Map["D"] = 3;
334 
335   std::vector<StringRef> Keys{Map.keys().begin(), Map.keys().end()};
336   llvm::sort(Keys);
337 
338   std::vector<StringRef> Expected{{"A", "B", "C", "D"}};
339   EXPECT_EQ(Expected, Keys);
340 }
341 
342 TEST_F(StringMapTest, IterMapKeysSmallVector) {
343   StringMap<int> Map;
344   Map["A"] = 1;
345   Map["B"] = 2;
346   Map["C"] = 3;
347   Map["D"] = 3;
348 
349   auto Keys = to_vector<4>(Map.keys());
350   llvm::sort(Keys);
351 
352   SmallVector<StringRef, 4> Expected = {"A", "B", "C", "D"};
353   EXPECT_EQ(Expected, Keys);
354 }
355 
356 // Create a non-default constructable value
357 struct StringMapTestStruct {
358   StringMapTestStruct(int i) : i(i) {}
359   StringMapTestStruct() = delete;
360   int i;
361 };
362 
363 TEST_F(StringMapTest, NonDefaultConstructable) {
364   StringMap<StringMapTestStruct> t;
365   t.insert(std::make_pair("Test", StringMapTestStruct(123)));
366   StringMap<StringMapTestStruct>::iterator iter = t.find("Test");
367   ASSERT_NE(iter, t.end());
368   ASSERT_EQ(iter->second.i, 123);
369 }
370 
371 struct Immovable {
372   Immovable() {}
373   Immovable(Immovable &&) = delete; // will disable the other special members
374 };
375 
376 struct MoveOnly {
377   int i;
378   MoveOnly(int i) : i(i) {}
379   MoveOnly(const Immovable &) : i(0) {}
380   MoveOnly(MoveOnly &&RHS) : i(RHS.i) {}
381   MoveOnly &operator=(MoveOnly &&RHS) {
382     i = RHS.i;
383     return *this;
384   }
385 
386 private:
387   MoveOnly(const MoveOnly &) = delete;
388   MoveOnly &operator=(const MoveOnly &) = delete;
389 };
390 
391 TEST_F(StringMapTest, MoveOnly) {
392   StringMap<MoveOnly> t;
393   t.insert(std::make_pair("Test", MoveOnly(42)));
394   StringRef Key = "Test";
395   StringMapEntry<MoveOnly>::create(Key, t.getAllocator(), MoveOnly(42))
396       ->Destroy(t.getAllocator());
397 }
398 
399 TEST_F(StringMapTest, CtorArg) {
400   StringRef Key = "Test";
401   MallocAllocator Allocator;
402   StringMapEntry<MoveOnly>::create(Key, Allocator, Immovable())
403       ->Destroy(Allocator);
404 }
405 
406 TEST_F(StringMapTest, MoveConstruct) {
407   StringMap<int> A;
408   A["x"] = 42;
409   StringMap<int> B = std::move(A);
410   ASSERT_EQ(A.size(), 0u);
411   ASSERT_EQ(B.size(), 1u);
412   ASSERT_EQ(B["x"], 42);
413   ASSERT_EQ(B.count("y"), 0u);
414 }
415 
416 TEST_F(StringMapTest, MoveAssignment) {
417   StringMap<int> A;
418   A["x"] = 42;
419   StringMap<int> B;
420   B["y"] = 117;
421   A = std::move(B);
422   ASSERT_EQ(A.size(), 1u);
423   ASSERT_EQ(B.size(), 0u);
424   ASSERT_EQ(A["y"], 117);
425   ASSERT_EQ(B.count("x"), 0u);
426 }
427 
428 TEST_F(StringMapTest, EqualEmpty) {
429   StringMap<int> A;
430   StringMap<int> B;
431   ASSERT_TRUE(A == B);
432   ASSERT_FALSE(A != B);
433   ASSERT_TRUE(A == A); // self check
434 }
435 
436 TEST_F(StringMapTest, EqualWithValues) {
437   StringMap<int> A;
438   A["A"] = 1;
439   A["B"] = 2;
440   A["C"] = 3;
441   A["D"] = 3;
442 
443   StringMap<int> B;
444   B["A"] = 1;
445   B["B"] = 2;
446   B["C"] = 3;
447   B["D"] = 3;
448 
449   ASSERT_TRUE(A == B);
450   ASSERT_TRUE(B == A);
451   ASSERT_FALSE(A != B);
452   ASSERT_FALSE(B != A);
453   ASSERT_TRUE(A == A); // self check
454 }
455 
456 TEST_F(StringMapTest, NotEqualMissingKeys) {
457   StringMap<int> A;
458   A["A"] = 1;
459   A["B"] = 2;
460 
461   StringMap<int> B;
462   B["A"] = 1;
463   B["B"] = 2;
464   B["C"] = 3;
465   B["D"] = 3;
466 
467   ASSERT_FALSE(A == B);
468   ASSERT_FALSE(B == A);
469   ASSERT_TRUE(A != B);
470   ASSERT_TRUE(B != A);
471 }
472 
473 TEST_F(StringMapTest, NotEqualWithDifferentValues) {
474   StringMap<int> A;
475   A["A"] = 1;
476   A["B"] = 2;
477   A["C"] = 100;
478   A["D"] = 3;
479 
480   StringMap<int> B;
481   B["A"] = 1;
482   B["B"] = 2;
483   B["C"] = 3;
484   B["D"] = 3;
485 
486   ASSERT_FALSE(A == B);
487   ASSERT_FALSE(B == A);
488   ASSERT_TRUE(A != B);
489   ASSERT_TRUE(B != A);
490 }
491 
492 struct Countable {
493   int &InstanceCount;
494   int Number;
495   Countable(int Number, int &InstanceCount)
496       : InstanceCount(InstanceCount), Number(Number) {
497     ++InstanceCount;
498   }
499   Countable(Countable &&C) : InstanceCount(C.InstanceCount), Number(C.Number) {
500     ++InstanceCount;
501     C.Number = -1;
502   }
503   Countable(const Countable &C)
504       : InstanceCount(C.InstanceCount), Number(C.Number) {
505     ++InstanceCount;
506   }
507   Countable &operator=(Countable C) {
508     Number = C.Number;
509     return *this;
510   }
511   ~Countable() { --InstanceCount; }
512 };
513 
514 TEST_F(StringMapTest, MoveDtor) {
515   int InstanceCount = 0;
516   StringMap<Countable> A;
517   A.insert(std::make_pair("x", Countable(42, InstanceCount)));
518   ASSERT_EQ(InstanceCount, 1);
519   auto I = A.find("x");
520   ASSERT_NE(I, A.end());
521   ASSERT_EQ(I->second.Number, 42);
522 
523   StringMap<Countable> B;
524   B = std::move(A);
525   ASSERT_EQ(InstanceCount, 1);
526   ASSERT_TRUE(A.empty());
527   I = B.find("x");
528   ASSERT_NE(I, B.end());
529   ASSERT_EQ(I->second.Number, 42);
530 
531   B = StringMap<Countable>();
532   ASSERT_EQ(InstanceCount, 0);
533   ASSERT_TRUE(B.empty());
534 }
535 
536 TEST_F(StringMapTest, StructuredBindings) {
537   StringMap<int> A;
538   A["a"] = 42;
539 
540   for (auto &[Key, Value] : A) {
541     EXPECT_EQ("a", Key);
542     EXPECT_EQ(42, Value);
543   }
544 }
545 
546 namespace {
547 // Simple class that counts how many moves and copy happens when growing a map
548 struct CountCtorCopyAndMove {
549   static unsigned Ctor;
550   static unsigned Move;
551   static unsigned Copy;
552   int Data = 0;
553   CountCtorCopyAndMove(int Data) : Data(Data) { Ctor++; }
554   CountCtorCopyAndMove() { Ctor++; }
555 
556   CountCtorCopyAndMove(const CountCtorCopyAndMove &) { Copy++; }
557   CountCtorCopyAndMove &operator=(const CountCtorCopyAndMove &) {
558     Copy++;
559     return *this;
560   }
561   CountCtorCopyAndMove(CountCtorCopyAndMove &&) { Move++; }
562   CountCtorCopyAndMove &operator=(const CountCtorCopyAndMove &&) {
563     Move++;
564     return *this;
565   }
566 };
567 unsigned CountCtorCopyAndMove::Copy = 0;
568 unsigned CountCtorCopyAndMove::Move = 0;
569 unsigned CountCtorCopyAndMove::Ctor = 0;
570 
571 } // anonymous namespace
572 
573 // Make sure creating the map with an initial size of N actually gives us enough
574 // buckets to insert N items without increasing allocation size.
575 TEST(StringMapCustomTest, InitialSizeTest) {
576   // 1 is an "edge value", 32 is an arbitrary power of two, and 67 is an
577   // arbitrary prime, picked without any good reason.
578   for (auto Size : {1, 32, 67}) {
579     StringMap<CountCtorCopyAndMove> Map(Size);
580     auto NumBuckets = Map.getNumBuckets();
581     CountCtorCopyAndMove::Move = 0;
582     CountCtorCopyAndMove::Copy = 0;
583     for (int i = 0; i < Size; ++i)
584       Map.insert(std::pair<std::string, CountCtorCopyAndMove>(
585           std::piecewise_construct, std::forward_as_tuple(Twine(i).str()),
586           std::forward_as_tuple(i)));
587     // After the initial move, the map will move the Elts in the Entry.
588     EXPECT_EQ((unsigned)Size * 2, CountCtorCopyAndMove::Move);
589     // We copy once the pair from the Elts vector
590     EXPECT_EQ(0u, CountCtorCopyAndMove::Copy);
591     // Check that the map didn't grow
592     EXPECT_EQ(Map.getNumBuckets(), NumBuckets);
593   }
594 }
595 
596 TEST(StringMapCustomTest, BracketOperatorCtor) {
597   StringMap<CountCtorCopyAndMove> Map;
598   CountCtorCopyAndMove::Ctor = 0;
599   Map["abcd"];
600   EXPECT_EQ(1u, CountCtorCopyAndMove::Ctor);
601   // Test that operator[] does not create a value when it is already in the map
602   CountCtorCopyAndMove::Ctor = 0;
603   Map["abcd"];
604   EXPECT_EQ(0u, CountCtorCopyAndMove::Ctor);
605 }
606 
607 namespace {
608 struct NonMoveableNonCopyableType {
609   int Data = 0;
610   NonMoveableNonCopyableType() = default;
611   NonMoveableNonCopyableType(int Data) : Data(Data) {}
612   NonMoveableNonCopyableType(const NonMoveableNonCopyableType &) = delete;
613   NonMoveableNonCopyableType(NonMoveableNonCopyableType &&) = delete;
614 };
615 } // namespace
616 
617 // Test that we can "emplace" an element in the map without involving map/move
618 TEST(StringMapCustomTest, EmplaceTest) {
619   StringMap<NonMoveableNonCopyableType> Map;
620   Map.try_emplace("abcd", 42);
621   EXPECT_EQ(1u, Map.count("abcd"));
622   EXPECT_EQ(42, Map["abcd"].Data);
623 }
624 
625 // Test that StringMapEntryBase can handle size_t wide sizes.
626 TEST(StringMapCustomTest, StringMapEntryBaseSize) {
627   size_t LargeValue;
628 
629   // Test that the entry can represent max-unsigned.
630   if (sizeof(size_t) <= sizeof(unsigned))
631     LargeValue = std::numeric_limits<unsigned>::max();
632   else
633     LargeValue = std::numeric_limits<unsigned>::max() + 1ULL;
634   StringMapEntryBase LargeBase(LargeValue);
635   EXPECT_EQ(LargeValue, LargeBase.getKeyLength());
636 
637   // Test that the entry can hold at least max size_t.
638   LargeValue = std::numeric_limits<size_t>::max();
639   StringMapEntryBase LargerBase(LargeValue);
640   LargeValue = std::numeric_limits<size_t>::max();
641   EXPECT_EQ(LargeValue, LargerBase.getKeyLength());
642 }
643 
644 // Test that StringMapEntry can handle size_t wide sizes.
645 TEST(StringMapCustomTest, StringMapEntrySize) {
646   size_t LargeValue;
647 
648   // Test that the entry can represent max-unsigned.
649   if (sizeof(size_t) <= sizeof(unsigned))
650     LargeValue = std::numeric_limits<unsigned>::max();
651   else
652     LargeValue = std::numeric_limits<unsigned>::max() + 1ULL;
653   StringMapEntry<int> LargeEntry(LargeValue);
654   StringRef Key = LargeEntry.getKey();
655   EXPECT_EQ(LargeValue, Key.size());
656 
657   // Test that the entry can hold at least max size_t.
658   LargeValue = std::numeric_limits<size_t>::max();
659   StringMapEntry<int> LargerEntry(LargeValue);
660   Key = LargerEntry.getKey();
661   EXPECT_EQ(LargeValue, Key.size());
662 }
663 
664 } // end anonymous namespace
665