blob: a44bbbfee0951e20f2a2570a947fc3b24dfc91fb [file] [log] [blame]
Bill Wendling1ed36632009-01-08 07:35:39 +00001//===- llvm/unittest/ADT/StringMapMap.cpp - StringMap unit tests ----------===//
Misha Brukman8bb5e992009-01-08 04:48:20 +00002//
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
Misha Brukman8bb5e992009-01-08 04:48:20 +000010#include "llvm/ADT/StringMap.h"
Zachary Turnerd10b8de2017-03-21 23:45:03 +000011#include "llvm/ADT/StringSet.h"
Mehdi Amini492acdd2016-04-16 07:51:28 +000012#include "llvm/ADT/Twine.h"
Michael J. Spencer1f6efa32010-11-29 18:16:10 +000013#include "llvm/Support/DataTypes.h"
Mehdi Amini492acdd2016-04-16 07:51:28 +000014#include "gtest/gtest.h"
Aaron Ballman03af6d42018-01-11 18:47:15 +000015#include <limits>
David Blaikie9dd6fee2014-06-23 18:28:53 +000016#include <tuple>
Misha Brukman8bb5e992009-01-08 04:48:20 +000017using namespace llvm;
18
19namespace {
20
21// Test fixture
22class StringMapTest : public testing::Test {
23protected:
24 StringMap<uint32_t> testMap;
25
26 static const char testKey[];
27 static const uint32_t testValue;
28 static const char* testKeyFirst;
Daniel Dunbar6316fbc2009-07-23 18:17:34 +000029 static size_t testKeyLength;
Misha Brukman8bb5e992009-01-08 04:48:20 +000030 static const std::string testKeyStr;
31
32 void assertEmptyMap() {
33 // Size tests
34 EXPECT_EQ(0u, testMap.size());
35 EXPECT_TRUE(testMap.empty());
36
37 // Iterator tests
38 EXPECT_TRUE(testMap.begin() == testMap.end());
39
40 // Lookup tests
41 EXPECT_EQ(0u, testMap.count(testKey));
Daniel Dunbar6316fbc2009-07-23 18:17:34 +000042 EXPECT_EQ(0u, testMap.count(StringRef(testKeyFirst, testKeyLength)));
Misha Brukman8bb5e992009-01-08 04:48:20 +000043 EXPECT_EQ(0u, testMap.count(testKeyStr));
44 EXPECT_TRUE(testMap.find(testKey) == testMap.end());
Daniel Dunbar6316fbc2009-07-23 18:17:34 +000045 EXPECT_TRUE(testMap.find(StringRef(testKeyFirst, testKeyLength)) ==
46 testMap.end());
Misha Brukman8bb5e992009-01-08 04:48:20 +000047 EXPECT_TRUE(testMap.find(testKeyStr) == testMap.end());
48 }
49
50 void assertSingleItemMap() {
51 // Size tests
52 EXPECT_EQ(1u, testMap.size());
53 EXPECT_FALSE(testMap.begin() == testMap.end());
54 EXPECT_FALSE(testMap.empty());
55
56 // Iterator tests
57 StringMap<uint32_t>::iterator it = testMap.begin();
Chris Lattnerd7c02732011-07-14 18:31:43 +000058 EXPECT_STREQ(testKey, it->first().data());
Misha Brukman8bb5e992009-01-08 04:48:20 +000059 EXPECT_EQ(testValue, it->second);
60 ++it;
61 EXPECT_TRUE(it == testMap.end());
62
63 // Lookup tests
64 EXPECT_EQ(1u, testMap.count(testKey));
Daniel Dunbar6316fbc2009-07-23 18:17:34 +000065 EXPECT_EQ(1u, testMap.count(StringRef(testKeyFirst, testKeyLength)));
Misha Brukman8bb5e992009-01-08 04:48:20 +000066 EXPECT_EQ(1u, testMap.count(testKeyStr));
67 EXPECT_TRUE(testMap.find(testKey) == testMap.begin());
Daniel Dunbar6316fbc2009-07-23 18:17:34 +000068 EXPECT_TRUE(testMap.find(StringRef(testKeyFirst, testKeyLength)) ==
69 testMap.begin());
Misha Brukman8bb5e992009-01-08 04:48:20 +000070 EXPECT_TRUE(testMap.find(testKeyStr) == testMap.begin());
71 }
72};
73
74const char StringMapTest::testKey[] = "key";
75const uint32_t StringMapTest::testValue = 1u;
76const char* StringMapTest::testKeyFirst = testKey;
Daniel Dunbar6316fbc2009-07-23 18:17:34 +000077size_t StringMapTest::testKeyLength = sizeof(testKey) - 1;
Misha Brukman8bb5e992009-01-08 04:48:20 +000078const std::string StringMapTest::testKeyStr(testKey);
79
Bill Wendling6b223d72009-01-08 09:31:36 +000080// Empty map tests.
Misha Brukman8bb5e992009-01-08 04:48:20 +000081TEST_F(StringMapTest, EmptyMapTest) {
Misha Brukman8bb5e992009-01-08 04:48:20 +000082 assertEmptyMap();
83}
84
Bill Wendling6b223d72009-01-08 09:31:36 +000085// Constant map tests.
Misha Brukman8bb5e992009-01-08 04:48:20 +000086TEST_F(StringMapTest, ConstEmptyMapTest) {
87 const StringMap<uint32_t>& constTestMap = testMap;
88
89 // Size tests
90 EXPECT_EQ(0u, constTestMap.size());
91 EXPECT_TRUE(constTestMap.empty());
92
93 // Iterator tests
94 EXPECT_TRUE(constTestMap.begin() == constTestMap.end());
95
96 // Lookup tests
97 EXPECT_EQ(0u, constTestMap.count(testKey));
Daniel Dunbar6316fbc2009-07-23 18:17:34 +000098 EXPECT_EQ(0u, constTestMap.count(StringRef(testKeyFirst, testKeyLength)));
Misha Brukman8bb5e992009-01-08 04:48:20 +000099 EXPECT_EQ(0u, constTestMap.count(testKeyStr));
100 EXPECT_TRUE(constTestMap.find(testKey) == constTestMap.end());
Daniel Dunbar6316fbc2009-07-23 18:17:34 +0000101 EXPECT_TRUE(constTestMap.find(StringRef(testKeyFirst, testKeyLength)) ==
Bill Wendling6b223d72009-01-08 09:31:36 +0000102 constTestMap.end());
Misha Brukman8bb5e992009-01-08 04:48:20 +0000103 EXPECT_TRUE(constTestMap.find(testKeyStr) == constTestMap.end());
104}
105
Bill Wendling6b223d72009-01-08 09:31:36 +0000106// A map with a single entry.
Misha Brukman8bb5e992009-01-08 04:48:20 +0000107TEST_F(StringMapTest, SingleEntryMapTest) {
Misha Brukman8bb5e992009-01-08 04:48:20 +0000108 testMap[testKey] = testValue;
109 assertSingleItemMap();
110}
111
Bill Wendling6b223d72009-01-08 09:31:36 +0000112// Test clear() method.
Misha Brukman8bb5e992009-01-08 04:48:20 +0000113TEST_F(StringMapTest, ClearTest) {
Misha Brukman8bb5e992009-01-08 04:48:20 +0000114 testMap[testKey] = testValue;
115 testMap.clear();
116 assertEmptyMap();
117}
118
Bill Wendling6b223d72009-01-08 09:31:36 +0000119// Test erase(iterator) method.
Misha Brukman8bb5e992009-01-08 04:48:20 +0000120TEST_F(StringMapTest, EraseIteratorTest) {
Misha Brukman8bb5e992009-01-08 04:48:20 +0000121 testMap[testKey] = testValue;
122 testMap.erase(testMap.begin());
123 assertEmptyMap();
124}
125
Bill Wendling6b223d72009-01-08 09:31:36 +0000126// Test erase(value) method.
Misha Brukman8bb5e992009-01-08 04:48:20 +0000127TEST_F(StringMapTest, EraseValueTest) {
Misha Brukman8bb5e992009-01-08 04:48:20 +0000128 testMap[testKey] = testValue;
129 testMap.erase(testKey);
130 assertEmptyMap();
131}
132
Bill Wendling6b223d72009-01-08 09:31:36 +0000133// Test inserting two values and erasing one.
Misha Brukman8bb5e992009-01-08 04:48:20 +0000134TEST_F(StringMapTest, InsertAndEraseTest) {
Misha Brukman8bb5e992009-01-08 04:48:20 +0000135 testMap[testKey] = testValue;
136 testMap["otherKey"] = 2;
137 testMap.erase("otherKey");
138 assertSingleItemMap();
139}
140
Chandler Carruth2a791162012-06-19 17:40:35 +0000141TEST_F(StringMapTest, SmallFullMapTest) {
142 // StringMap has a tricky corner case when the map is small (<8 buckets) and
143 // it fills up through a balanced pattern of inserts and erases. This can
144 // lead to inf-loops in some cases (PR13148) so we test it explicitly here.
145 llvm::StringMap<int> Map(2);
146
147 Map["eins"] = 1;
148 Map["zwei"] = 2;
149 Map["drei"] = 3;
150 Map.erase("drei");
151 Map.erase("eins");
152 Map["veir"] = 4;
153 Map["funf"] = 5;
154
155 EXPECT_EQ(3u, Map.size());
156 EXPECT_EQ(0, Map.lookup("eins"));
157 EXPECT_EQ(2, Map.lookup("zwei"));
158 EXPECT_EQ(0, Map.lookup("drei"));
159 EXPECT_EQ(4, Map.lookup("veir"));
160 EXPECT_EQ(5, Map.lookup("funf"));
161}
162
Hal Finkelf5526fc2016-03-30 19:54:56 +0000163TEST_F(StringMapTest, CopyCtorTest) {
164 llvm::StringMap<int> Map;
165
166 Map["eins"] = 1;
167 Map["zwei"] = 2;
168 Map["drei"] = 3;
169 Map.erase("drei");
170 Map.erase("eins");
171 Map["veir"] = 4;
172 Map["funf"] = 5;
173
174 EXPECT_EQ(3u, Map.size());
175 EXPECT_EQ(0, Map.lookup("eins"));
176 EXPECT_EQ(2, Map.lookup("zwei"));
177 EXPECT_EQ(0, Map.lookup("drei"));
178 EXPECT_EQ(4, Map.lookup("veir"));
179 EXPECT_EQ(5, Map.lookup("funf"));
180
181 llvm::StringMap<int> Map2(Map);
182 EXPECT_EQ(3u, Map2.size());
183 EXPECT_EQ(0, Map2.lookup("eins"));
184 EXPECT_EQ(2, Map2.lookup("zwei"));
185 EXPECT_EQ(0, Map2.lookup("drei"));
186 EXPECT_EQ(4, Map2.lookup("veir"));
187 EXPECT_EQ(5, Map2.lookup("funf"));
188}
189
Bill Wendling6b223d72009-01-08 09:31:36 +0000190// A more complex iteration test.
Misha Brukman8bb5e992009-01-08 04:48:20 +0000191TEST_F(StringMapTest, IterationTest) {
192 bool visited[100];
193
194 // Insert 100 numbers into the map
195 for (int i = 0; i < 100; ++i) {
196 std::stringstream ss;
197 ss << "key_" << i;
198 testMap[ss.str()] = i;
199 visited[i] = false;
200 }
201
202 // Iterate over all numbers and mark each one found.
203 for (StringMap<uint32_t>::iterator it = testMap.begin();
204 it != testMap.end(); ++it) {
205 std::stringstream ss;
206 ss << "key_" << it->second;
Chris Lattnerd7c02732011-07-14 18:31:43 +0000207 ASSERT_STREQ(ss.str().c_str(), it->first().data());
Misha Brukman8bb5e992009-01-08 04:48:20 +0000208 visited[it->second] = true;
209 }
210
211 // Ensure every number was visited.
212 for (int i = 0; i < 100; ++i) {
213 ASSERT_TRUE(visited[i]) << "Entry #" << i << " was never visited";
214 }
215}
216
Bill Wendling6b223d72009-01-08 09:31:36 +0000217// Test StringMapEntry::Create() method.
218TEST_F(StringMapTest, StringMapEntryTest) {
219 StringMap<uint32_t>::value_type* entry =
220 StringMap<uint32_t>::value_type::Create(
Craig Topper27be15c2014-06-11 05:35:56 +0000221 StringRef(testKeyFirst, testKeyLength), 1u);
Chris Lattnerd7c02732011-07-14 18:31:43 +0000222 EXPECT_STREQ(testKey, entry->first().data());
Bill Wendling6b223d72009-01-08 09:31:36 +0000223 EXPECT_EQ(1u, entry->second);
Jeffrey Yasskind8735352010-02-11 07:16:13 +0000224 free(entry);
Misha Brukman8bb5e992009-01-08 04:48:20 +0000225}
Bill Wendling6b223d72009-01-08 09:31:36 +0000226
227// Test insert() method.
228TEST_F(StringMapTest, InsertTest) {
229 SCOPED_TRACE("InsertTest");
230 testMap.insert(
231 StringMap<uint32_t>::value_type::Create(
Craig Topper27be15c2014-06-11 05:35:56 +0000232 StringRef(testKeyFirst, testKeyLength),
Daniel Dunbar6316fbc2009-07-23 18:17:34 +0000233 testMap.getAllocator(), 1u));
Bill Wendling6b223d72009-01-08 09:31:36 +0000234 assertSingleItemMap();
235}
236
David Blaikie9dd6fee2014-06-23 18:28:53 +0000237// Test insert(pair<K, V>) method
238TEST_F(StringMapTest, InsertPairTest) {
239 bool Inserted;
240 StringMap<uint32_t>::iterator NewIt;
241 std::tie(NewIt, Inserted) =
242 testMap.insert(std::make_pair(testKeyFirst, testValue));
243 EXPECT_EQ(1u, testMap.size());
244 EXPECT_EQ(testValue, testMap[testKeyFirst]);
245 EXPECT_EQ(testKeyFirst, NewIt->first());
246 EXPECT_EQ(testValue, NewIt->second);
247 EXPECT_TRUE(Inserted);
248
249 StringMap<uint32_t>::iterator ExistingIt;
250 std::tie(ExistingIt, Inserted) =
251 testMap.insert(std::make_pair(testKeyFirst, testValue + 1));
252 EXPECT_EQ(1u, testMap.size());
253 EXPECT_EQ(testValue, testMap[testKeyFirst]);
254 EXPECT_FALSE(Inserted);
255 EXPECT_EQ(NewIt, ExistingIt);
256}
257
258// Test insert(pair<K, V>) method when rehashing occurs
259TEST_F(StringMapTest, InsertRehashingPairTest) {
260 // Check that the correct iterator is returned when the inserted element is
261 // moved to a different bucket during internal rehashing. This depends on
262 // the particular key, and the implementation of StringMap and HashString.
263 // Changes to those might result in this test not actually checking that.
Mehdi Aminibf941ea2016-03-25 05:57:57 +0000264 StringMap<uint32_t> t(0);
265 EXPECT_EQ(0u, t.getNumBuckets());
David Blaikie9dd6fee2014-06-23 18:28:53 +0000266
267 StringMap<uint32_t>::iterator It =
268 t.insert(std::make_pair("abcdef", 42)).first;
Mehdi Aminibf941ea2016-03-25 05:57:57 +0000269 EXPECT_EQ(16u, t.getNumBuckets());
David Blaikie9dd6fee2014-06-23 18:28:53 +0000270 EXPECT_EQ("abcdef", It->first());
271 EXPECT_EQ(42u, It->second);
272}
273
Zachary Turnerd10b8de2017-03-21 23:45:03 +0000274TEST_F(StringMapTest, IterMapKeys) {
275 StringMap<int> Map;
276 Map["A"] = 1;
277 Map["B"] = 2;
278 Map["C"] = 3;
279 Map["D"] = 3;
280
281 auto Keys = to_vector<4>(Map.keys());
Fangrui Song3b35e172018-09-27 02:13:45 +0000282 llvm::sort(Keys);
Zachary Turnerd10b8de2017-03-21 23:45:03 +0000283
284 SmallVector<StringRef, 4> Expected = {"A", "B", "C", "D"};
285 EXPECT_EQ(Expected, Keys);
286}
287
288TEST_F(StringMapTest, IterSetKeys) {
289 StringSet<> Set;
290 Set.insert("A");
291 Set.insert("B");
292 Set.insert("C");
293 Set.insert("D");
294
295 auto Keys = to_vector<4>(Set.keys());
Fangrui Song3b35e172018-09-27 02:13:45 +0000296 llvm::sort(Keys);
Zachary Turnerd10b8de2017-03-21 23:45:03 +0000297
298 SmallVector<StringRef, 4> Expected = {"A", "B", "C", "D"};
299 EXPECT_EQ(Expected, Keys);
300}
301
David Blaikie4c9b6812014-01-02 23:57:28 +0000302// Create a non-default constructable value
David Blaikie30342182014-01-03 00:00:41 +0000303struct StringMapTestStruct {
304 StringMapTestStruct(int i) : i(i) {}
Aaron Ballman66981fe2015-02-15 22:54:22 +0000305 StringMapTestStruct() = delete;
David Blaikie30342182014-01-03 00:00:41 +0000306 int i;
307};
David Blaikie4c9b6812014-01-02 23:57:28 +0000308
David Blaikie30342182014-01-03 00:00:41 +0000309TEST_F(StringMapTest, NonDefaultConstructable) {
David Blaikie4c9b6812014-01-02 23:57:28 +0000310 StringMap<StringMapTestStruct> t;
David Blaikie1d4f28c2014-11-19 05:49:42 +0000311 t.insert(std::make_pair("Test", StringMapTestStruct(123)));
David Blaikie4c9b6812014-01-02 23:57:28 +0000312 StringMap<StringMapTestStruct>::iterator iter = t.find("Test");
313 ASSERT_NE(iter, t.end());
314 ASSERT_EQ(iter->second.i, 123);
315}
316
David Blaikie79876832014-11-14 00:41:46 +0000317struct Immovable {
318 Immovable() {}
Aaron Ballman66981fe2015-02-15 22:54:22 +0000319 Immovable(Immovable&&) = delete; // will disable the other special members
David Blaikie79876832014-11-14 00:41:46 +0000320};
321
David Blaikieb0439e62014-05-08 21:52:23 +0000322struct MoveOnly {
323 int i;
324 MoveOnly(int i) : i(i) {}
David Blaikie79876832014-11-14 00:41:46 +0000325 MoveOnly(const Immovable&) : i(0) {}
David Blaikie3fb66ae2014-05-09 02:26:36 +0000326 MoveOnly(MoveOnly &&RHS) : i(RHS.i) {}
327 MoveOnly &operator=(MoveOnly &&RHS) {
328 i = RHS.i;
329 return *this;
330 }
331
332private:
Aaron Ballman66981fe2015-02-15 22:54:22 +0000333 MoveOnly(const MoveOnly &) = delete;
334 MoveOnly &operator=(const MoveOnly &) = delete;
David Blaikieb0439e62014-05-08 21:52:23 +0000335};
336
David Blaikie79876832014-11-14 00:41:46 +0000337TEST_F(StringMapTest, MoveOnly) {
David Blaikieb0439e62014-05-08 21:52:23 +0000338 StringMap<MoveOnly> t;
David Blaikie1d4f28c2014-11-19 05:49:42 +0000339 t.insert(std::make_pair("Test", MoveOnly(42)));
David Blaikieb0439e62014-05-08 21:52:23 +0000340 StringRef Key = "Test";
Craig Topper27be15c2014-06-11 05:35:56 +0000341 StringMapEntry<MoveOnly>::Create(Key, MoveOnly(42))
David Blaikie50f8a532014-05-08 21:53:33 +0000342 ->Destroy();
David Blaikieb0439e62014-05-08 21:52:23 +0000343}
344
David Blaikie79876832014-11-14 00:41:46 +0000345TEST_F(StringMapTest, CtorArg) {
David Blaikie79876832014-11-14 00:41:46 +0000346 StringRef Key = "Test";
347 StringMapEntry<MoveOnly>::Create(Key, Immovable())
348 ->Destroy();
349}
350
David Blaikie2b94fa72014-05-08 21:52:29 +0000351TEST_F(StringMapTest, MoveConstruct) {
352 StringMap<int> A;
David Blaikie1d4f28c2014-11-19 05:49:42 +0000353 A["x"] = 42;
David Blaikie2b94fa72014-05-08 21:52:29 +0000354 StringMap<int> B = std::move(A);
355 ASSERT_EQ(A.size(), 0u);
356 ASSERT_EQ(B.size(), 1u);
357 ASSERT_EQ(B["x"], 42);
358 ASSERT_EQ(B.count("y"), 0u);
359}
360
361TEST_F(StringMapTest, MoveAssignment) {
362 StringMap<int> A;
363 A["x"] = 42;
364 StringMap<int> B;
365 B["y"] = 117;
366 A = std::move(B);
367 ASSERT_EQ(A.size(), 1u);
368 ASSERT_EQ(B.size(), 0u);
369 ASSERT_EQ(A["y"], 117);
370 ASSERT_EQ(B.count("x"), 0u);
371}
372
373struct Countable {
374 int &InstanceCount;
375 int Number;
David Blaikie50f8a532014-05-08 21:53:33 +0000376 Countable(int Number, int &InstanceCount)
377 : InstanceCount(InstanceCount), Number(Number) {
David Blaikie2b94fa72014-05-08 21:52:29 +0000378 ++InstanceCount;
379 }
380 Countable(Countable &&C) : InstanceCount(C.InstanceCount), Number(C.Number) {
381 ++InstanceCount;
382 C.Number = -1;
383 }
David Blaikie50f8a532014-05-08 21:53:33 +0000384 Countable(const Countable &C)
385 : InstanceCount(C.InstanceCount), Number(C.Number) {
David Blaikie2b94fa72014-05-08 21:52:29 +0000386 ++InstanceCount;
387 }
388 Countable &operator=(Countable C) {
389 Number = C.Number;
390 return *this;
391 }
David Blaikie50f8a532014-05-08 21:53:33 +0000392 ~Countable() { --InstanceCount; }
David Blaikie2b94fa72014-05-08 21:52:29 +0000393};
394
395TEST_F(StringMapTest, MoveDtor) {
396 int InstanceCount = 0;
397 StringMap<Countable> A;
David Blaikie1d4f28c2014-11-19 05:49:42 +0000398 A.insert(std::make_pair("x", Countable(42, InstanceCount)));
David Blaikie2b94fa72014-05-08 21:52:29 +0000399 ASSERT_EQ(InstanceCount, 1);
400 auto I = A.find("x");
401 ASSERT_NE(I, A.end());
402 ASSERT_EQ(I->second.Number, 42);
403
404 StringMap<Countable> B;
405 B = std::move(A);
406 ASSERT_EQ(InstanceCount, 1);
407 ASSERT_TRUE(A.empty());
408 I = B.find("x");
409 ASSERT_NE(I, B.end());
410 ASSERT_EQ(I->second.Number, 42);
411
412 B = StringMap<Countable>();
413 ASSERT_EQ(InstanceCount, 0);
414 ASSERT_TRUE(B.empty());
415}
416
Mehdi Aminibf941ea2016-03-25 05:57:57 +0000417namespace {
418// Simple class that counts how many moves and copy happens when growing a map
Mehdi Amini25656752016-03-25 05:58:04 +0000419struct CountCtorCopyAndMove {
420 static unsigned Ctor;
Mehdi Aminibf941ea2016-03-25 05:57:57 +0000421 static unsigned Move;
422 static unsigned Copy;
Mehdi Amini25656752016-03-25 05:58:04 +0000423 int Data = 0;
424 CountCtorCopyAndMove(int Data) : Data(Data) { Ctor++; }
425 CountCtorCopyAndMove() { Ctor++; }
Mehdi Aminibf941ea2016-03-25 05:57:57 +0000426
Mehdi Amini25656752016-03-25 05:58:04 +0000427 CountCtorCopyAndMove(const CountCtorCopyAndMove &) { Copy++; }
428 CountCtorCopyAndMove &operator=(const CountCtorCopyAndMove &) {
Mehdi Aminibf941ea2016-03-25 05:57:57 +0000429 Copy++;
430 return *this;
431 }
Mehdi Amini25656752016-03-25 05:58:04 +0000432 CountCtorCopyAndMove(CountCtorCopyAndMove &&) { Move++; }
433 CountCtorCopyAndMove &operator=(const CountCtorCopyAndMove &&) {
Mehdi Aminibf941ea2016-03-25 05:57:57 +0000434 Move++;
435 return *this;
436 }
437};
Mehdi Amini25656752016-03-25 05:58:04 +0000438unsigned CountCtorCopyAndMove::Copy = 0;
439unsigned CountCtorCopyAndMove::Move = 0;
440unsigned CountCtorCopyAndMove::Ctor = 0;
Mehdi Aminibf941ea2016-03-25 05:57:57 +0000441
442} // anonymous namespace
443
444// Make sure creating the map with an initial size of N actually gives us enough
445// buckets to insert N items without increasing allocation size.
446TEST(StringMapCustomTest, InitialSizeTest) {
447 // 1 is an "edge value", 32 is an arbitrary power of two, and 67 is an
448 // arbitrary prime, picked without any good reason.
449 for (auto Size : {1, 32, 67}) {
Mehdi Amini25656752016-03-25 05:58:04 +0000450 StringMap<CountCtorCopyAndMove> Map(Size);
Mehdi Aminidf98afd2016-03-25 16:09:34 +0000451 auto NumBuckets = Map.getNumBuckets();
Mehdi Amini25656752016-03-25 05:58:04 +0000452 CountCtorCopyAndMove::Move = 0;
453 CountCtorCopyAndMove::Copy = 0;
Mehdi Aminibf941ea2016-03-25 05:57:57 +0000454 for (int i = 0; i < Size; ++i)
Mehdi Amini64f92382016-03-25 23:25:06 +0000455 Map.insert(std::pair<std::string, CountCtorCopyAndMove>(
456 std::piecewise_construct, std::forward_as_tuple(Twine(i).str()),
457 std::forward_as_tuple(i)));
Simon Pilgrim8d28e342017-03-31 10:59:37 +0000458 // After the initial move, the map will move the Elts in the Entry.
Mehdi Amini64f92382016-03-25 23:25:06 +0000459 EXPECT_EQ((unsigned)Size * 2, CountCtorCopyAndMove::Move);
Mehdi Aminiff9b2312016-03-25 16:36:00 +0000460 // We copy once the pair from the Elts vector
Mehdi Amini64f92382016-03-25 23:25:06 +0000461 EXPECT_EQ(0u, CountCtorCopyAndMove::Copy);
Mehdi Aminidf98afd2016-03-25 16:09:34 +0000462 // Check that the map didn't grow
463 EXPECT_EQ(Map.getNumBuckets(), NumBuckets);
Mehdi Aminibf941ea2016-03-25 05:57:57 +0000464 }
465}
466
Mehdi Amini25656752016-03-25 05:58:04 +0000467TEST(StringMapCustomTest, BracketOperatorCtor) {
468 StringMap<CountCtorCopyAndMove> Map;
469 CountCtorCopyAndMove::Ctor = 0;
470 Map["abcd"];
471 EXPECT_EQ(1u, CountCtorCopyAndMove::Ctor);
472 // Test that operator[] does not create a value when it is already in the map
473 CountCtorCopyAndMove::Ctor = 0;
474 Map["abcd"];
475 EXPECT_EQ(0u, CountCtorCopyAndMove::Ctor);
476}
477
478namespace {
479struct NonMoveableNonCopyableType {
480 int Data = 0;
481 NonMoveableNonCopyableType() = default;
482 NonMoveableNonCopyableType(int Data) : Data(Data) {}
483 NonMoveableNonCopyableType(const NonMoveableNonCopyableType &) = delete;
484 NonMoveableNonCopyableType(NonMoveableNonCopyableType &&) = delete;
485};
486}
487
488// Test that we can "emplace" an element in the map without involving map/move
489TEST(StringMapCustomTest, EmplaceTest) {
490 StringMap<NonMoveableNonCopyableType> Map;
Benjamin Kramerb11b3522016-07-21 13:37:48 +0000491 Map.try_emplace("abcd", 42);
Mehdi Amini25656752016-03-25 05:58:04 +0000492 EXPECT_EQ(1u, Map.count("abcd"));
493 EXPECT_EQ(42, Map["abcd"].Data);
494}
495
Aaron Ballman03af6d42018-01-11 18:47:15 +0000496// Test that StringMapEntryBase can handle size_t wide sizes.
497TEST(StringMapCustomTest, StringMapEntryBaseSize) {
498 size_t LargeValue;
499
500 // Test that the entry can represent max-unsigned.
501 if (sizeof(size_t) <= sizeof(unsigned))
502 LargeValue = std::numeric_limits<unsigned>::max();
503 else
504 LargeValue = std::numeric_limits<unsigned>::max() + 1ULL;
505 StringMapEntryBase LargeBase(LargeValue);
506 EXPECT_EQ(LargeValue, LargeBase.getKeyLength());
507
508 // Test that the entry can hold at least max size_t.
509 LargeValue = std::numeric_limits<size_t>::max();
510 StringMapEntryBase LargerBase(LargeValue);
511 LargeValue = std::numeric_limits<size_t>::max();
512 EXPECT_EQ(LargeValue, LargerBase.getKeyLength());
513}
514
515// Test that StringMapEntry can handle size_t wide sizes.
516TEST(StringMapCustomTest, StringMapEntrySize) {
517 size_t LargeValue;
518
519 // Test that the entry can represent max-unsigned.
520 if (sizeof(size_t) <= sizeof(unsigned))
521 LargeValue = std::numeric_limits<unsigned>::max();
522 else
523 LargeValue = std::numeric_limits<unsigned>::max() + 1ULL;
524 StringMapEntry<int> LargeEntry(LargeValue);
525 StringRef Key = LargeEntry.getKey();
526 EXPECT_EQ(LargeValue, Key.size());
527
528 // Test that the entry can hold at least max size_t.
529 LargeValue = std::numeric_limits<size_t>::max();
530 StringMapEntry<int> LargerEntry(LargeValue);
531 Key = LargerEntry.getKey();
532 EXPECT_EQ(LargeValue, Key.size());
533}
534
Bill Wendling6b223d72009-01-08 09:31:36 +0000535} // end anonymous namespace