blob: 15f0c24b73ad4397ef83d6f88eb9575ae2b57af1 [file] [log] [blame]
pph34r@gmail.com4f029ab2011-06-25 13:33:18 +09001// Copyright (c) 2011 The Chromium Authors. All rights reserved.
phajdan.jr@chromium.orga12746c2009-08-19 23:56:38 +09002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/id_map.h"
6
avia6a6a682015-12-27 07:15:14 +09007#include <stdint.h>
8
rlandayf5b01dd2016-12-01 03:59:30 +09009#include <memory>
10
11#include "base/memory/ptr_util.h"
phajdan.jr@chromium.orga12746c2009-08-19 23:56:38 +090012#include "testing/gtest/include/gtest/gtest.h"
13
14namespace {
15
phajdan.jr@chromium.orga12746c2009-08-19 23:56:38 +090016class TestObject {
17};
18
neb@chromium.orged1f8d72010-01-26 08:25:16 +090019class DestructorCounter {
20 public:
21 explicit DestructorCounter(int* counter) : counter_(counter) {}
22 ~DestructorCounter() { ++(*counter_); }
tfarina@chromium.org6ac12282012-12-04 02:04:28 +090023
neb@chromium.orged1f8d72010-01-26 08:25:16 +090024 private:
25 int* counter_;
26};
27
tfarina@chromium.org6ac12282012-12-04 02:04:28 +090028TEST(IDMapTest, Basic) {
rlanday644d4f42016-12-01 12:05:40 +090029 IDMap<TestObject*> map;
phajdan.jr@chromium.orga12746c2009-08-19 23:56:38 +090030 EXPECT_TRUE(map.IsEmpty());
31 EXPECT_EQ(0U, map.size());
32
33 TestObject obj1;
34 TestObject obj2;
35
avia6a6a682015-12-27 07:15:14 +090036 int32_t id1 = map.Add(&obj1);
phajdan.jr@chromium.orga12746c2009-08-19 23:56:38 +090037 EXPECT_FALSE(map.IsEmpty());
38 EXPECT_EQ(1U, map.size());
39 EXPECT_EQ(&obj1, map.Lookup(id1));
40
avia6a6a682015-12-27 07:15:14 +090041 int32_t id2 = map.Add(&obj2);
phajdan.jr@chromium.orga12746c2009-08-19 23:56:38 +090042 EXPECT_FALSE(map.IsEmpty());
43 EXPECT_EQ(2U, map.size());
44
45 EXPECT_EQ(&obj1, map.Lookup(id1));
46 EXPECT_EQ(&obj2, map.Lookup(id2));
47
48 map.Remove(id1);
49 EXPECT_FALSE(map.IsEmpty());
50 EXPECT_EQ(1U, map.size());
51
52 map.Remove(id2);
53 EXPECT_TRUE(map.IsEmpty());
54 EXPECT_EQ(0U, map.size());
55
56 map.AddWithID(&obj1, 1);
57 map.AddWithID(&obj2, 2);
58 EXPECT_EQ(&obj1, map.Lookup(1));
59 EXPECT_EQ(&obj2, map.Lookup(2));
phajdan.jr@chromium.org7c63ed82012-10-27 10:03:01 +090060
michaeln699d8f52014-12-10 08:16:13 +090061 EXPECT_EQ(&obj2, map.Replace(2, &obj1));
62 EXPECT_EQ(&obj1, map.Lookup(2));
63
phajdan.jr@chromium.org7c63ed82012-10-27 10:03:01 +090064 EXPECT_EQ(0, map.iteration_depth());
phajdan.jr@chromium.orga12746c2009-08-19 23:56:38 +090065}
66
tfarina@chromium.org6ac12282012-12-04 02:04:28 +090067TEST(IDMapTest, IteratorRemainsValidWhenRemovingCurrentElement) {
rlanday644d4f42016-12-01 12:05:40 +090068 IDMap<TestObject*> map;
phajdan.jr@chromium.orga12746c2009-08-19 23:56:38 +090069
70 TestObject obj1;
71 TestObject obj2;
72 TestObject obj3;
73
74 map.Add(&obj1);
75 map.Add(&obj2);
76 map.Add(&obj3);
77
phajdan.jr@chromium.org61544a02010-02-16 18:15:38 +090078 {
rlanday644d4f42016-12-01 12:05:40 +090079 IDMap<TestObject*>::const_iterator iter(&map);
phajdan.jr@chromium.org7c63ed82012-10-27 10:03:01 +090080
81 EXPECT_EQ(1, map.iteration_depth());
82
phajdan.jr@chromium.org61544a02010-02-16 18:15:38 +090083 while (!iter.IsAtEnd()) {
84 map.Remove(iter.GetCurrentKey());
85 iter.Advance();
86 }
87
88 // Test that while an iterator is still in scope, we get the map emptiness
89 // right (http://crbug.com/35571).
90 EXPECT_TRUE(map.IsEmpty());
91 EXPECT_EQ(0U, map.size());
phajdan.jr@chromium.orga12746c2009-08-19 23:56:38 +090092 }
phajdan.jr@chromium.org61544a02010-02-16 18:15:38 +090093
94 EXPECT_TRUE(map.IsEmpty());
95 EXPECT_EQ(0U, map.size());
phajdan.jr@chromium.org7c63ed82012-10-27 10:03:01 +090096
97 EXPECT_EQ(0, map.iteration_depth());
phajdan.jr@chromium.orga12746c2009-08-19 23:56:38 +090098}
99
tfarina@chromium.org6ac12282012-12-04 02:04:28 +0900100TEST(IDMapTest, IteratorRemainsValidWhenRemovingOtherElements) {
rlanday644d4f42016-12-01 12:05:40 +0900101 IDMap<TestObject*> map;
phajdan.jr@chromium.orga12746c2009-08-19 23:56:38 +0900102
103 const int kCount = 5;
104 TestObject obj[kCount];
phajdan.jr@chromium.orga12746c2009-08-19 23:56:38 +0900105
106 for (int i = 0; i < kCount; i++)
earthdok@chromium.org8be6e992014-01-24 03:17:15 +0900107 map.Add(&obj[i]);
phajdan.jr@chromium.orga12746c2009-08-19 23:56:38 +0900108
brettw0b7bff32017-04-28 04:42:32 +0900109 // IDMap has no predictable iteration order.
avia6a6a682015-12-27 07:15:14 +0900110 int32_t ids_in_iteration_order[kCount];
earthdok@chromium.org8be6e992014-01-24 03:17:15 +0900111 const TestObject* objs_in_iteration_order[kCount];
phajdan.jr@chromium.orga12746c2009-08-19 23:56:38 +0900112 int counter = 0;
rlanday644d4f42016-12-01 12:05:40 +0900113 for (IDMap<TestObject*>::const_iterator iter(&map); !iter.IsAtEnd();
114 iter.Advance()) {
earthdok@chromium.org8be6e992014-01-24 03:17:15 +0900115 ids_in_iteration_order[counter] = iter.GetCurrentKey();
116 objs_in_iteration_order[counter] = iter.GetCurrentValue();
117 counter++;
118 }
119
120 counter = 0;
rlanday644d4f42016-12-01 12:05:40 +0900121 for (IDMap<TestObject*>::const_iterator iter(&map); !iter.IsAtEnd();
122 iter.Advance()) {
phajdan.jr@chromium.org7c63ed82012-10-27 10:03:01 +0900123 EXPECT_EQ(1, map.iteration_depth());
124
phajdan.jr@chromium.orga12746c2009-08-19 23:56:38 +0900125 switch (counter) {
126 case 0:
earthdok@chromium.org8be6e992014-01-24 03:17:15 +0900127 EXPECT_EQ(ids_in_iteration_order[0], iter.GetCurrentKey());
128 EXPECT_EQ(objs_in_iteration_order[0], iter.GetCurrentValue());
129 map.Remove(ids_in_iteration_order[1]);
phajdan.jr@chromium.orga12746c2009-08-19 23:56:38 +0900130 break;
131 case 1:
earthdok@chromium.org8be6e992014-01-24 03:17:15 +0900132 EXPECT_EQ(ids_in_iteration_order[2], iter.GetCurrentKey());
133 EXPECT_EQ(objs_in_iteration_order[2], iter.GetCurrentValue());
134 map.Remove(ids_in_iteration_order[3]);
phajdan.jr@chromium.orga12746c2009-08-19 23:56:38 +0900135 break;
136 case 2:
earthdok@chromium.org8be6e992014-01-24 03:17:15 +0900137 EXPECT_EQ(ids_in_iteration_order[4], iter.GetCurrentKey());
138 EXPECT_EQ(objs_in_iteration_order[4], iter.GetCurrentValue());
139 map.Remove(ids_in_iteration_order[0]);
phajdan.jr@chromium.orga12746c2009-08-19 23:56:38 +0900140 break;
141 default:
142 FAIL() << "should not have that many elements";
143 break;
144 }
145
146 counter++;
147 }
phajdan.jr@chromium.org7c63ed82012-10-27 10:03:01 +0900148
149 EXPECT_EQ(0, map.iteration_depth());
150}
151
tfarina@chromium.org6ac12282012-12-04 02:04:28 +0900152TEST(IDMapTest, CopyIterator) {
rlanday644d4f42016-12-01 12:05:40 +0900153 IDMap<TestObject*> map;
phajdan.jr@chromium.org7c63ed82012-10-27 10:03:01 +0900154
155 TestObject obj1;
156 TestObject obj2;
157 TestObject obj3;
158
159 map.Add(&obj1);
160 map.Add(&obj2);
161 map.Add(&obj3);
162
163 EXPECT_EQ(0, map.iteration_depth());
164
165 {
rlanday644d4f42016-12-01 12:05:40 +0900166 IDMap<TestObject*>::const_iterator iter1(&map);
phajdan.jr@chromium.org7c63ed82012-10-27 10:03:01 +0900167 EXPECT_EQ(1, map.iteration_depth());
168
169 // Make sure that copying the iterator correctly increments
170 // map's iteration depth.
rlanday644d4f42016-12-01 12:05:40 +0900171 IDMap<TestObject*>::const_iterator iter2(iter1);
phajdan.jr@chromium.org7c63ed82012-10-27 10:03:01 +0900172 EXPECT_EQ(2, map.iteration_depth());
173 }
174
175 // Make sure after destroying all iterators the map's iteration depth
176 // returns to initial state.
177 EXPECT_EQ(0, map.iteration_depth());
178}
179
tfarina@chromium.org6ac12282012-12-04 02:04:28 +0900180TEST(IDMapTest, AssignIterator) {
rlanday644d4f42016-12-01 12:05:40 +0900181 IDMap<TestObject*> map;
phajdan.jr@chromium.org7c63ed82012-10-27 10:03:01 +0900182
183 TestObject obj1;
184 TestObject obj2;
185 TestObject obj3;
186
187 map.Add(&obj1);
188 map.Add(&obj2);
189 map.Add(&obj3);
190
191 EXPECT_EQ(0, map.iteration_depth());
192
193 {
rlanday644d4f42016-12-01 12:05:40 +0900194 IDMap<TestObject*>::const_iterator iter1(&map);
phajdan.jr@chromium.org7c63ed82012-10-27 10:03:01 +0900195 EXPECT_EQ(1, map.iteration_depth());
196
rlanday644d4f42016-12-01 12:05:40 +0900197 IDMap<TestObject*>::const_iterator iter2(&map);
phajdan.jr@chromium.org7c63ed82012-10-27 10:03:01 +0900198 EXPECT_EQ(2, map.iteration_depth());
199
200 // Make sure that assigning the iterator correctly updates
201 // map's iteration depth (-1 for destruction, +1 for assignment).
202 EXPECT_EQ(2, map.iteration_depth());
203 }
204
205 // Make sure after destroying all iterators the map's iteration depth
206 // returns to initial state.
207 EXPECT_EQ(0, map.iteration_depth());
phajdan.jr@chromium.orga12746c2009-08-19 23:56:38 +0900208}
209
tfarina@chromium.org6ac12282012-12-04 02:04:28 +0900210TEST(IDMapTest, IteratorRemainsValidWhenClearing) {
rlanday644d4f42016-12-01 12:05:40 +0900211 IDMap<TestObject*> map;
jsbell@chromium.org8fe2a8f2012-10-30 06:36:22 +0900212
213 const int kCount = 5;
214 TestObject obj[kCount];
jsbell@chromium.org8fe2a8f2012-10-30 06:36:22 +0900215
216 for (int i = 0; i < kCount; i++)
earthdok@chromium.org8be6e992014-01-24 03:17:15 +0900217 map.Add(&obj[i]);
jsbell@chromium.org8fe2a8f2012-10-30 06:36:22 +0900218
brettw0b7bff32017-04-28 04:42:32 +0900219 // IDMap has no predictable iteration order.
avia6a6a682015-12-27 07:15:14 +0900220 int32_t ids_in_iteration_order[kCount];
earthdok@chromium.org8be6e992014-01-24 03:17:15 +0900221 const TestObject* objs_in_iteration_order[kCount];
jsbell@chromium.org8fe2a8f2012-10-30 06:36:22 +0900222 int counter = 0;
rlanday644d4f42016-12-01 12:05:40 +0900223 for (IDMap<TestObject*>::const_iterator iter(&map); !iter.IsAtEnd();
224 iter.Advance()) {
earthdok@chromium.org8be6e992014-01-24 03:17:15 +0900225 ids_in_iteration_order[counter] = iter.GetCurrentKey();
226 objs_in_iteration_order[counter] = iter.GetCurrentValue();
227 counter++;
228 }
229
230 counter = 0;
rlanday644d4f42016-12-01 12:05:40 +0900231 for (IDMap<TestObject*>::const_iterator iter(&map); !iter.IsAtEnd();
232 iter.Advance()) {
jsbell@chromium.org8fe2a8f2012-10-30 06:36:22 +0900233 switch (counter) {
234 case 0:
earthdok@chromium.org8be6e992014-01-24 03:17:15 +0900235 EXPECT_EQ(ids_in_iteration_order[0], iter.GetCurrentKey());
236 EXPECT_EQ(objs_in_iteration_order[0], iter.GetCurrentValue());
jsbell@chromium.org8fe2a8f2012-10-30 06:36:22 +0900237 break;
238 case 1:
earthdok@chromium.org8be6e992014-01-24 03:17:15 +0900239 EXPECT_EQ(ids_in_iteration_order[1], iter.GetCurrentKey());
240 EXPECT_EQ(objs_in_iteration_order[1], iter.GetCurrentValue());
jsbell@chromium.org8fe2a8f2012-10-30 06:36:22 +0900241 map.Clear();
242 EXPECT_TRUE(map.IsEmpty());
243 EXPECT_EQ(0U, map.size());
244 break;
245 default:
246 FAIL() << "should not have that many elements";
247 break;
248 }
249 counter++;
250 }
251
252 EXPECT_TRUE(map.IsEmpty());
253 EXPECT_EQ(0U, map.size());
254}
255
tfarina@chromium.org6ac12282012-12-04 02:04:28 +0900256TEST(IDMapTest, OwningPointersDeletesThemOnRemove) {
neb@chromium.orged1f8d72010-01-26 08:25:16 +0900257 const int kCount = 3;
258
259 int external_del_count = 0;
260 DestructorCounter* external_obj[kCount];
261 int map_external_ids[kCount];
262
263 int owned_del_count = 0;
neb@chromium.orged1f8d72010-01-26 08:25:16 +0900264 int map_owned_ids[kCount];
265
rlanday644d4f42016-12-01 12:05:40 +0900266 IDMap<DestructorCounter*> map_external;
267 IDMap<std::unique_ptr<DestructorCounter>> map_owned;
neb@chromium.orged1f8d72010-01-26 08:25:16 +0900268
269 for (int i = 0; i < kCount; ++i) {
270 external_obj[i] = new DestructorCounter(&external_del_count);
271 map_external_ids[i] = map_external.Add(external_obj[i]);
272
rlandayf5b01dd2016-12-01 03:59:30 +0900273 map_owned_ids[i] =
274 map_owned.Add(base::MakeUnique<DestructorCounter>(&owned_del_count));
neb@chromium.orged1f8d72010-01-26 08:25:16 +0900275 }
276
277 for (int i = 0; i < kCount; ++i) {
278 EXPECT_EQ(external_del_count, 0);
279 EXPECT_EQ(owned_del_count, i);
280
281 map_external.Remove(map_external_ids[i]);
282 map_owned.Remove(map_owned_ids[i]);
283 }
284
285 for (int i = 0; i < kCount; ++i) {
286 delete external_obj[i];
287 }
288
289 EXPECT_EQ(external_del_count, kCount);
290 EXPECT_EQ(owned_del_count, kCount);
291}
292
tfarina@chromium.org6ac12282012-12-04 02:04:28 +0900293TEST(IDMapTest, OwningPointersDeletesThemOnClear) {
jsbell@chromium.org8fe2a8f2012-10-30 06:36:22 +0900294 const int kCount = 3;
295
296 int external_del_count = 0;
297 DestructorCounter* external_obj[kCount];
298
299 int owned_del_count = 0;
jsbell@chromium.org8fe2a8f2012-10-30 06:36:22 +0900300
rlanday644d4f42016-12-01 12:05:40 +0900301 IDMap<DestructorCounter*> map_external;
302 IDMap<std::unique_ptr<DestructorCounter>> map_owned;
jsbell@chromium.org8fe2a8f2012-10-30 06:36:22 +0900303
304 for (int i = 0; i < kCount; ++i) {
305 external_obj[i] = new DestructorCounter(&external_del_count);
306 map_external.Add(external_obj[i]);
307
rlandayf5b01dd2016-12-01 03:59:30 +0900308 map_owned.Add(base::MakeUnique<DestructorCounter>(&owned_del_count));
jsbell@chromium.org8fe2a8f2012-10-30 06:36:22 +0900309 }
310
311 EXPECT_EQ(external_del_count, 0);
312 EXPECT_EQ(owned_del_count, 0);
313
314 map_external.Clear();
315 map_owned.Clear();
316
317 EXPECT_EQ(external_del_count, 0);
318 EXPECT_EQ(owned_del_count, kCount);
319
320 for (int i = 0; i < kCount; ++i) {
321 delete external_obj[i];
322 }
323
324 EXPECT_EQ(external_del_count, kCount);
325 EXPECT_EQ(owned_del_count, kCount);
326}
327
tfarina@chromium.org6ac12282012-12-04 02:04:28 +0900328TEST(IDMapTest, OwningPointersDeletesThemOnDestruct) {
neb@chromium.orged1f8d72010-01-26 08:25:16 +0900329 const int kCount = 3;
330
331 int external_del_count = 0;
332 DestructorCounter* external_obj[kCount];
neb@chromium.orged1f8d72010-01-26 08:25:16 +0900333
334 int owned_del_count = 0;
neb@chromium.orged1f8d72010-01-26 08:25:16 +0900335
336 {
rlanday644d4f42016-12-01 12:05:40 +0900337 IDMap<DestructorCounter*> map_external;
338 IDMap<std::unique_ptr<DestructorCounter>> map_owned;
neb@chromium.orged1f8d72010-01-26 08:25:16 +0900339
340 for (int i = 0; i < kCount; ++i) {
341 external_obj[i] = new DestructorCounter(&external_del_count);
pph34r@gmail.com4f029ab2011-06-25 13:33:18 +0900342 map_external.Add(external_obj[i]);
neb@chromium.orged1f8d72010-01-26 08:25:16 +0900343
rlandayf5b01dd2016-12-01 03:59:30 +0900344 map_owned.Add(base::MakeUnique<DestructorCounter>(&owned_del_count));
neb@chromium.orged1f8d72010-01-26 08:25:16 +0900345 }
346 }
347
348 EXPECT_EQ(external_del_count, 0);
349
350 for (int i = 0; i < kCount; ++i) {
351 delete external_obj[i];
352 }
353
354 EXPECT_EQ(external_del_count, kCount);
355 EXPECT_EQ(owned_del_count, kCount);
356}
357
jkarlina5762912015-09-26 05:45:47 +0900358TEST(IDMapTest, Int64KeyType) {
rlanday644d4f42016-12-01 12:05:40 +0900359 IDMap<TestObject*, int64_t> map;
jkarlina5762912015-09-26 05:45:47 +0900360 TestObject obj1;
361 const int64_t kId1 = 999999999999999999;
362
363 map.AddWithID(&obj1, kId1);
364 EXPECT_EQ(&obj1, map.Lookup(kId1));
365
rlanday644d4f42016-12-01 12:05:40 +0900366 IDMap<TestObject*, int64_t>::const_iterator iter(&map);
bcwhite0ac12b02016-02-23 07:16:10 +0900367 ASSERT_FALSE(iter.IsAtEnd());
368 EXPECT_EQ(kId1, iter.GetCurrentKey());
369 EXPECT_EQ(&obj1, iter.GetCurrentValue());
370 iter.Advance();
371 ASSERT_TRUE(iter.IsAtEnd());
372
jkarlina5762912015-09-26 05:45:47 +0900373 map.Remove(kId1);
374 EXPECT_TRUE(map.IsEmpty());
375}
376
phajdan.jr@chromium.orga12746c2009-08-19 23:56:38 +0900377} // namespace