brintos

brintos / llvm-project-archived public Read only

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