1*9880d681SAndroid Build Coastguard Worker //===- llvm/unittest/ADT/StringMapMap.cpp - StringMap unit tests ----------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker
10*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/StringMap.h"
11*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Twine.h"
12*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/DataTypes.h"
13*9880d681SAndroid Build Coastguard Worker #include "gtest/gtest.h"
14*9880d681SAndroid Build Coastguard Worker #include <tuple>
15*9880d681SAndroid Build Coastguard Worker using namespace llvm;
16*9880d681SAndroid Build Coastguard Worker
17*9880d681SAndroid Build Coastguard Worker namespace {
18*9880d681SAndroid Build Coastguard Worker
19*9880d681SAndroid Build Coastguard Worker // Test fixture
20*9880d681SAndroid Build Coastguard Worker class StringMapTest : public testing::Test {
21*9880d681SAndroid Build Coastguard Worker protected:
22*9880d681SAndroid Build Coastguard Worker StringMap<uint32_t> testMap;
23*9880d681SAndroid Build Coastguard Worker
24*9880d681SAndroid Build Coastguard Worker static const char testKey[];
25*9880d681SAndroid Build Coastguard Worker static const uint32_t testValue;
26*9880d681SAndroid Build Coastguard Worker static const char* testKeyFirst;
27*9880d681SAndroid Build Coastguard Worker static size_t testKeyLength;
28*9880d681SAndroid Build Coastguard Worker static const std::string testKeyStr;
29*9880d681SAndroid Build Coastguard Worker
assertEmptyMap()30*9880d681SAndroid Build Coastguard Worker void assertEmptyMap() {
31*9880d681SAndroid Build Coastguard Worker // Size tests
32*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(0u, testMap.size());
33*9880d681SAndroid Build Coastguard Worker EXPECT_TRUE(testMap.empty());
34*9880d681SAndroid Build Coastguard Worker
35*9880d681SAndroid Build Coastguard Worker // Iterator tests
36*9880d681SAndroid Build Coastguard Worker EXPECT_TRUE(testMap.begin() == testMap.end());
37*9880d681SAndroid Build Coastguard Worker
38*9880d681SAndroid Build Coastguard Worker // Lookup tests
39*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(0u, testMap.count(testKey));
40*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(0u, testMap.count(StringRef(testKeyFirst, testKeyLength)));
41*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(0u, testMap.count(testKeyStr));
42*9880d681SAndroid Build Coastguard Worker EXPECT_TRUE(testMap.find(testKey) == testMap.end());
43*9880d681SAndroid Build Coastguard Worker EXPECT_TRUE(testMap.find(StringRef(testKeyFirst, testKeyLength)) ==
44*9880d681SAndroid Build Coastguard Worker testMap.end());
45*9880d681SAndroid Build Coastguard Worker EXPECT_TRUE(testMap.find(testKeyStr) == testMap.end());
46*9880d681SAndroid Build Coastguard Worker }
47*9880d681SAndroid Build Coastguard Worker
assertSingleItemMap()48*9880d681SAndroid Build Coastguard Worker void assertSingleItemMap() {
49*9880d681SAndroid Build Coastguard Worker // Size tests
50*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(1u, testMap.size());
51*9880d681SAndroid Build Coastguard Worker EXPECT_FALSE(testMap.begin() == testMap.end());
52*9880d681SAndroid Build Coastguard Worker EXPECT_FALSE(testMap.empty());
53*9880d681SAndroid Build Coastguard Worker
54*9880d681SAndroid Build Coastguard Worker // Iterator tests
55*9880d681SAndroid Build Coastguard Worker StringMap<uint32_t>::iterator it = testMap.begin();
56*9880d681SAndroid Build Coastguard Worker EXPECT_STREQ(testKey, it->first().data());
57*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(testValue, it->second);
58*9880d681SAndroid Build Coastguard Worker ++it;
59*9880d681SAndroid Build Coastguard Worker EXPECT_TRUE(it == testMap.end());
60*9880d681SAndroid Build Coastguard Worker
61*9880d681SAndroid Build Coastguard Worker // Lookup tests
62*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(1u, testMap.count(testKey));
63*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(1u, testMap.count(StringRef(testKeyFirst, testKeyLength)));
64*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(1u, testMap.count(testKeyStr));
65*9880d681SAndroid Build Coastguard Worker EXPECT_TRUE(testMap.find(testKey) == testMap.begin());
66*9880d681SAndroid Build Coastguard Worker EXPECT_TRUE(testMap.find(StringRef(testKeyFirst, testKeyLength)) ==
67*9880d681SAndroid Build Coastguard Worker testMap.begin());
68*9880d681SAndroid Build Coastguard Worker EXPECT_TRUE(testMap.find(testKeyStr) == testMap.begin());
69*9880d681SAndroid Build Coastguard Worker }
70*9880d681SAndroid Build Coastguard Worker };
71*9880d681SAndroid Build Coastguard Worker
72*9880d681SAndroid Build Coastguard Worker const char StringMapTest::testKey[] = "key";
73*9880d681SAndroid Build Coastguard Worker const uint32_t StringMapTest::testValue = 1u;
74*9880d681SAndroid Build Coastguard Worker const char* StringMapTest::testKeyFirst = testKey;
75*9880d681SAndroid Build Coastguard Worker size_t StringMapTest::testKeyLength = sizeof(testKey) - 1;
76*9880d681SAndroid Build Coastguard Worker const std::string StringMapTest::testKeyStr(testKey);
77*9880d681SAndroid Build Coastguard Worker
78*9880d681SAndroid Build Coastguard Worker // Empty map tests.
TEST_F(StringMapTest,EmptyMapTest)79*9880d681SAndroid Build Coastguard Worker TEST_F(StringMapTest, EmptyMapTest) {
80*9880d681SAndroid Build Coastguard Worker assertEmptyMap();
81*9880d681SAndroid Build Coastguard Worker }
82*9880d681SAndroid Build Coastguard Worker
83*9880d681SAndroid Build Coastguard Worker // Constant map tests.
TEST_F(StringMapTest,ConstEmptyMapTest)84*9880d681SAndroid Build Coastguard Worker TEST_F(StringMapTest, ConstEmptyMapTest) {
85*9880d681SAndroid Build Coastguard Worker const StringMap<uint32_t>& constTestMap = testMap;
86*9880d681SAndroid Build Coastguard Worker
87*9880d681SAndroid Build Coastguard Worker // Size tests
88*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(0u, constTestMap.size());
89*9880d681SAndroid Build Coastguard Worker EXPECT_TRUE(constTestMap.empty());
90*9880d681SAndroid Build Coastguard Worker
91*9880d681SAndroid Build Coastguard Worker // Iterator tests
92*9880d681SAndroid Build Coastguard Worker EXPECT_TRUE(constTestMap.begin() == constTestMap.end());
93*9880d681SAndroid Build Coastguard Worker
94*9880d681SAndroid Build Coastguard Worker // Lookup tests
95*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(0u, constTestMap.count(testKey));
96*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(0u, constTestMap.count(StringRef(testKeyFirst, testKeyLength)));
97*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(0u, constTestMap.count(testKeyStr));
98*9880d681SAndroid Build Coastguard Worker EXPECT_TRUE(constTestMap.find(testKey) == constTestMap.end());
99*9880d681SAndroid Build Coastguard Worker EXPECT_TRUE(constTestMap.find(StringRef(testKeyFirst, testKeyLength)) ==
100*9880d681SAndroid Build Coastguard Worker constTestMap.end());
101*9880d681SAndroid Build Coastguard Worker EXPECT_TRUE(constTestMap.find(testKeyStr) == constTestMap.end());
102*9880d681SAndroid Build Coastguard Worker }
103*9880d681SAndroid Build Coastguard Worker
104*9880d681SAndroid Build Coastguard Worker // A map with a single entry.
TEST_F(StringMapTest,SingleEntryMapTest)105*9880d681SAndroid Build Coastguard Worker TEST_F(StringMapTest, SingleEntryMapTest) {
106*9880d681SAndroid Build Coastguard Worker testMap[testKey] = testValue;
107*9880d681SAndroid Build Coastguard Worker assertSingleItemMap();
108*9880d681SAndroid Build Coastguard Worker }
109*9880d681SAndroid Build Coastguard Worker
110*9880d681SAndroid Build Coastguard Worker // Test clear() method.
TEST_F(StringMapTest,ClearTest)111*9880d681SAndroid Build Coastguard Worker TEST_F(StringMapTest, ClearTest) {
112*9880d681SAndroid Build Coastguard Worker testMap[testKey] = testValue;
113*9880d681SAndroid Build Coastguard Worker testMap.clear();
114*9880d681SAndroid Build Coastguard Worker assertEmptyMap();
115*9880d681SAndroid Build Coastguard Worker }
116*9880d681SAndroid Build Coastguard Worker
117*9880d681SAndroid Build Coastguard Worker // Test erase(iterator) method.
TEST_F(StringMapTest,EraseIteratorTest)118*9880d681SAndroid Build Coastguard Worker TEST_F(StringMapTest, EraseIteratorTest) {
119*9880d681SAndroid Build Coastguard Worker testMap[testKey] = testValue;
120*9880d681SAndroid Build Coastguard Worker testMap.erase(testMap.begin());
121*9880d681SAndroid Build Coastguard Worker assertEmptyMap();
122*9880d681SAndroid Build Coastguard Worker }
123*9880d681SAndroid Build Coastguard Worker
124*9880d681SAndroid Build Coastguard Worker // Test erase(value) method.
TEST_F(StringMapTest,EraseValueTest)125*9880d681SAndroid Build Coastguard Worker TEST_F(StringMapTest, EraseValueTest) {
126*9880d681SAndroid Build Coastguard Worker testMap[testKey] = testValue;
127*9880d681SAndroid Build Coastguard Worker testMap.erase(testKey);
128*9880d681SAndroid Build Coastguard Worker assertEmptyMap();
129*9880d681SAndroid Build Coastguard Worker }
130*9880d681SAndroid Build Coastguard Worker
131*9880d681SAndroid Build Coastguard Worker // Test inserting two values and erasing one.
TEST_F(StringMapTest,InsertAndEraseTest)132*9880d681SAndroid Build Coastguard Worker TEST_F(StringMapTest, InsertAndEraseTest) {
133*9880d681SAndroid Build Coastguard Worker testMap[testKey] = testValue;
134*9880d681SAndroid Build Coastguard Worker testMap["otherKey"] = 2;
135*9880d681SAndroid Build Coastguard Worker testMap.erase("otherKey");
136*9880d681SAndroid Build Coastguard Worker assertSingleItemMap();
137*9880d681SAndroid Build Coastguard Worker }
138*9880d681SAndroid Build Coastguard Worker
TEST_F(StringMapTest,SmallFullMapTest)139*9880d681SAndroid Build Coastguard Worker TEST_F(StringMapTest, SmallFullMapTest) {
140*9880d681SAndroid Build Coastguard Worker // StringMap has a tricky corner case when the map is small (<8 buckets) and
141*9880d681SAndroid Build Coastguard Worker // it fills up through a balanced pattern of inserts and erases. This can
142*9880d681SAndroid Build Coastguard Worker // lead to inf-loops in some cases (PR13148) so we test it explicitly here.
143*9880d681SAndroid Build Coastguard Worker llvm::StringMap<int> Map(2);
144*9880d681SAndroid Build Coastguard Worker
145*9880d681SAndroid Build Coastguard Worker Map["eins"] = 1;
146*9880d681SAndroid Build Coastguard Worker Map["zwei"] = 2;
147*9880d681SAndroid Build Coastguard Worker Map["drei"] = 3;
148*9880d681SAndroid Build Coastguard Worker Map.erase("drei");
149*9880d681SAndroid Build Coastguard Worker Map.erase("eins");
150*9880d681SAndroid Build Coastguard Worker Map["veir"] = 4;
151*9880d681SAndroid Build Coastguard Worker Map["funf"] = 5;
152*9880d681SAndroid Build Coastguard Worker
153*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(3u, Map.size());
154*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(0, Map.lookup("eins"));
155*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(2, Map.lookup("zwei"));
156*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(0, Map.lookup("drei"));
157*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(4, Map.lookup("veir"));
158*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(5, Map.lookup("funf"));
159*9880d681SAndroid Build Coastguard Worker }
160*9880d681SAndroid Build Coastguard Worker
TEST_F(StringMapTest,CopyCtorTest)161*9880d681SAndroid Build Coastguard Worker TEST_F(StringMapTest, CopyCtorTest) {
162*9880d681SAndroid Build Coastguard Worker llvm::StringMap<int> Map;
163*9880d681SAndroid Build Coastguard Worker
164*9880d681SAndroid Build Coastguard Worker Map["eins"] = 1;
165*9880d681SAndroid Build Coastguard Worker Map["zwei"] = 2;
166*9880d681SAndroid Build Coastguard Worker Map["drei"] = 3;
167*9880d681SAndroid Build Coastguard Worker Map.erase("drei");
168*9880d681SAndroid Build Coastguard Worker Map.erase("eins");
169*9880d681SAndroid Build Coastguard Worker Map["veir"] = 4;
170*9880d681SAndroid Build Coastguard Worker Map["funf"] = 5;
171*9880d681SAndroid Build Coastguard Worker
172*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(3u, Map.size());
173*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(0, Map.lookup("eins"));
174*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(2, Map.lookup("zwei"));
175*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(0, Map.lookup("drei"));
176*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(4, Map.lookup("veir"));
177*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(5, Map.lookup("funf"));
178*9880d681SAndroid Build Coastguard Worker
179*9880d681SAndroid Build Coastguard Worker llvm::StringMap<int> Map2(Map);
180*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(3u, Map2.size());
181*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(0, Map2.lookup("eins"));
182*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(2, Map2.lookup("zwei"));
183*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(0, Map2.lookup("drei"));
184*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(4, Map2.lookup("veir"));
185*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(5, Map2.lookup("funf"));
186*9880d681SAndroid Build Coastguard Worker }
187*9880d681SAndroid Build Coastguard Worker
188*9880d681SAndroid Build Coastguard Worker // A more complex iteration test.
TEST_F(StringMapTest,IterationTest)189*9880d681SAndroid Build Coastguard Worker TEST_F(StringMapTest, IterationTest) {
190*9880d681SAndroid Build Coastguard Worker bool visited[100];
191*9880d681SAndroid Build Coastguard Worker
192*9880d681SAndroid Build Coastguard Worker // Insert 100 numbers into the map
193*9880d681SAndroid Build Coastguard Worker for (int i = 0; i < 100; ++i) {
194*9880d681SAndroid Build Coastguard Worker std::stringstream ss;
195*9880d681SAndroid Build Coastguard Worker ss << "key_" << i;
196*9880d681SAndroid Build Coastguard Worker testMap[ss.str()] = i;
197*9880d681SAndroid Build Coastguard Worker visited[i] = false;
198*9880d681SAndroid Build Coastguard Worker }
199*9880d681SAndroid Build Coastguard Worker
200*9880d681SAndroid Build Coastguard Worker // Iterate over all numbers and mark each one found.
201*9880d681SAndroid Build Coastguard Worker for (StringMap<uint32_t>::iterator it = testMap.begin();
202*9880d681SAndroid Build Coastguard Worker it != testMap.end(); ++it) {
203*9880d681SAndroid Build Coastguard Worker std::stringstream ss;
204*9880d681SAndroid Build Coastguard Worker ss << "key_" << it->second;
205*9880d681SAndroid Build Coastguard Worker ASSERT_STREQ(ss.str().c_str(), it->first().data());
206*9880d681SAndroid Build Coastguard Worker visited[it->second] = true;
207*9880d681SAndroid Build Coastguard Worker }
208*9880d681SAndroid Build Coastguard Worker
209*9880d681SAndroid Build Coastguard Worker // Ensure every number was visited.
210*9880d681SAndroid Build Coastguard Worker for (int i = 0; i < 100; ++i) {
211*9880d681SAndroid Build Coastguard Worker ASSERT_TRUE(visited[i]) << "Entry #" << i << " was never visited";
212*9880d681SAndroid Build Coastguard Worker }
213*9880d681SAndroid Build Coastguard Worker }
214*9880d681SAndroid Build Coastguard Worker
215*9880d681SAndroid Build Coastguard Worker // Test StringMapEntry::Create() method.
TEST_F(StringMapTest,StringMapEntryTest)216*9880d681SAndroid Build Coastguard Worker TEST_F(StringMapTest, StringMapEntryTest) {
217*9880d681SAndroid Build Coastguard Worker StringMap<uint32_t>::value_type* entry =
218*9880d681SAndroid Build Coastguard Worker StringMap<uint32_t>::value_type::Create(
219*9880d681SAndroid Build Coastguard Worker StringRef(testKeyFirst, testKeyLength), 1u);
220*9880d681SAndroid Build Coastguard Worker EXPECT_STREQ(testKey, entry->first().data());
221*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(1u, entry->second);
222*9880d681SAndroid Build Coastguard Worker free(entry);
223*9880d681SAndroid Build Coastguard Worker }
224*9880d681SAndroid Build Coastguard Worker
225*9880d681SAndroid Build Coastguard Worker // Test insert() method.
TEST_F(StringMapTest,InsertTest)226*9880d681SAndroid Build Coastguard Worker TEST_F(StringMapTest, InsertTest) {
227*9880d681SAndroid Build Coastguard Worker SCOPED_TRACE("InsertTest");
228*9880d681SAndroid Build Coastguard Worker testMap.insert(
229*9880d681SAndroid Build Coastguard Worker StringMap<uint32_t>::value_type::Create(
230*9880d681SAndroid Build Coastguard Worker StringRef(testKeyFirst, testKeyLength),
231*9880d681SAndroid Build Coastguard Worker testMap.getAllocator(), 1u));
232*9880d681SAndroid Build Coastguard Worker assertSingleItemMap();
233*9880d681SAndroid Build Coastguard Worker }
234*9880d681SAndroid Build Coastguard Worker
235*9880d681SAndroid Build Coastguard Worker // Test insert(pair<K, V>) method
TEST_F(StringMapTest,InsertPairTest)236*9880d681SAndroid Build Coastguard Worker TEST_F(StringMapTest, InsertPairTest) {
237*9880d681SAndroid Build Coastguard Worker bool Inserted;
238*9880d681SAndroid Build Coastguard Worker StringMap<uint32_t>::iterator NewIt;
239*9880d681SAndroid Build Coastguard Worker std::tie(NewIt, Inserted) =
240*9880d681SAndroid Build Coastguard Worker testMap.insert(std::make_pair(testKeyFirst, testValue));
241*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(1u, testMap.size());
242*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(testValue, testMap[testKeyFirst]);
243*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(testKeyFirst, NewIt->first());
244*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(testValue, NewIt->second);
245*9880d681SAndroid Build Coastguard Worker EXPECT_TRUE(Inserted);
246*9880d681SAndroid Build Coastguard Worker
247*9880d681SAndroid Build Coastguard Worker StringMap<uint32_t>::iterator ExistingIt;
248*9880d681SAndroid Build Coastguard Worker std::tie(ExistingIt, Inserted) =
249*9880d681SAndroid Build Coastguard Worker testMap.insert(std::make_pair(testKeyFirst, testValue + 1));
250*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(1u, testMap.size());
251*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(testValue, testMap[testKeyFirst]);
252*9880d681SAndroid Build Coastguard Worker EXPECT_FALSE(Inserted);
253*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(NewIt, ExistingIt);
254*9880d681SAndroid Build Coastguard Worker }
255*9880d681SAndroid Build Coastguard Worker
256*9880d681SAndroid Build Coastguard Worker // Test insert(pair<K, V>) method when rehashing occurs
TEST_F(StringMapTest,InsertRehashingPairTest)257*9880d681SAndroid Build Coastguard Worker TEST_F(StringMapTest, InsertRehashingPairTest) {
258*9880d681SAndroid Build Coastguard Worker // Check that the correct iterator is returned when the inserted element is
259*9880d681SAndroid Build Coastguard Worker // moved to a different bucket during internal rehashing. This depends on
260*9880d681SAndroid Build Coastguard Worker // the particular key, and the implementation of StringMap and HashString.
261*9880d681SAndroid Build Coastguard Worker // Changes to those might result in this test not actually checking that.
262*9880d681SAndroid Build Coastguard Worker StringMap<uint32_t> t(0);
263*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(0u, t.getNumBuckets());
264*9880d681SAndroid Build Coastguard Worker
265*9880d681SAndroid Build Coastguard Worker StringMap<uint32_t>::iterator It =
266*9880d681SAndroid Build Coastguard Worker t.insert(std::make_pair("abcdef", 42)).first;
267*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(16u, t.getNumBuckets());
268*9880d681SAndroid Build Coastguard Worker EXPECT_EQ("abcdef", It->first());
269*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(42u, It->second);
270*9880d681SAndroid Build Coastguard Worker }
271*9880d681SAndroid Build Coastguard Worker
272*9880d681SAndroid Build Coastguard Worker // Create a non-default constructable value
273*9880d681SAndroid Build Coastguard Worker struct StringMapTestStruct {
StringMapTestStruct__anon55ab63410111::StringMapTestStruct274*9880d681SAndroid Build Coastguard Worker StringMapTestStruct(int i) : i(i) {}
275*9880d681SAndroid Build Coastguard Worker StringMapTestStruct() = delete;
276*9880d681SAndroid Build Coastguard Worker int i;
277*9880d681SAndroid Build Coastguard Worker };
278*9880d681SAndroid Build Coastguard Worker
TEST_F(StringMapTest,NonDefaultConstructable)279*9880d681SAndroid Build Coastguard Worker TEST_F(StringMapTest, NonDefaultConstructable) {
280*9880d681SAndroid Build Coastguard Worker StringMap<StringMapTestStruct> t;
281*9880d681SAndroid Build Coastguard Worker t.insert(std::make_pair("Test", StringMapTestStruct(123)));
282*9880d681SAndroid Build Coastguard Worker StringMap<StringMapTestStruct>::iterator iter = t.find("Test");
283*9880d681SAndroid Build Coastguard Worker ASSERT_NE(iter, t.end());
284*9880d681SAndroid Build Coastguard Worker ASSERT_EQ(iter->second.i, 123);
285*9880d681SAndroid Build Coastguard Worker }
286*9880d681SAndroid Build Coastguard Worker
287*9880d681SAndroid Build Coastguard Worker struct Immovable {
Immovable__anon55ab63410111::Immovable288*9880d681SAndroid Build Coastguard Worker Immovable() {}
289*9880d681SAndroid Build Coastguard Worker Immovable(Immovable&&) = delete; // will disable the other special members
290*9880d681SAndroid Build Coastguard Worker };
291*9880d681SAndroid Build Coastguard Worker
292*9880d681SAndroid Build Coastguard Worker struct MoveOnly {
293*9880d681SAndroid Build Coastguard Worker int i;
MoveOnly__anon55ab63410111::MoveOnly294*9880d681SAndroid Build Coastguard Worker MoveOnly(int i) : i(i) {}
MoveOnly__anon55ab63410111::MoveOnly295*9880d681SAndroid Build Coastguard Worker MoveOnly(const Immovable&) : i(0) {}
MoveOnly__anon55ab63410111::MoveOnly296*9880d681SAndroid Build Coastguard Worker MoveOnly(MoveOnly &&RHS) : i(RHS.i) {}
operator =__anon55ab63410111::MoveOnly297*9880d681SAndroid Build Coastguard Worker MoveOnly &operator=(MoveOnly &&RHS) {
298*9880d681SAndroid Build Coastguard Worker i = RHS.i;
299*9880d681SAndroid Build Coastguard Worker return *this;
300*9880d681SAndroid Build Coastguard Worker }
301*9880d681SAndroid Build Coastguard Worker
302*9880d681SAndroid Build Coastguard Worker private:
303*9880d681SAndroid Build Coastguard Worker MoveOnly(const MoveOnly &) = delete;
304*9880d681SAndroid Build Coastguard Worker MoveOnly &operator=(const MoveOnly &) = delete;
305*9880d681SAndroid Build Coastguard Worker };
306*9880d681SAndroid Build Coastguard Worker
TEST_F(StringMapTest,MoveOnly)307*9880d681SAndroid Build Coastguard Worker TEST_F(StringMapTest, MoveOnly) {
308*9880d681SAndroid Build Coastguard Worker StringMap<MoveOnly> t;
309*9880d681SAndroid Build Coastguard Worker t.insert(std::make_pair("Test", MoveOnly(42)));
310*9880d681SAndroid Build Coastguard Worker StringRef Key = "Test";
311*9880d681SAndroid Build Coastguard Worker StringMapEntry<MoveOnly>::Create(Key, MoveOnly(42))
312*9880d681SAndroid Build Coastguard Worker ->Destroy();
313*9880d681SAndroid Build Coastguard Worker }
314*9880d681SAndroid Build Coastguard Worker
TEST_F(StringMapTest,CtorArg)315*9880d681SAndroid Build Coastguard Worker TEST_F(StringMapTest, CtorArg) {
316*9880d681SAndroid Build Coastguard Worker StringRef Key = "Test";
317*9880d681SAndroid Build Coastguard Worker StringMapEntry<MoveOnly>::Create(Key, Immovable())
318*9880d681SAndroid Build Coastguard Worker ->Destroy();
319*9880d681SAndroid Build Coastguard Worker }
320*9880d681SAndroid Build Coastguard Worker
TEST_F(StringMapTest,MoveConstruct)321*9880d681SAndroid Build Coastguard Worker TEST_F(StringMapTest, MoveConstruct) {
322*9880d681SAndroid Build Coastguard Worker StringMap<int> A;
323*9880d681SAndroid Build Coastguard Worker A["x"] = 42;
324*9880d681SAndroid Build Coastguard Worker StringMap<int> B = std::move(A);
325*9880d681SAndroid Build Coastguard Worker ASSERT_EQ(A.size(), 0u);
326*9880d681SAndroid Build Coastguard Worker ASSERT_EQ(B.size(), 1u);
327*9880d681SAndroid Build Coastguard Worker ASSERT_EQ(B["x"], 42);
328*9880d681SAndroid Build Coastguard Worker ASSERT_EQ(B.count("y"), 0u);
329*9880d681SAndroid Build Coastguard Worker }
330*9880d681SAndroid Build Coastguard Worker
TEST_F(StringMapTest,MoveAssignment)331*9880d681SAndroid Build Coastguard Worker TEST_F(StringMapTest, MoveAssignment) {
332*9880d681SAndroid Build Coastguard Worker StringMap<int> A;
333*9880d681SAndroid Build Coastguard Worker A["x"] = 42;
334*9880d681SAndroid Build Coastguard Worker StringMap<int> B;
335*9880d681SAndroid Build Coastguard Worker B["y"] = 117;
336*9880d681SAndroid Build Coastguard Worker A = std::move(B);
337*9880d681SAndroid Build Coastguard Worker ASSERT_EQ(A.size(), 1u);
338*9880d681SAndroid Build Coastguard Worker ASSERT_EQ(B.size(), 0u);
339*9880d681SAndroid Build Coastguard Worker ASSERT_EQ(A["y"], 117);
340*9880d681SAndroid Build Coastguard Worker ASSERT_EQ(B.count("x"), 0u);
341*9880d681SAndroid Build Coastguard Worker }
342*9880d681SAndroid Build Coastguard Worker
343*9880d681SAndroid Build Coastguard Worker struct Countable {
344*9880d681SAndroid Build Coastguard Worker int &InstanceCount;
345*9880d681SAndroid Build Coastguard Worker int Number;
Countable__anon55ab63410111::Countable346*9880d681SAndroid Build Coastguard Worker Countable(int Number, int &InstanceCount)
347*9880d681SAndroid Build Coastguard Worker : InstanceCount(InstanceCount), Number(Number) {
348*9880d681SAndroid Build Coastguard Worker ++InstanceCount;
349*9880d681SAndroid Build Coastguard Worker }
Countable__anon55ab63410111::Countable350*9880d681SAndroid Build Coastguard Worker Countable(Countable &&C) : InstanceCount(C.InstanceCount), Number(C.Number) {
351*9880d681SAndroid Build Coastguard Worker ++InstanceCount;
352*9880d681SAndroid Build Coastguard Worker C.Number = -1;
353*9880d681SAndroid Build Coastguard Worker }
Countable__anon55ab63410111::Countable354*9880d681SAndroid Build Coastguard Worker Countable(const Countable &C)
355*9880d681SAndroid Build Coastguard Worker : InstanceCount(C.InstanceCount), Number(C.Number) {
356*9880d681SAndroid Build Coastguard Worker ++InstanceCount;
357*9880d681SAndroid Build Coastguard Worker }
operator =__anon55ab63410111::Countable358*9880d681SAndroid Build Coastguard Worker Countable &operator=(Countable C) {
359*9880d681SAndroid Build Coastguard Worker Number = C.Number;
360*9880d681SAndroid Build Coastguard Worker return *this;
361*9880d681SAndroid Build Coastguard Worker }
~Countable__anon55ab63410111::Countable362*9880d681SAndroid Build Coastguard Worker ~Countable() { --InstanceCount; }
363*9880d681SAndroid Build Coastguard Worker };
364*9880d681SAndroid Build Coastguard Worker
TEST_F(StringMapTest,MoveDtor)365*9880d681SAndroid Build Coastguard Worker TEST_F(StringMapTest, MoveDtor) {
366*9880d681SAndroid Build Coastguard Worker int InstanceCount = 0;
367*9880d681SAndroid Build Coastguard Worker StringMap<Countable> A;
368*9880d681SAndroid Build Coastguard Worker A.insert(std::make_pair("x", Countable(42, InstanceCount)));
369*9880d681SAndroid Build Coastguard Worker ASSERT_EQ(InstanceCount, 1);
370*9880d681SAndroid Build Coastguard Worker auto I = A.find("x");
371*9880d681SAndroid Build Coastguard Worker ASSERT_NE(I, A.end());
372*9880d681SAndroid Build Coastguard Worker ASSERT_EQ(I->second.Number, 42);
373*9880d681SAndroid Build Coastguard Worker
374*9880d681SAndroid Build Coastguard Worker StringMap<Countable> B;
375*9880d681SAndroid Build Coastguard Worker B = std::move(A);
376*9880d681SAndroid Build Coastguard Worker ASSERT_EQ(InstanceCount, 1);
377*9880d681SAndroid Build Coastguard Worker ASSERT_TRUE(A.empty());
378*9880d681SAndroid Build Coastguard Worker I = B.find("x");
379*9880d681SAndroid Build Coastguard Worker ASSERT_NE(I, B.end());
380*9880d681SAndroid Build Coastguard Worker ASSERT_EQ(I->second.Number, 42);
381*9880d681SAndroid Build Coastguard Worker
382*9880d681SAndroid Build Coastguard Worker B = StringMap<Countable>();
383*9880d681SAndroid Build Coastguard Worker ASSERT_EQ(InstanceCount, 0);
384*9880d681SAndroid Build Coastguard Worker ASSERT_TRUE(B.empty());
385*9880d681SAndroid Build Coastguard Worker }
386*9880d681SAndroid Build Coastguard Worker
387*9880d681SAndroid Build Coastguard Worker namespace {
388*9880d681SAndroid Build Coastguard Worker // Simple class that counts how many moves and copy happens when growing a map
389*9880d681SAndroid Build Coastguard Worker struct CountCtorCopyAndMove {
390*9880d681SAndroid Build Coastguard Worker static unsigned Ctor;
391*9880d681SAndroid Build Coastguard Worker static unsigned Move;
392*9880d681SAndroid Build Coastguard Worker static unsigned Copy;
393*9880d681SAndroid Build Coastguard Worker int Data = 0;
CountCtorCopyAndMove__anon55ab63410111::__anon55ab63410211::CountCtorCopyAndMove394*9880d681SAndroid Build Coastguard Worker CountCtorCopyAndMove(int Data) : Data(Data) { Ctor++; }
CountCtorCopyAndMove__anon55ab63410111::__anon55ab63410211::CountCtorCopyAndMove395*9880d681SAndroid Build Coastguard Worker CountCtorCopyAndMove() { Ctor++; }
396*9880d681SAndroid Build Coastguard Worker
CountCtorCopyAndMove__anon55ab63410111::__anon55ab63410211::CountCtorCopyAndMove397*9880d681SAndroid Build Coastguard Worker CountCtorCopyAndMove(const CountCtorCopyAndMove &) { Copy++; }
operator =__anon55ab63410111::__anon55ab63410211::CountCtorCopyAndMove398*9880d681SAndroid Build Coastguard Worker CountCtorCopyAndMove &operator=(const CountCtorCopyAndMove &) {
399*9880d681SAndroid Build Coastguard Worker Copy++;
400*9880d681SAndroid Build Coastguard Worker return *this;
401*9880d681SAndroid Build Coastguard Worker }
CountCtorCopyAndMove__anon55ab63410111::__anon55ab63410211::CountCtorCopyAndMove402*9880d681SAndroid Build Coastguard Worker CountCtorCopyAndMove(CountCtorCopyAndMove &&) { Move++; }
operator =__anon55ab63410111::__anon55ab63410211::CountCtorCopyAndMove403*9880d681SAndroid Build Coastguard Worker CountCtorCopyAndMove &operator=(const CountCtorCopyAndMove &&) {
404*9880d681SAndroid Build Coastguard Worker Move++;
405*9880d681SAndroid Build Coastguard Worker return *this;
406*9880d681SAndroid Build Coastguard Worker }
407*9880d681SAndroid Build Coastguard Worker };
408*9880d681SAndroid Build Coastguard Worker unsigned CountCtorCopyAndMove::Copy = 0;
409*9880d681SAndroid Build Coastguard Worker unsigned CountCtorCopyAndMove::Move = 0;
410*9880d681SAndroid Build Coastguard Worker unsigned CountCtorCopyAndMove::Ctor = 0;
411*9880d681SAndroid Build Coastguard Worker
412*9880d681SAndroid Build Coastguard Worker } // anonymous namespace
413*9880d681SAndroid Build Coastguard Worker
414*9880d681SAndroid Build Coastguard Worker // Make sure creating the map with an initial size of N actually gives us enough
415*9880d681SAndroid Build Coastguard Worker // buckets to insert N items without increasing allocation size.
TEST(StringMapCustomTest,InitialSizeTest)416*9880d681SAndroid Build Coastguard Worker TEST(StringMapCustomTest, InitialSizeTest) {
417*9880d681SAndroid Build Coastguard Worker // 1 is an "edge value", 32 is an arbitrary power of two, and 67 is an
418*9880d681SAndroid Build Coastguard Worker // arbitrary prime, picked without any good reason.
419*9880d681SAndroid Build Coastguard Worker for (auto Size : {1, 32, 67}) {
420*9880d681SAndroid Build Coastguard Worker StringMap<CountCtorCopyAndMove> Map(Size);
421*9880d681SAndroid Build Coastguard Worker auto NumBuckets = Map.getNumBuckets();
422*9880d681SAndroid Build Coastguard Worker CountCtorCopyAndMove::Move = 0;
423*9880d681SAndroid Build Coastguard Worker CountCtorCopyAndMove::Copy = 0;
424*9880d681SAndroid Build Coastguard Worker for (int i = 0; i < Size; ++i)
425*9880d681SAndroid Build Coastguard Worker Map.insert(std::pair<std::string, CountCtorCopyAndMove>(
426*9880d681SAndroid Build Coastguard Worker std::piecewise_construct, std::forward_as_tuple(Twine(i).str()),
427*9880d681SAndroid Build Coastguard Worker std::forward_as_tuple(i)));
428*9880d681SAndroid Build Coastguard Worker // After the inital move, the map will move the Elts in the Entry.
429*9880d681SAndroid Build Coastguard Worker EXPECT_EQ((unsigned)Size * 2, CountCtorCopyAndMove::Move);
430*9880d681SAndroid Build Coastguard Worker // We copy once the pair from the Elts vector
431*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(0u, CountCtorCopyAndMove::Copy);
432*9880d681SAndroid Build Coastguard Worker // Check that the map didn't grow
433*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(Map.getNumBuckets(), NumBuckets);
434*9880d681SAndroid Build Coastguard Worker }
435*9880d681SAndroid Build Coastguard Worker }
436*9880d681SAndroid Build Coastguard Worker
TEST(StringMapCustomTest,BracketOperatorCtor)437*9880d681SAndroid Build Coastguard Worker TEST(StringMapCustomTest, BracketOperatorCtor) {
438*9880d681SAndroid Build Coastguard Worker StringMap<CountCtorCopyAndMove> Map;
439*9880d681SAndroid Build Coastguard Worker CountCtorCopyAndMove::Ctor = 0;
440*9880d681SAndroid Build Coastguard Worker Map["abcd"];
441*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(1u, CountCtorCopyAndMove::Ctor);
442*9880d681SAndroid Build Coastguard Worker // Test that operator[] does not create a value when it is already in the map
443*9880d681SAndroid Build Coastguard Worker CountCtorCopyAndMove::Ctor = 0;
444*9880d681SAndroid Build Coastguard Worker Map["abcd"];
445*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(0u, CountCtorCopyAndMove::Ctor);
446*9880d681SAndroid Build Coastguard Worker }
447*9880d681SAndroid Build Coastguard Worker
448*9880d681SAndroid Build Coastguard Worker namespace {
449*9880d681SAndroid Build Coastguard Worker struct NonMoveableNonCopyableType {
450*9880d681SAndroid Build Coastguard Worker int Data = 0;
451*9880d681SAndroid Build Coastguard Worker NonMoveableNonCopyableType() = default;
NonMoveableNonCopyableType__anon55ab63410111::__anon55ab63410311::NonMoveableNonCopyableType452*9880d681SAndroid Build Coastguard Worker NonMoveableNonCopyableType(int Data) : Data(Data) {}
453*9880d681SAndroid Build Coastguard Worker NonMoveableNonCopyableType(const NonMoveableNonCopyableType &) = delete;
454*9880d681SAndroid Build Coastguard Worker NonMoveableNonCopyableType(NonMoveableNonCopyableType &&) = delete;
455*9880d681SAndroid Build Coastguard Worker };
456*9880d681SAndroid Build Coastguard Worker }
457*9880d681SAndroid Build Coastguard Worker
458*9880d681SAndroid Build Coastguard Worker // Test that we can "emplace" an element in the map without involving map/move
TEST(StringMapCustomTest,EmplaceTest)459*9880d681SAndroid Build Coastguard Worker TEST(StringMapCustomTest, EmplaceTest) {
460*9880d681SAndroid Build Coastguard Worker StringMap<NonMoveableNonCopyableType> Map;
461*9880d681SAndroid Build Coastguard Worker Map.emplace_second("abcd", 42);
462*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(1u, Map.count("abcd"));
463*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(42, Map["abcd"].Data);
464*9880d681SAndroid Build Coastguard Worker }
465*9880d681SAndroid Build Coastguard Worker
466*9880d681SAndroid Build Coastguard Worker } // end anonymous namespace
467