1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/containers/small_map.h"
13 #include "base/logging.h"
14 #include "base/hash_tables.h"
15 #include "testing/gtest/include/gtest/gtest.h"
19 TEST(SmallMap
, General
) {
20 SmallMap
<hash_map
<int, int> > m
;
22 EXPECT_TRUE(m
.empty());
26 EXPECT_FALSE(m
.empty());
27 EXPECT_EQ(m
.size(), 1u);
31 EXPECT_FALSE(m
.empty());
32 EXPECT_EQ(m
.size(), 2u);
36 EXPECT_FALSE(m
.UsingFullMap());
38 SmallMap
<hash_map
<int, int> >::iterator
iter(m
.begin());
39 ASSERT_TRUE(iter
!= m
.end());
40 EXPECT_EQ(iter
->first
, 0);
41 EXPECT_EQ(iter
->second
, 5);
43 ASSERT_TRUE(iter
!= m
.end());
44 EXPECT_EQ((*iter
).first
, 9);
45 EXPECT_EQ((*iter
).second
, 2);
47 EXPECT_TRUE(iter
== m
.end());
55 EXPECT_EQ(m
[1234], 90);
58 EXPECT_EQ(m
.size(), 5u);
59 EXPECT_FALSE(m
.empty());
60 EXPECT_TRUE(m
.UsingFullMap());
63 for (int i
= 0; i
< 5; i
++) {
64 EXPECT_TRUE(iter
!= m
.end());
67 EXPECT_TRUE(iter
== m
.end());
69 const SmallMap
<hash_map
<int, int> >& ref
= m
;
70 EXPECT_TRUE(ref
.find(1234) != m
.end());
71 EXPECT_TRUE(ref
.find(5678) == m
.end());
74 TEST(SmallMap
, PostFixIteratorIncrement
) {
75 SmallMap
<hash_map
<int, int> > m
;
80 SmallMap
<hash_map
<int, int> >::iterator
iter(m
.begin());
81 SmallMap
<hash_map
<int, int> >::iterator
last(iter
++);
83 EXPECT_TRUE(last
== iter
);
87 SmallMap
<hash_map
<int, int> >::const_iterator
iter(m
.begin());
88 SmallMap
<hash_map
<int, int> >::const_iterator
last(iter
++);
90 EXPECT_TRUE(last
== iter
);
94 // Based on the General testcase.
95 TEST(SmallMap
, CopyConstructor
) {
96 SmallMap
<hash_map
<int, int> > src
;
99 SmallMap
<hash_map
<int, int> > m(src
);
100 EXPECT_TRUE(m
.empty());
106 SmallMap
<hash_map
<int, int> > m(src
);
107 EXPECT_FALSE(m
.empty());
108 EXPECT_EQ(m
.size(), 1u);
114 SmallMap
<hash_map
<int, int> > m(src
);
115 EXPECT_FALSE(m
.empty());
116 EXPECT_EQ(m
.size(), 2u);
120 EXPECT_FALSE(m
.UsingFullMap());
128 SmallMap
<hash_map
<int, int> > m(src
);
131 EXPECT_EQ(m
[1234], 90);
132 EXPECT_EQ(m
[ 8], 23);
133 EXPECT_EQ(m
[ -5], 6);
134 EXPECT_EQ(m
.size(), 5u);
135 EXPECT_FALSE(m
.empty());
136 EXPECT_TRUE(m
.UsingFullMap());
140 template<class inner
>
141 static void SmallMapToMap(SmallMap
<inner
> const& src
, inner
* dest
) {
142 typename SmallMap
<inner
>::const_iterator it
;
143 for (it
= src
.begin(); it
!= src
.end(); ++it
) {
144 dest
->insert(std::make_pair(it
->first
, it
->second
));
148 template<class inner
>
149 static bool SmallMapEqual(SmallMap
<inner
> const& a
,
150 SmallMap
<inner
> const& b
) {
152 SmallMapToMap(a
, &ia
);
153 SmallMapToMap(b
, &ib
);
155 // On most systems we can use operator== here, but under some lesser STL
156 // implementations it doesn't seem to work. So we manually compare.
157 if (ia
.size() != ib
.size())
159 for (typename
inner::iterator ia_it
= ia
.begin(), ib_it
= ib
.begin();
160 ia_it
!= ia
.end(); ++ia_it
, ++ib_it
) {
161 if (*ia_it
!= *ib_it
)
167 TEST(SmallMap
, AssignmentOperator
) {
168 SmallMap
<hash_map
<int, int> > src_small
;
169 SmallMap
<hash_map
<int, int> > src_large
;
174 EXPECT_FALSE(src_small
.UsingFullMap());
182 EXPECT_TRUE(src_large
.UsingFullMap());
184 // Assignments to empty.
185 SmallMap
<hash_map
<int, int> > dest_small
;
186 dest_small
= src_small
;
187 EXPECT_TRUE(SmallMapEqual(dest_small
, src_small
));
188 EXPECT_EQ(dest_small
.UsingFullMap(),
189 src_small
.UsingFullMap());
191 SmallMap
<hash_map
<int, int> > dest_large
;
192 dest_large
= src_large
;
193 EXPECT_TRUE(SmallMapEqual(dest_large
, src_large
));
194 EXPECT_EQ(dest_large
.UsingFullMap(),
195 src_large
.UsingFullMap());
197 // Assignments which assign from full to small, and vice versa.
198 dest_small
= src_large
;
199 EXPECT_TRUE(SmallMapEqual(dest_small
, src_large
));
200 EXPECT_EQ(dest_small
.UsingFullMap(),
201 src_large
.UsingFullMap());
203 dest_large
= src_small
;
204 EXPECT_TRUE(SmallMapEqual(dest_large
, src_small
));
205 EXPECT_EQ(dest_large
.UsingFullMap(),
206 src_small
.UsingFullMap());
208 // Double check that SmallMapEqual works:
209 dest_large
[42] = 666;
210 EXPECT_FALSE(SmallMapEqual(dest_large
, src_small
));
213 TEST(SmallMap
, Insert
) {
214 SmallMap
<hash_map
<int, int> > sm
;
216 // loop through the transition from small map to map.
217 for (int i
= 1; i
<= 10; ++i
) {
218 VLOG(1) << "Iteration " << i
;
220 std::pair
<SmallMap
<hash_map
<int, int> >::iterator
,
222 ret
= sm
.insert(std::make_pair(i
, 100*i
));
223 EXPECT_TRUE(ret
.second
);
224 EXPECT_TRUE(ret
.first
== sm
.find(i
));
225 EXPECT_EQ(ret
.first
->first
, i
);
226 EXPECT_EQ(ret
.first
->second
, 100*i
);
228 // try to insert it again with different value, fails, but we still get an
229 // iterator back with the original value.
230 ret
= sm
.insert(std::make_pair(i
, -i
));
231 EXPECT_FALSE(ret
.second
);
232 EXPECT_TRUE(ret
.first
== sm
.find(i
));
233 EXPECT_EQ(ret
.first
->first
, i
);
234 EXPECT_EQ(ret
.first
->second
, 100*i
);
236 // check the state of the map.
237 for (int j
= 1; j
<= i
; ++j
) {
238 SmallMap
<hash_map
<int, int> >::iterator it
= sm
.find(j
);
239 EXPECT_TRUE(it
!= sm
.end());
240 EXPECT_EQ(it
->first
, j
);
241 EXPECT_EQ(it
->second
, j
* 100);
243 EXPECT_EQ(sm
.size(), static_cast<size_t>(i
));
244 EXPECT_FALSE(sm
.empty());
248 TEST(SmallMap
, InsertRange
) {
249 // loop through the transition from small map to map.
250 for (int elements
= 0; elements
<= 10; ++elements
) {
251 VLOG(1) << "Elements " << elements
;
252 hash_map
<int, int> normal_map
;
253 for (int i
= 1; i
<= elements
; ++i
) {
254 normal_map
.insert(std::make_pair(i
, 100*i
));
257 SmallMap
<hash_map
<int, int> > sm
;
258 sm
.insert(normal_map
.begin(), normal_map
.end());
259 EXPECT_EQ(normal_map
.size(), sm
.size());
260 for (int i
= 1; i
<= elements
; ++i
) {
261 VLOG(1) << "Iteration " << i
;
262 EXPECT_TRUE(sm
.find(i
) != sm
.end());
263 EXPECT_EQ(sm
.find(i
)->first
, i
);
264 EXPECT_EQ(sm
.find(i
)->second
, 100*i
);
269 TEST(SmallMap
, Erase
) {
270 SmallMap
<hash_map
<std::string
, int> > m
;
271 SmallMap
<hash_map
<std::string
, int> >::iterator iter
;
277 EXPECT_EQ(m
["monday" ], 1);
278 EXPECT_EQ(m
["tuesday" ], 2);
279 EXPECT_EQ(m
["wednesday"], 3);
280 EXPECT_EQ(m
.count("tuesday"), 1u);
281 EXPECT_FALSE(m
.UsingFullMap());
284 ASSERT_TRUE(iter
!= m
.end());
285 EXPECT_EQ(iter
->first
, "monday");
286 EXPECT_EQ(iter
->second
, 1);
288 ASSERT_TRUE(iter
!= m
.end());
289 EXPECT_EQ(iter
->first
, "tuesday");
290 EXPECT_EQ(iter
->second
, 2);
292 ASSERT_TRUE(iter
!= m
.end());
293 EXPECT_EQ(iter
->first
, "wednesday");
294 EXPECT_EQ(iter
->second
, 3);
296 EXPECT_TRUE(iter
== m
.end());
298 EXPECT_EQ(m
.erase("tuesday"), 1u);
300 EXPECT_EQ(m
["monday" ], 1);
301 EXPECT_EQ(m
["wednesday"], 3);
302 EXPECT_EQ(m
.count("tuesday"), 0u);
303 EXPECT_EQ(m
.erase("tuesday"), 0u);
306 ASSERT_TRUE(iter
!= m
.end());
307 EXPECT_EQ(iter
->first
, "monday");
308 EXPECT_EQ(iter
->second
, 1);
310 ASSERT_TRUE(iter
!= m
.end());
311 EXPECT_EQ(iter
->first
, "wednesday");
312 EXPECT_EQ(iter
->second
, 3);
314 EXPECT_TRUE(iter
== m
.end());
318 EXPECT_EQ(m
.size(), 4u);
319 EXPECT_FALSE(m
.empty());
320 EXPECT_FALSE(m
.UsingFullMap());
323 EXPECT_TRUE(m
.UsingFullMap());
325 EXPECT_EQ(m
.count("friday"), 1u);
326 EXPECT_EQ(m
.erase("friday"), 1u);
327 EXPECT_TRUE(m
.UsingFullMap());
328 EXPECT_EQ(m
.count("friday"), 0u);
329 EXPECT_EQ(m
.erase("friday"), 0u);
331 EXPECT_EQ(m
.size(), 4u);
332 EXPECT_FALSE(m
.empty());
333 EXPECT_EQ(m
.erase("monday"), 1u);
334 EXPECT_EQ(m
.size(), 3u);
335 EXPECT_FALSE(m
.empty());
338 EXPECT_FALSE(m
.UsingFullMap());
339 EXPECT_EQ(m
.size(), 0u);
340 EXPECT_TRUE(m
.empty());
343 TEST(SmallMap
, NonHashMap
) {
344 SmallMap
<std::map
<int, int>, 4, std::equal_to
<int> > m
;
345 EXPECT_TRUE(m
.empty());
352 EXPECT_EQ(m
.size(), 2u);
353 EXPECT_FALSE(m
.empty());
354 EXPECT_FALSE(m
.UsingFullMap());
356 SmallMap
<std::map
<int, int>, 4, std::equal_to
<int> >::iterator
iter(
358 ASSERT_TRUE(iter
!= m
.end());
359 EXPECT_EQ(iter
->first
, 9);
360 EXPECT_EQ(iter
->second
, 2);
362 ASSERT_TRUE(iter
!= m
.end());
363 EXPECT_EQ(iter
->first
, 0);
364 EXPECT_EQ(iter
->second
, 5);
366 EXPECT_TRUE(iter
== m
.end());
368 ASSERT_TRUE(iter
!= m
.end());
369 EXPECT_EQ(iter
->first
, 0);
370 EXPECT_EQ(iter
->second
, 5);
378 EXPECT_EQ(m
[1234], 90);
379 EXPECT_EQ(m
[ 8], 23);
380 EXPECT_EQ(m
[ -5], 6);
381 EXPECT_EQ(m
.size(), 5u);
382 EXPECT_FALSE(m
.empty());
383 EXPECT_TRUE(m
.UsingFullMap());
386 ASSERT_TRUE(iter
!= m
.end());
387 EXPECT_EQ(iter
->first
, -5);
388 EXPECT_EQ(iter
->second
, 6);
390 ASSERT_TRUE(iter
!= m
.end());
391 EXPECT_EQ(iter
->first
, 0);
392 EXPECT_EQ(iter
->second
, 5);
394 ASSERT_TRUE(iter
!= m
.end());
395 EXPECT_EQ(iter
->first
, 8);
396 EXPECT_EQ(iter
->second
, 23);
398 ASSERT_TRUE(iter
!= m
.end());
399 EXPECT_EQ(iter
->first
, 9);
400 EXPECT_EQ(iter
->second
, 2);
402 ASSERT_TRUE(iter
!= m
.end());
403 EXPECT_EQ(iter
->first
, 1234);
404 EXPECT_EQ(iter
->second
, 90);
406 EXPECT_TRUE(iter
== m
.end());
408 ASSERT_TRUE(iter
!= m
.end());
409 EXPECT_EQ(iter
->first
, 1234);
410 EXPECT_EQ(iter
->second
, 90);
413 TEST(SmallMap
, DefaultEqualKeyWorks
) {
414 // If these tests compile, they pass. The EXPECT calls are only there to avoid
415 // unused variable warnings.
416 SmallMap
<hash_map
<int, int> > hm
;
417 EXPECT_EQ(0u, hm
.size());
418 SmallMap
<std::map
<int, int> > m
;
419 EXPECT_EQ(0u, m
.size());
424 class hash_map_add_item
: public hash_map
<int, int> {
426 hash_map_add_item() : hash_map
<int, int>() {}
427 explicit hash_map_add_item(const std::pair
<int, int>& item
)
428 : hash_map
<int, int>() {
433 void InitMap(ManualConstructor
<hash_map_add_item
>* map_ctor
) {
434 map_ctor
->Init(std::make_pair(0, 0));
437 class hash_map_add_item_initializer
{
439 explicit hash_map_add_item_initializer(int item_to_add
)
440 : item_(item_to_add
) {}
441 hash_map_add_item_initializer()
443 void operator()(ManualConstructor
<hash_map_add_item
>* map_ctor
) const {
444 map_ctor
->Init(std::make_pair(item_
, item_
));
450 } // anonymous namespace
452 TEST(SmallMap
, SubclassInitializationWithFunctionPointer
) {
453 SmallMap
<hash_map_add_item
, 4, std::equal_to
<int>,
454 void (&)(ManualConstructor
<hash_map_add_item
>*)> m(InitMap
);
456 EXPECT_TRUE(m
.empty());
463 EXPECT_EQ(4u, m
.size());
464 EXPECT_EQ(0u, m
.count(0));
467 EXPECT_EQ(6u, m
.size());
468 // Our function adds an extra item when we convert to a map.
469 EXPECT_EQ(1u, m
.count(0));
472 TEST(SmallMap
, SubclassInitializationWithFunctionObject
) {
473 SmallMap
<hash_map_add_item
, 4, std::equal_to
<int>,
474 hash_map_add_item_initializer
> m(hash_map_add_item_initializer(-1));
476 EXPECT_TRUE(m
.empty());
483 EXPECT_EQ(4u, m
.size());
484 EXPECT_EQ(0u, m
.count(-1));
487 EXPECT_EQ(6u, m
.size());
488 // Our functor adds an extra item when we convert to a map.
489 EXPECT_EQ(1u, m
.count(-1));