StringMapTest.cpp 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. //===- llvm/unittest/ADT/StringMapMap.cpp - StringMap unit tests ----------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #include "gtest/gtest.h"
  10. #include "llvm/ADT/StringMap.h"
  11. #include "llvm/Support/DataTypes.h"
  12. #include <tuple>
  13. using namespace llvm;
  14. namespace {
  15. // Test fixture
  16. class StringMapTest : public testing::Test {
  17. protected:
  18. StringMap<uint32_t> testMap;
  19. static const char testKey[];
  20. static const uint32_t testValue;
  21. static const char* testKeyFirst;
  22. static size_t testKeyLength;
  23. static const std::string testKeyStr;
  24. void assertEmptyMap() {
  25. // Size tests
  26. EXPECT_EQ(0u, testMap.size());
  27. EXPECT_TRUE(testMap.empty());
  28. // Iterator tests
  29. EXPECT_TRUE(testMap.begin() == testMap.end());
  30. // Lookup tests
  31. EXPECT_EQ(0u, testMap.count(testKey));
  32. EXPECT_EQ(0u, testMap.count(StringRef(testKeyFirst, testKeyLength)));
  33. EXPECT_EQ(0u, testMap.count(testKeyStr));
  34. EXPECT_TRUE(testMap.find(testKey) == testMap.end());
  35. EXPECT_TRUE(testMap.find(StringRef(testKeyFirst, testKeyLength)) ==
  36. testMap.end());
  37. EXPECT_TRUE(testMap.find(testKeyStr) == testMap.end());
  38. }
  39. void assertSingleItemMap() {
  40. // Size tests
  41. EXPECT_EQ(1u, testMap.size());
  42. EXPECT_FALSE(testMap.begin() == testMap.end());
  43. EXPECT_FALSE(testMap.empty());
  44. // Iterator tests
  45. StringMap<uint32_t>::iterator it = testMap.begin();
  46. EXPECT_STREQ(testKey, it->first().data());
  47. EXPECT_EQ(testValue, it->second);
  48. ++it;
  49. EXPECT_TRUE(it == testMap.end());
  50. // Lookup tests
  51. EXPECT_EQ(1u, testMap.count(testKey));
  52. EXPECT_EQ(1u, testMap.count(StringRef(testKeyFirst, testKeyLength)));
  53. EXPECT_EQ(1u, testMap.count(testKeyStr));
  54. EXPECT_TRUE(testMap.find(testKey) == testMap.begin());
  55. EXPECT_TRUE(testMap.find(StringRef(testKeyFirst, testKeyLength)) ==
  56. testMap.begin());
  57. EXPECT_TRUE(testMap.find(testKeyStr) == testMap.begin());
  58. }
  59. };
  60. const char StringMapTest::testKey[] = "key";
  61. const uint32_t StringMapTest::testValue = 1u;
  62. const char* StringMapTest::testKeyFirst = testKey;
  63. size_t StringMapTest::testKeyLength = sizeof(testKey) - 1;
  64. const std::string StringMapTest::testKeyStr(testKey);
  65. // Empty map tests.
  66. TEST_F(StringMapTest, EmptyMapTest) {
  67. assertEmptyMap();
  68. }
  69. // Constant map tests.
  70. TEST_F(StringMapTest, ConstEmptyMapTest) {
  71. const StringMap<uint32_t>& constTestMap = testMap;
  72. // Size tests
  73. EXPECT_EQ(0u, constTestMap.size());
  74. EXPECT_TRUE(constTestMap.empty());
  75. // Iterator tests
  76. EXPECT_TRUE(constTestMap.begin() == constTestMap.end());
  77. // Lookup tests
  78. EXPECT_EQ(0u, constTestMap.count(testKey));
  79. EXPECT_EQ(0u, constTestMap.count(StringRef(testKeyFirst, testKeyLength)));
  80. EXPECT_EQ(0u, constTestMap.count(testKeyStr));
  81. EXPECT_TRUE(constTestMap.find(testKey) == constTestMap.end());
  82. EXPECT_TRUE(constTestMap.find(StringRef(testKeyFirst, testKeyLength)) ==
  83. constTestMap.end());
  84. EXPECT_TRUE(constTestMap.find(testKeyStr) == constTestMap.end());
  85. }
  86. // A map with a single entry.
  87. TEST_F(StringMapTest, SingleEntryMapTest) {
  88. testMap[testKey] = testValue;
  89. assertSingleItemMap();
  90. }
  91. // Test clear() method.
  92. TEST_F(StringMapTest, ClearTest) {
  93. testMap[testKey] = testValue;
  94. testMap.clear();
  95. assertEmptyMap();
  96. }
  97. // Test erase(iterator) method.
  98. TEST_F(StringMapTest, EraseIteratorTest) {
  99. testMap[testKey] = testValue;
  100. testMap.erase(testMap.begin());
  101. assertEmptyMap();
  102. }
  103. // Test erase(value) method.
  104. TEST_F(StringMapTest, EraseValueTest) {
  105. testMap[testKey] = testValue;
  106. testMap.erase(testKey);
  107. assertEmptyMap();
  108. }
  109. // Test inserting two values and erasing one.
  110. TEST_F(StringMapTest, InsertAndEraseTest) {
  111. testMap[testKey] = testValue;
  112. testMap["otherKey"] = 2;
  113. testMap.erase("otherKey");
  114. assertSingleItemMap();
  115. }
  116. TEST_F(StringMapTest, SmallFullMapTest) {
  117. // StringMap has a tricky corner case when the map is small (<8 buckets) and
  118. // it fills up through a balanced pattern of inserts and erases. This can
  119. // lead to inf-loops in some cases (PR13148) so we test it explicitly here.
  120. llvm::StringMap<int> Map(2);
  121. Map["eins"] = 1;
  122. Map["zwei"] = 2;
  123. Map["drei"] = 3;
  124. Map.erase("drei");
  125. Map.erase("eins");
  126. Map["veir"] = 4;
  127. Map["funf"] = 5;
  128. EXPECT_EQ(3u, Map.size());
  129. EXPECT_EQ(0, Map.lookup("eins"));
  130. EXPECT_EQ(2, Map.lookup("zwei"));
  131. EXPECT_EQ(0, Map.lookup("drei"));
  132. EXPECT_EQ(4, Map.lookup("veir"));
  133. EXPECT_EQ(5, Map.lookup("funf"));
  134. }
  135. // A more complex iteration test.
  136. TEST_F(StringMapTest, IterationTest) {
  137. bool visited[100];
  138. // Insert 100 numbers into the map
  139. for (int i = 0; i < 100; ++i) {
  140. std::stringstream ss;
  141. ss << "key_" << i;
  142. testMap[ss.str()] = i;
  143. visited[i] = false;
  144. }
  145. // Iterate over all numbers and mark each one found.
  146. for (StringMap<uint32_t>::iterator it = testMap.begin();
  147. it != testMap.end(); ++it) {
  148. std::stringstream ss;
  149. ss << "key_" << it->second;
  150. ASSERT_STREQ(ss.str().c_str(), it->first().data());
  151. visited[it->second] = true;
  152. }
  153. // Ensure every number was visited.
  154. for (int i = 0; i < 100; ++i) {
  155. ASSERT_TRUE(visited[i]) << "Entry #" << i << " was never visited";
  156. }
  157. }
  158. // Test StringMapEntry::Create() method.
  159. TEST_F(StringMapTest, StringMapEntryTest) {
  160. StringMap<uint32_t>::value_type* entry =
  161. StringMap<uint32_t>::value_type::Create(
  162. StringRef(testKeyFirst, testKeyLength), 1u);
  163. EXPECT_STREQ(testKey, entry->first().data());
  164. EXPECT_EQ(1u, entry->second);
  165. free(entry);
  166. }
  167. // Test insert() method.
  168. TEST_F(StringMapTest, InsertTest) {
  169. SCOPED_TRACE("InsertTest");
  170. testMap.insert(
  171. StringMap<uint32_t>::value_type::Create(
  172. StringRef(testKeyFirst, testKeyLength),
  173. testMap.getAllocator(), 1u));
  174. assertSingleItemMap();
  175. }
  176. // Test insert(pair<K, V>) method
  177. TEST_F(StringMapTest, InsertPairTest) {
  178. bool Inserted;
  179. StringMap<uint32_t>::iterator NewIt;
  180. std::tie(NewIt, Inserted) =
  181. testMap.insert(std::make_pair(testKeyFirst, testValue));
  182. EXPECT_EQ(1u, testMap.size());
  183. EXPECT_EQ(testValue, testMap[testKeyFirst]);
  184. EXPECT_EQ(testKeyFirst, NewIt->first());
  185. EXPECT_EQ(testValue, NewIt->second);
  186. EXPECT_TRUE(Inserted);
  187. StringMap<uint32_t>::iterator ExistingIt;
  188. std::tie(ExistingIt, Inserted) =
  189. testMap.insert(std::make_pair(testKeyFirst, testValue + 1));
  190. EXPECT_EQ(1u, testMap.size());
  191. EXPECT_EQ(testValue, testMap[testKeyFirst]);
  192. EXPECT_FALSE(Inserted);
  193. EXPECT_EQ(NewIt, ExistingIt);
  194. }
  195. // Test insert(pair<K, V>) method when rehashing occurs
  196. TEST_F(StringMapTest, InsertRehashingPairTest) {
  197. // Check that the correct iterator is returned when the inserted element is
  198. // moved to a different bucket during internal rehashing. This depends on
  199. // the particular key, and the implementation of StringMap and HashString.
  200. // Changes to those might result in this test not actually checking that.
  201. StringMap<uint32_t> t(1);
  202. EXPECT_EQ(1u, t.getNumBuckets());
  203. StringMap<uint32_t>::iterator It =
  204. t.insert(std::make_pair("abcdef", 42)).first;
  205. EXPECT_EQ(2u, t.getNumBuckets());
  206. EXPECT_EQ("abcdef", It->first());
  207. EXPECT_EQ(42u, It->second);
  208. }
  209. // Create a non-default constructable value
  210. struct StringMapTestStruct {
  211. StringMapTestStruct(int i) : i(i) {}
  212. StringMapTestStruct() = delete;
  213. int i;
  214. };
  215. TEST_F(StringMapTest, NonDefaultConstructable) {
  216. StringMap<StringMapTestStruct> t;
  217. t.insert(std::make_pair("Test", StringMapTestStruct(123)));
  218. StringMap<StringMapTestStruct>::iterator iter = t.find("Test");
  219. ASSERT_NE(iter, t.end());
  220. ASSERT_EQ(iter->second.i, 123);
  221. }
  222. struct Immovable {
  223. Immovable() {}
  224. Immovable(Immovable&&) = delete; // will disable the other special members
  225. };
  226. struct MoveOnly {
  227. int i;
  228. MoveOnly(int i) : i(i) {}
  229. MoveOnly(const Immovable&) : i(0) {}
  230. MoveOnly(MoveOnly &&RHS) : i(RHS.i) {}
  231. MoveOnly &operator=(MoveOnly &&RHS) {
  232. i = RHS.i;
  233. return *this;
  234. }
  235. private:
  236. MoveOnly(const MoveOnly &) = delete;
  237. MoveOnly &operator=(const MoveOnly &) = delete;
  238. };
  239. TEST_F(StringMapTest, MoveOnly) {
  240. StringMap<MoveOnly> t;
  241. t.insert(std::make_pair("Test", MoveOnly(42)));
  242. StringRef Key = "Test";
  243. StringMapEntry<MoveOnly>::Create(Key, MoveOnly(42))
  244. ->Destroy();
  245. }
  246. TEST_F(StringMapTest, CtorArg) {
  247. StringRef Key = "Test";
  248. StringMapEntry<MoveOnly>::Create(Key, Immovable())
  249. ->Destroy();
  250. }
  251. TEST_F(StringMapTest, MoveConstruct) {
  252. StringMap<int> A;
  253. A["x"] = 42;
  254. StringMap<int> B = std::move(A);
  255. ASSERT_EQ(A.size(), 0u);
  256. ASSERT_EQ(B.size(), 1u);
  257. ASSERT_EQ(B["x"], 42);
  258. ASSERT_EQ(B.count("y"), 0u);
  259. }
  260. TEST_F(StringMapTest, MoveAssignment) {
  261. StringMap<int> A;
  262. A["x"] = 42;
  263. StringMap<int> B;
  264. B["y"] = 117;
  265. A = std::move(B);
  266. ASSERT_EQ(A.size(), 1u);
  267. ASSERT_EQ(B.size(), 0u);
  268. ASSERT_EQ(A["y"], 117);
  269. ASSERT_EQ(B.count("x"), 0u);
  270. }
  271. struct Countable {
  272. int &InstanceCount;
  273. int Number;
  274. Countable(int Number, int &InstanceCount)
  275. : InstanceCount(InstanceCount), Number(Number) {
  276. ++InstanceCount;
  277. }
  278. Countable(Countable &&C) : InstanceCount(C.InstanceCount), Number(C.Number) {
  279. ++InstanceCount;
  280. C.Number = -1;
  281. }
  282. Countable(const Countable &C)
  283. : InstanceCount(C.InstanceCount), Number(C.Number) {
  284. ++InstanceCount;
  285. }
  286. Countable &operator=(Countable C) {
  287. Number = C.Number;
  288. return *this;
  289. }
  290. ~Countable() { --InstanceCount; }
  291. };
  292. TEST_F(StringMapTest, MoveDtor) {
  293. int InstanceCount = 0;
  294. StringMap<Countable> A;
  295. A.insert(std::make_pair("x", Countable(42, InstanceCount)));
  296. ASSERT_EQ(InstanceCount, 1);
  297. auto I = A.find("x");
  298. ASSERT_NE(I, A.end());
  299. ASSERT_EQ(I->second.Number, 42);
  300. StringMap<Countable> B;
  301. B = std::move(A);
  302. ASSERT_EQ(InstanceCount, 1);
  303. ASSERT_TRUE(A.empty());
  304. I = B.find("x");
  305. ASSERT_NE(I, B.end());
  306. ASSERT_EQ(I->second.Number, 42);
  307. B = StringMap<Countable>();
  308. ASSERT_EQ(InstanceCount, 0);
  309. ASSERT_TRUE(B.empty());
  310. }
  311. } // end anonymous namespace