1 // Copyright (c) 2011 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/id_map.h"
7 #include "testing/gtest/include/gtest/gtest.h"
14 class DestructorCounter
{
16 explicit DestructorCounter(int* counter
) : counter_(counter
) {}
17 ~DestructorCounter() { ++(*counter_
); }
23 TEST(IDMapTest
, Basic
) {
24 IDMap
<TestObject
> map
;
25 EXPECT_TRUE(map
.IsEmpty());
26 EXPECT_EQ(0U, map
.size());
31 int32 id1
= map
.Add(&obj1
);
32 EXPECT_FALSE(map
.IsEmpty());
33 EXPECT_EQ(1U, map
.size());
34 EXPECT_EQ(&obj1
, map
.Lookup(id1
));
36 int32 id2
= map
.Add(&obj2
);
37 EXPECT_FALSE(map
.IsEmpty());
38 EXPECT_EQ(2U, map
.size());
40 EXPECT_EQ(&obj1
, map
.Lookup(id1
));
41 EXPECT_EQ(&obj2
, map
.Lookup(id2
));
44 EXPECT_FALSE(map
.IsEmpty());
45 EXPECT_EQ(1U, map
.size());
48 EXPECT_TRUE(map
.IsEmpty());
49 EXPECT_EQ(0U, map
.size());
51 map
.AddWithID(&obj1
, 1);
52 map
.AddWithID(&obj2
, 2);
53 EXPECT_EQ(&obj1
, map
.Lookup(1));
54 EXPECT_EQ(&obj2
, map
.Lookup(2));
56 EXPECT_EQ(0, map
.iteration_depth());
59 TEST(IDMapTest
, IteratorRemainsValidWhenRemovingCurrentElement
) {
60 IDMap
<TestObject
> map
;
71 IDMap
<TestObject
>::const_iterator
iter(&map
);
73 EXPECT_EQ(1, map
.iteration_depth());
75 while (!iter
.IsAtEnd()) {
76 map
.Remove(iter
.GetCurrentKey());
80 // Test that while an iterator is still in scope, we get the map emptiness
81 // right (http://crbug.com/35571).
82 EXPECT_TRUE(map
.IsEmpty());
83 EXPECT_EQ(0U, map
.size());
86 EXPECT_TRUE(map
.IsEmpty());
87 EXPECT_EQ(0U, map
.size());
89 EXPECT_EQ(0, map
.iteration_depth());
92 TEST(IDMapTest
, IteratorRemainsValidWhenRemovingOtherElements
) {
93 IDMap
<TestObject
> map
;
96 TestObject obj
[kCount
];
98 for (int i
= 0; i
< kCount
; i
++)
101 // IDMap uses a hash_map, which has no predictable iteration order.
102 int32 ids_in_iteration_order
[kCount
];
103 const TestObject
* objs_in_iteration_order
[kCount
];
105 for (IDMap
<TestObject
>::const_iterator
iter(&map
);
106 !iter
.IsAtEnd(); iter
.Advance()) {
107 ids_in_iteration_order
[counter
] = iter
.GetCurrentKey();
108 objs_in_iteration_order
[counter
] = iter
.GetCurrentValue();
113 for (IDMap
<TestObject
>::const_iterator
iter(&map
);
114 !iter
.IsAtEnd(); iter
.Advance()) {
115 EXPECT_EQ(1, map
.iteration_depth());
119 EXPECT_EQ(ids_in_iteration_order
[0], iter
.GetCurrentKey());
120 EXPECT_EQ(objs_in_iteration_order
[0], iter
.GetCurrentValue());
121 map
.Remove(ids_in_iteration_order
[1]);
124 EXPECT_EQ(ids_in_iteration_order
[2], iter
.GetCurrentKey());
125 EXPECT_EQ(objs_in_iteration_order
[2], iter
.GetCurrentValue());
126 map
.Remove(ids_in_iteration_order
[3]);
129 EXPECT_EQ(ids_in_iteration_order
[4], iter
.GetCurrentKey());
130 EXPECT_EQ(objs_in_iteration_order
[4], iter
.GetCurrentValue());
131 map
.Remove(ids_in_iteration_order
[0]);
134 FAIL() << "should not have that many elements";
141 EXPECT_EQ(0, map
.iteration_depth());
144 TEST(IDMapTest
, CopyIterator
) {
145 IDMap
<TestObject
> map
;
155 EXPECT_EQ(0, map
.iteration_depth());
158 IDMap
<TestObject
>::const_iterator
iter1(&map
);
159 EXPECT_EQ(1, map
.iteration_depth());
161 // Make sure that copying the iterator correctly increments
162 // map's iteration depth.
163 IDMap
<TestObject
>::const_iterator
iter2(iter1
);
164 EXPECT_EQ(2, map
.iteration_depth());
167 // Make sure after destroying all iterators the map's iteration depth
168 // returns to initial state.
169 EXPECT_EQ(0, map
.iteration_depth());
172 TEST(IDMapTest
, AssignIterator
) {
173 IDMap
<TestObject
> map
;
183 EXPECT_EQ(0, map
.iteration_depth());
186 IDMap
<TestObject
>::const_iterator
iter1(&map
);
187 EXPECT_EQ(1, map
.iteration_depth());
189 IDMap
<TestObject
>::const_iterator
iter2(&map
);
190 EXPECT_EQ(2, map
.iteration_depth());
192 // Make sure that assigning the iterator correctly updates
193 // map's iteration depth (-1 for destruction, +1 for assignment).
194 EXPECT_EQ(2, map
.iteration_depth());
197 // Make sure after destroying all iterators the map's iteration depth
198 // returns to initial state.
199 EXPECT_EQ(0, map
.iteration_depth());
202 TEST(IDMapTest
, IteratorRemainsValidWhenClearing
) {
203 IDMap
<TestObject
> map
;
205 const int kCount
= 5;
206 TestObject obj
[kCount
];
208 for (int i
= 0; i
< kCount
; i
++)
211 // IDMap uses a hash_map, which has no predictable iteration order.
212 int32 ids_in_iteration_order
[kCount
];
213 const TestObject
* objs_in_iteration_order
[kCount
];
215 for (IDMap
<TestObject
>::const_iterator
iter(&map
);
216 !iter
.IsAtEnd(); iter
.Advance()) {
217 ids_in_iteration_order
[counter
] = iter
.GetCurrentKey();
218 objs_in_iteration_order
[counter
] = iter
.GetCurrentValue();
223 for (IDMap
<TestObject
>::const_iterator
iter(&map
);
224 !iter
.IsAtEnd(); iter
.Advance()) {
227 EXPECT_EQ(ids_in_iteration_order
[0], iter
.GetCurrentKey());
228 EXPECT_EQ(objs_in_iteration_order
[0], iter
.GetCurrentValue());
231 EXPECT_EQ(ids_in_iteration_order
[1], iter
.GetCurrentKey());
232 EXPECT_EQ(objs_in_iteration_order
[1], iter
.GetCurrentValue());
234 EXPECT_TRUE(map
.IsEmpty());
235 EXPECT_EQ(0U, map
.size());
238 FAIL() << "should not have that many elements";
244 EXPECT_TRUE(map
.IsEmpty());
245 EXPECT_EQ(0U, map
.size());
248 TEST(IDMapTest
, OwningPointersDeletesThemOnRemove
) {
249 const int kCount
= 3;
251 int external_del_count
= 0;
252 DestructorCounter
* external_obj
[kCount
];
253 int map_external_ids
[kCount
];
255 int owned_del_count
= 0;
256 DestructorCounter
* owned_obj
[kCount
];
257 int map_owned_ids
[kCount
];
259 IDMap
<DestructorCounter
> map_external
;
260 IDMap
<DestructorCounter
, IDMapOwnPointer
> map_owned
;
262 for (int i
= 0; i
< kCount
; ++i
) {
263 external_obj
[i
] = new DestructorCounter(&external_del_count
);
264 map_external_ids
[i
] = map_external
.Add(external_obj
[i
]);
266 owned_obj
[i
] = new DestructorCounter(&owned_del_count
);
267 map_owned_ids
[i
] = map_owned
.Add(owned_obj
[i
]);
270 for (int i
= 0; i
< kCount
; ++i
) {
271 EXPECT_EQ(external_del_count
, 0);
272 EXPECT_EQ(owned_del_count
, i
);
274 map_external
.Remove(map_external_ids
[i
]);
275 map_owned
.Remove(map_owned_ids
[i
]);
278 for (int i
= 0; i
< kCount
; ++i
) {
279 delete external_obj
[i
];
282 EXPECT_EQ(external_del_count
, kCount
);
283 EXPECT_EQ(owned_del_count
, kCount
);
286 TEST(IDMapTest
, OwningPointersDeletesThemOnClear
) {
287 const int kCount
= 3;
289 int external_del_count
= 0;
290 DestructorCounter
* external_obj
[kCount
];
292 int owned_del_count
= 0;
293 DestructorCounter
* owned_obj
[kCount
];
295 IDMap
<DestructorCounter
> map_external
;
296 IDMap
<DestructorCounter
, IDMapOwnPointer
> map_owned
;
298 for (int i
= 0; i
< kCount
; ++i
) {
299 external_obj
[i
] = new DestructorCounter(&external_del_count
);
300 map_external
.Add(external_obj
[i
]);
302 owned_obj
[i
] = new DestructorCounter(&owned_del_count
);
303 map_owned
.Add(owned_obj
[i
]);
306 EXPECT_EQ(external_del_count
, 0);
307 EXPECT_EQ(owned_del_count
, 0);
309 map_external
.Clear();
312 EXPECT_EQ(external_del_count
, 0);
313 EXPECT_EQ(owned_del_count
, kCount
);
315 for (int i
= 0; i
< kCount
; ++i
) {
316 delete external_obj
[i
];
319 EXPECT_EQ(external_del_count
, kCount
);
320 EXPECT_EQ(owned_del_count
, kCount
);
323 TEST(IDMapTest
, OwningPointersDeletesThemOnDestruct
) {
324 const int kCount
= 3;
326 int external_del_count
= 0;
327 DestructorCounter
* external_obj
[kCount
];
329 int owned_del_count
= 0;
330 DestructorCounter
* owned_obj
[kCount
];
333 IDMap
<DestructorCounter
> map_external
;
334 IDMap
<DestructorCounter
, IDMapOwnPointer
> map_owned
;
336 for (int i
= 0; i
< kCount
; ++i
) {
337 external_obj
[i
] = new DestructorCounter(&external_del_count
);
338 map_external
.Add(external_obj
[i
]);
340 owned_obj
[i
] = new DestructorCounter(&owned_del_count
);
341 map_owned
.Add(owned_obj
[i
]);
345 EXPECT_EQ(external_del_count
, 0);
347 for (int i
= 0; i
< kCount
; ++i
) {
348 delete external_obj
[i
];
351 EXPECT_EQ(external_del_count
, kCount
);
352 EXPECT_EQ(owned_del_count
, kCount
);