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