xref: /llvm-project/llvm/unittests/ADT/StringMapTest.cpp (revision 72ebcf1a53a2fcf28aef96e606d030fa06749c55)
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 // A more complex iteration test.
209 TEST_F(StringMapTest, IterationTest) {
210   bool visited[100];
211 
212   // Insert 100 numbers into the map
213   for (int i = 0; i < 100; ++i) {
214     std::stringstream ss;
215     ss << "key_" << i;
216     testMap[ss.str()] = i;
217     visited[i] = false;
218   }
219 
220   // Iterate over all numbers and mark each one found.
221   for (StringMap<uint32_t>::iterator it = testMap.begin(); it != testMap.end();
222        ++it) {
223     std::stringstream ss;
224     ss << "key_" << it->second;
225     ASSERT_STREQ(ss.str().c_str(), it->first().data());
226     visited[it->second] = true;
227   }
228 
229   // Ensure every number was visited.
230   for (int i = 0; i < 100; ++i) {
231     ASSERT_TRUE(visited[i]) << "Entry #" << i << " was never visited";
232   }
233 }
234 
235 // Test StringMapEntry::Create() method.
236 TEST_F(StringMapTest, StringMapEntryTest) {
237   MallocAllocator Allocator;
238   StringMap<uint32_t>::value_type *entry =
239       StringMap<uint32_t>::value_type::Create(
240           StringRef(testKeyFirst, testKeyLength), Allocator, 1u);
241   EXPECT_STREQ(testKey, entry->first().data());
242   EXPECT_EQ(1u, entry->second);
243   entry->Destroy(Allocator);
244 }
245 
246 // Test insert() method.
247 TEST_F(StringMapTest, InsertTest) {
248   SCOPED_TRACE("InsertTest");
249   testMap.insert(StringMap<uint32_t>::value_type::Create(
250       StringRef(testKeyFirst, testKeyLength), testMap.getAllocator(), 1u));
251   assertSingleItemMap();
252 }
253 
254 // Test insert(pair<K, V>) method
255 TEST_F(StringMapTest, InsertPairTest) {
256   bool Inserted;
257   StringMap<uint32_t>::iterator NewIt;
258   std::tie(NewIt, Inserted) =
259       testMap.insert(std::make_pair(testKeyFirst, testValue));
260   EXPECT_EQ(1u, testMap.size());
261   EXPECT_EQ(testValue, testMap[testKeyFirst]);
262   EXPECT_EQ(testKeyFirst, NewIt->first());
263   EXPECT_EQ(testValue, NewIt->second);
264   EXPECT_TRUE(Inserted);
265 
266   StringMap<uint32_t>::iterator ExistingIt;
267   std::tie(ExistingIt, Inserted) =
268       testMap.insert(std::make_pair(testKeyFirst, testValue + 1));
269   EXPECT_EQ(1u, testMap.size());
270   EXPECT_EQ(testValue, testMap[testKeyFirst]);
271   EXPECT_FALSE(Inserted);
272   EXPECT_EQ(NewIt, ExistingIt);
273 }
274 
275 // Test insert(pair<K, V>) method when rehashing occurs
276 TEST_F(StringMapTest, InsertRehashingPairTest) {
277   // Check that the correct iterator is returned when the inserted element is
278   // moved to a different bucket during internal rehashing. This depends on
279   // the particular key, and the implementation of StringMap and HashString.
280   // Changes to those might result in this test not actually checking that.
281   StringMap<uint32_t> t(0);
282   EXPECT_EQ(0u, t.getNumBuckets());
283 
284   StringMap<uint32_t>::iterator It =
285       t.insert(std::make_pair("abcdef", 42)).first;
286   EXPECT_EQ(16u, t.getNumBuckets());
287   EXPECT_EQ("abcdef", It->first());
288   EXPECT_EQ(42u, It->second);
289 }
290 
291 TEST_F(StringMapTest, InsertOrAssignTest) {
292   struct A : CountCopyAndMove {
293     A(int v) : v(v) {}
294     int v;
295   };
296   StringMap<A> t(0);
297 
298   auto try1 = t.insert_or_assign("A", A(1));
299   EXPECT_TRUE(try1.second);
300   EXPECT_EQ(1, try1.first->second.v);
301   EXPECT_EQ(1, try1.first->second.move);
302 
303   auto try2 = t.insert_or_assign("A", A(2));
304   EXPECT_FALSE(try2.second);
305   EXPECT_EQ(2, try2.first->second.v);
306   EXPECT_EQ(2, try1.first->second.move);
307 
308   EXPECT_EQ(try1.first, try2.first);
309   EXPECT_EQ(0, try1.first->second.copy);
310 }
311 
312 TEST_F(StringMapTest, IterMapKeysVector) {
313   StringMap<int> Map;
314   Map["A"] = 1;
315   Map["B"] = 2;
316   Map["C"] = 3;
317   Map["D"] = 3;
318 
319   std::vector<StringRef> Keys{Map.keys().begin(), Map.keys().end()};
320   llvm::sort(Keys);
321 
322   std::vector<StringRef> Expected{{"A", "B", "C", "D"}};
323   EXPECT_EQ(Expected, Keys);
324 }
325 
326 TEST_F(StringMapTest, IterMapKeysSmallVector) {
327   StringMap<int> Map;
328   Map["A"] = 1;
329   Map["B"] = 2;
330   Map["C"] = 3;
331   Map["D"] = 3;
332 
333   auto Keys = to_vector<4>(Map.keys());
334   llvm::sort(Keys);
335 
336   SmallVector<StringRef, 4> Expected = {"A", "B", "C", "D"};
337   EXPECT_EQ(Expected, Keys);
338 }
339 
340 // Create a non-default constructable value
341 struct StringMapTestStruct {
342   StringMapTestStruct(int i) : i(i) {}
343   StringMapTestStruct() = delete;
344   int i;
345 };
346 
347 TEST_F(StringMapTest, NonDefaultConstructable) {
348   StringMap<StringMapTestStruct> t;
349   t.insert(std::make_pair("Test", StringMapTestStruct(123)));
350   StringMap<StringMapTestStruct>::iterator iter = t.find("Test");
351   ASSERT_NE(iter, t.end());
352   ASSERT_EQ(iter->second.i, 123);
353 }
354 
355 struct Immovable {
356   Immovable() {}
357   Immovable(Immovable &&) = delete; // will disable the other special members
358 };
359 
360 struct MoveOnly {
361   int i;
362   MoveOnly(int i) : i(i) {}
363   MoveOnly(const Immovable &) : i(0) {}
364   MoveOnly(MoveOnly &&RHS) : i(RHS.i) {}
365   MoveOnly &operator=(MoveOnly &&RHS) {
366     i = RHS.i;
367     return *this;
368   }
369 
370 private:
371   MoveOnly(const MoveOnly &) = delete;
372   MoveOnly &operator=(const MoveOnly &) = delete;
373 };
374 
375 TEST_F(StringMapTest, MoveOnly) {
376   StringMap<MoveOnly> t;
377   t.insert(std::make_pair("Test", MoveOnly(42)));
378   StringRef Key = "Test";
379   StringMapEntry<MoveOnly>::Create(Key, t.getAllocator(), MoveOnly(42))
380       ->Destroy(t.getAllocator());
381 }
382 
383 TEST_F(StringMapTest, CtorArg) {
384   StringRef Key = "Test";
385   MallocAllocator Allocator;
386   StringMapEntry<MoveOnly>::Create(Key, Allocator, Immovable())
387       ->Destroy(Allocator);
388 }
389 
390 TEST_F(StringMapTest, MoveConstruct) {
391   StringMap<int> A;
392   A["x"] = 42;
393   StringMap<int> B = std::move(A);
394   ASSERT_EQ(A.size(), 0u);
395   ASSERT_EQ(B.size(), 1u);
396   ASSERT_EQ(B["x"], 42);
397   ASSERT_EQ(B.count("y"), 0u);
398 }
399 
400 TEST_F(StringMapTest, MoveAssignment) {
401   StringMap<int> A;
402   A["x"] = 42;
403   StringMap<int> B;
404   B["y"] = 117;
405   A = std::move(B);
406   ASSERT_EQ(A.size(), 1u);
407   ASSERT_EQ(B.size(), 0u);
408   ASSERT_EQ(A["y"], 117);
409   ASSERT_EQ(B.count("x"), 0u);
410 }
411 
412 TEST_F(StringMapTest, EqualEmpty) {
413   StringMap<int> A;
414   StringMap<int> B;
415   ASSERT_TRUE(A == B);
416   ASSERT_FALSE(A != B);
417   ASSERT_TRUE(A == A); // self check
418 }
419 
420 TEST_F(StringMapTest, EqualWithValues) {
421   StringMap<int> A;
422   A["A"] = 1;
423   A["B"] = 2;
424   A["C"] = 3;
425   A["D"] = 3;
426 
427   StringMap<int> B;
428   B["A"] = 1;
429   B["B"] = 2;
430   B["C"] = 3;
431   B["D"] = 3;
432 
433   ASSERT_TRUE(A == B);
434   ASSERT_TRUE(B == A);
435   ASSERT_FALSE(A != B);
436   ASSERT_FALSE(B != A);
437   ASSERT_TRUE(A == A); // self check
438 }
439 
440 TEST_F(StringMapTest, NotEqualMissingKeys) {
441   StringMap<int> A;
442   A["A"] = 1;
443   A["B"] = 2;
444 
445   StringMap<int> B;
446   B["A"] = 1;
447   B["B"] = 2;
448   B["C"] = 3;
449   B["D"] = 3;
450 
451   ASSERT_FALSE(A == B);
452   ASSERT_FALSE(B == A);
453   ASSERT_TRUE(A != B);
454   ASSERT_TRUE(B != A);
455 }
456 
457 TEST_F(StringMapTest, NotEqualWithDifferentValues) {
458   StringMap<int> A;
459   A["A"] = 1;
460   A["B"] = 2;
461   A["C"] = 100;
462   A["D"] = 3;
463 
464   StringMap<int> B;
465   B["A"] = 1;
466   B["B"] = 2;
467   B["C"] = 3;
468   B["D"] = 3;
469 
470   ASSERT_FALSE(A == B);
471   ASSERT_FALSE(B == A);
472   ASSERT_TRUE(A != B);
473   ASSERT_TRUE(B != A);
474 }
475 
476 struct Countable {
477   int &InstanceCount;
478   int Number;
479   Countable(int Number, int &InstanceCount)
480       : InstanceCount(InstanceCount), Number(Number) {
481     ++InstanceCount;
482   }
483   Countable(Countable &&C) : InstanceCount(C.InstanceCount), Number(C.Number) {
484     ++InstanceCount;
485     C.Number = -1;
486   }
487   Countable(const Countable &C)
488       : InstanceCount(C.InstanceCount), Number(C.Number) {
489     ++InstanceCount;
490   }
491   Countable &operator=(Countable C) {
492     Number = C.Number;
493     return *this;
494   }
495   ~Countable() { --InstanceCount; }
496 };
497 
498 TEST_F(StringMapTest, MoveDtor) {
499   int InstanceCount = 0;
500   StringMap<Countable> A;
501   A.insert(std::make_pair("x", Countable(42, InstanceCount)));
502   ASSERT_EQ(InstanceCount, 1);
503   auto I = A.find("x");
504   ASSERT_NE(I, A.end());
505   ASSERT_EQ(I->second.Number, 42);
506 
507   StringMap<Countable> B;
508   B = std::move(A);
509   ASSERT_EQ(InstanceCount, 1);
510   ASSERT_TRUE(A.empty());
511   I = B.find("x");
512   ASSERT_NE(I, B.end());
513   ASSERT_EQ(I->second.Number, 42);
514 
515   B = StringMap<Countable>();
516   ASSERT_EQ(InstanceCount, 0);
517   ASSERT_TRUE(B.empty());
518 }
519 
520 namespace {
521 // Simple class that counts how many moves and copy happens when growing a map
522 struct CountCtorCopyAndMove {
523   static unsigned Ctor;
524   static unsigned Move;
525   static unsigned Copy;
526   int Data = 0;
527   CountCtorCopyAndMove(int Data) : Data(Data) { Ctor++; }
528   CountCtorCopyAndMove() { Ctor++; }
529 
530   CountCtorCopyAndMove(const CountCtorCopyAndMove &) { Copy++; }
531   CountCtorCopyAndMove &operator=(const CountCtorCopyAndMove &) {
532     Copy++;
533     return *this;
534   }
535   CountCtorCopyAndMove(CountCtorCopyAndMove &&) { Move++; }
536   CountCtorCopyAndMove &operator=(const CountCtorCopyAndMove &&) {
537     Move++;
538     return *this;
539   }
540 };
541 unsigned CountCtorCopyAndMove::Copy = 0;
542 unsigned CountCtorCopyAndMove::Move = 0;
543 unsigned CountCtorCopyAndMove::Ctor = 0;
544 
545 } // anonymous namespace
546 
547 // Make sure creating the map with an initial size of N actually gives us enough
548 // buckets to insert N items without increasing allocation size.
549 TEST(StringMapCustomTest, InitialSizeTest) {
550   // 1 is an "edge value", 32 is an arbitrary power of two, and 67 is an
551   // arbitrary prime, picked without any good reason.
552   for (auto Size : {1, 32, 67}) {
553     StringMap<CountCtorCopyAndMove> Map(Size);
554     auto NumBuckets = Map.getNumBuckets();
555     CountCtorCopyAndMove::Move = 0;
556     CountCtorCopyAndMove::Copy = 0;
557     for (int i = 0; i < Size; ++i)
558       Map.insert(std::pair<std::string, CountCtorCopyAndMove>(
559           std::piecewise_construct, std::forward_as_tuple(Twine(i).str()),
560           std::forward_as_tuple(i)));
561     // After the initial move, the map will move the Elts in the Entry.
562     EXPECT_EQ((unsigned)Size * 2, CountCtorCopyAndMove::Move);
563     // We copy once the pair from the Elts vector
564     EXPECT_EQ(0u, CountCtorCopyAndMove::Copy);
565     // Check that the map didn't grow
566     EXPECT_EQ(Map.getNumBuckets(), NumBuckets);
567   }
568 }
569 
570 TEST(StringMapCustomTest, BracketOperatorCtor) {
571   StringMap<CountCtorCopyAndMove> Map;
572   CountCtorCopyAndMove::Ctor = 0;
573   Map["abcd"];
574   EXPECT_EQ(1u, CountCtorCopyAndMove::Ctor);
575   // Test that operator[] does not create a value when it is already in the map
576   CountCtorCopyAndMove::Ctor = 0;
577   Map["abcd"];
578   EXPECT_EQ(0u, CountCtorCopyAndMove::Ctor);
579 }
580 
581 namespace {
582 struct NonMoveableNonCopyableType {
583   int Data = 0;
584   NonMoveableNonCopyableType() = default;
585   NonMoveableNonCopyableType(int Data) : Data(Data) {}
586   NonMoveableNonCopyableType(const NonMoveableNonCopyableType &) = delete;
587   NonMoveableNonCopyableType(NonMoveableNonCopyableType &&) = delete;
588 };
589 } // namespace
590 
591 // Test that we can "emplace" an element in the map without involving map/move
592 TEST(StringMapCustomTest, EmplaceTest) {
593   StringMap<NonMoveableNonCopyableType> Map;
594   Map.try_emplace("abcd", 42);
595   EXPECT_EQ(1u, Map.count("abcd"));
596   EXPECT_EQ(42, Map["abcd"].Data);
597 }
598 
599 // Test that StringMapEntryBase can handle size_t wide sizes.
600 TEST(StringMapCustomTest, StringMapEntryBaseSize) {
601   size_t LargeValue;
602 
603   // Test that the entry can represent max-unsigned.
604   if (sizeof(size_t) <= sizeof(unsigned))
605     LargeValue = std::numeric_limits<unsigned>::max();
606   else
607     LargeValue = std::numeric_limits<unsigned>::max() + 1ULL;
608   StringMapEntryBase LargeBase(LargeValue);
609   EXPECT_EQ(LargeValue, LargeBase.getKeyLength());
610 
611   // Test that the entry can hold at least max size_t.
612   LargeValue = std::numeric_limits<size_t>::max();
613   StringMapEntryBase LargerBase(LargeValue);
614   LargeValue = std::numeric_limits<size_t>::max();
615   EXPECT_EQ(LargeValue, LargerBase.getKeyLength());
616 }
617 
618 // Test that StringMapEntry can handle size_t wide sizes.
619 TEST(StringMapCustomTest, StringMapEntrySize) {
620   size_t LargeValue;
621 
622   // Test that the entry can represent max-unsigned.
623   if (sizeof(size_t) <= sizeof(unsigned))
624     LargeValue = std::numeric_limits<unsigned>::max();
625   else
626     LargeValue = std::numeric_limits<unsigned>::max() + 1ULL;
627   StringMapEntry<int> LargeEntry(LargeValue);
628   StringRef Key = LargeEntry.getKey();
629   EXPECT_EQ(LargeValue, Key.size());
630 
631   // Test that the entry can hold at least max size_t.
632   LargeValue = std::numeric_limits<size_t>::max();
633   StringMapEntry<int> LargerEntry(LargeValue);
634   Key = LargerEntry.getKey();
635   EXPECT_EQ(LargeValue, Key.size());
636 }
637 
638 } // end anonymous namespace
639