1*6777b538SAndroid Build Coastguard Worker // Copyright 2011 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "base/containers/id_map.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
8*6777b538SAndroid Build Coastguard Worker
9*6777b538SAndroid Build Coastguard Worker #include <functional>
10*6777b538SAndroid Build Coastguard Worker #include <memory>
11*6777b538SAndroid Build Coastguard Worker
12*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/test/gtest_util.h"
14*6777b538SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
15*6777b538SAndroid Build Coastguard Worker
16*6777b538SAndroid Build Coastguard Worker namespace base::test::id_map {
17*6777b538SAndroid Build Coastguard Worker struct RepeatingKeyType {
RepeatingKeyTypebase::test::id_map::RepeatingKeyType18*6777b538SAndroid Build Coastguard Worker explicit RepeatingKeyType(int i) : i(i) {}
19*6777b538SAndroid Build Coastguard Worker
operator ++base::test::id_map::RepeatingKeyType20*6777b538SAndroid Build Coastguard Worker constexpr void operator++() {}
operator ++base::test::id_map::RepeatingKeyType21*6777b538SAndroid Build Coastguard Worker constexpr RepeatingKeyType& operator++(int) { return *this; }
22*6777b538SAndroid Build Coastguard Worker
operator ==base::test::id_map::RepeatingKeyType23*6777b538SAndroid Build Coastguard Worker constexpr bool operator==(const RepeatingKeyType& o) const {
24*6777b538SAndroid Build Coastguard Worker return i == o.i;
25*6777b538SAndroid Build Coastguard Worker }
operator <base::test::id_map::RepeatingKeyType26*6777b538SAndroid Build Coastguard Worker constexpr bool operator<(const RepeatingKeyType& o) const { return i < o.i; }
27*6777b538SAndroid Build Coastguard Worker
28*6777b538SAndroid Build Coastguard Worker int i = 0;
29*6777b538SAndroid Build Coastguard Worker };
30*6777b538SAndroid Build Coastguard Worker } // namespace base::test::id_map
31*6777b538SAndroid Build Coastguard Worker
32*6777b538SAndroid Build Coastguard Worker namespace std {
33*6777b538SAndroid Build Coastguard Worker template <>
34*6777b538SAndroid Build Coastguard Worker struct hash<::base::test::id_map::RepeatingKeyType> {
operator ()std::hash35*6777b538SAndroid Build Coastguard Worker size_t operator()(
36*6777b538SAndroid Build Coastguard Worker const ::base::test::id_map::RepeatingKeyType& k) const noexcept {
37*6777b538SAndroid Build Coastguard Worker return std::hash<int>()(k.i);
38*6777b538SAndroid Build Coastguard Worker }
39*6777b538SAndroid Build Coastguard Worker };
40*6777b538SAndroid Build Coastguard Worker } // namespace std
41*6777b538SAndroid Build Coastguard Worker
42*6777b538SAndroid Build Coastguard Worker namespace base {
43*6777b538SAndroid Build Coastguard Worker
44*6777b538SAndroid Build Coastguard Worker namespace {
45*6777b538SAndroid Build Coastguard Worker
46*6777b538SAndroid Build Coastguard Worker class TestObject {};
47*6777b538SAndroid Build Coastguard Worker
48*6777b538SAndroid Build Coastguard Worker class DestructorCounter {
49*6777b538SAndroid Build Coastguard Worker public:
DestructorCounter(int * counter)50*6777b538SAndroid Build Coastguard Worker explicit DestructorCounter(int* counter) : counter_(counter) {}
~DestructorCounter()51*6777b538SAndroid Build Coastguard Worker ~DestructorCounter() { ++(*counter_); }
52*6777b538SAndroid Build Coastguard Worker
53*6777b538SAndroid Build Coastguard Worker private:
54*6777b538SAndroid Build Coastguard Worker raw_ptr<int> counter_;
55*6777b538SAndroid Build Coastguard Worker };
56*6777b538SAndroid Build Coastguard Worker
57*6777b538SAndroid Build Coastguard Worker } // namespace
58*6777b538SAndroid Build Coastguard Worker
TEST(IDMapTest,Basic)59*6777b538SAndroid Build Coastguard Worker TEST(IDMapTest, Basic) {
60*6777b538SAndroid Build Coastguard Worker IDMap<TestObject*> map;
61*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(map.IsEmpty());
62*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0U, map.size());
63*6777b538SAndroid Build Coastguard Worker
64*6777b538SAndroid Build Coastguard Worker TestObject obj1;
65*6777b538SAndroid Build Coastguard Worker TestObject obj2;
66*6777b538SAndroid Build Coastguard Worker
67*6777b538SAndroid Build Coastguard Worker int32_t id1 = map.Add(&obj1);
68*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(map.IsEmpty());
69*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1U, map.size());
70*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(&obj1, map.Lookup(id1));
71*6777b538SAndroid Build Coastguard Worker
72*6777b538SAndroid Build Coastguard Worker int32_t id2 = map.Add(&obj2);
73*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(map.IsEmpty());
74*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(2U, map.size());
75*6777b538SAndroid Build Coastguard Worker
76*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(&obj1, map.Lookup(id1));
77*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(&obj2, map.Lookup(id2));
78*6777b538SAndroid Build Coastguard Worker
79*6777b538SAndroid Build Coastguard Worker map.Remove(id1);
80*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(map.IsEmpty());
81*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1U, map.size());
82*6777b538SAndroid Build Coastguard Worker
83*6777b538SAndroid Build Coastguard Worker map.Remove(id2);
84*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(map.IsEmpty());
85*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0U, map.size());
86*6777b538SAndroid Build Coastguard Worker
87*6777b538SAndroid Build Coastguard Worker map.AddWithID(&obj1, 1);
88*6777b538SAndroid Build Coastguard Worker map.AddWithID(&obj2, 2);
89*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(&obj1, map.Lookup(1));
90*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(&obj2, map.Lookup(2));
91*6777b538SAndroid Build Coastguard Worker
92*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(&obj2, map.Replace(2, &obj1));
93*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(&obj1, map.Lookup(2));
94*6777b538SAndroid Build Coastguard Worker
95*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0, map.iteration_depth());
96*6777b538SAndroid Build Coastguard Worker }
97*6777b538SAndroid Build Coastguard Worker
TEST(IDMapTest,IteratorRemainsValidWhenRemovingCurrentElement)98*6777b538SAndroid Build Coastguard Worker TEST(IDMapTest, IteratorRemainsValidWhenRemovingCurrentElement) {
99*6777b538SAndroid Build Coastguard Worker IDMap<TestObject*> map;
100*6777b538SAndroid Build Coastguard Worker
101*6777b538SAndroid Build Coastguard Worker TestObject obj1;
102*6777b538SAndroid Build Coastguard Worker TestObject obj2;
103*6777b538SAndroid Build Coastguard Worker TestObject obj3;
104*6777b538SAndroid Build Coastguard Worker
105*6777b538SAndroid Build Coastguard Worker map.Add(&obj1);
106*6777b538SAndroid Build Coastguard Worker map.Add(&obj2);
107*6777b538SAndroid Build Coastguard Worker map.Add(&obj3);
108*6777b538SAndroid Build Coastguard Worker
109*6777b538SAndroid Build Coastguard Worker {
110*6777b538SAndroid Build Coastguard Worker IDMap<TestObject*>::const_iterator iter(&map);
111*6777b538SAndroid Build Coastguard Worker
112*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, map.iteration_depth());
113*6777b538SAndroid Build Coastguard Worker
114*6777b538SAndroid Build Coastguard Worker while (!iter.IsAtEnd()) {
115*6777b538SAndroid Build Coastguard Worker map.Remove(iter.GetCurrentKey());
116*6777b538SAndroid Build Coastguard Worker iter.Advance();
117*6777b538SAndroid Build Coastguard Worker }
118*6777b538SAndroid Build Coastguard Worker
119*6777b538SAndroid Build Coastguard Worker // Test that while an iterator is still in scope, we get the map emptiness
120*6777b538SAndroid Build Coastguard Worker // right (http://crbug.com/35571).
121*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(map.IsEmpty());
122*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0U, map.size());
123*6777b538SAndroid Build Coastguard Worker }
124*6777b538SAndroid Build Coastguard Worker
125*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(map.IsEmpty());
126*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0U, map.size());
127*6777b538SAndroid Build Coastguard Worker
128*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0, map.iteration_depth());
129*6777b538SAndroid Build Coastguard Worker }
130*6777b538SAndroid Build Coastguard Worker
TEST(IDMapTest,IteratorRemainsValidWhenRemovingOtherElements)131*6777b538SAndroid Build Coastguard Worker TEST(IDMapTest, IteratorRemainsValidWhenRemovingOtherElements) {
132*6777b538SAndroid Build Coastguard Worker IDMap<TestObject*> map;
133*6777b538SAndroid Build Coastguard Worker
134*6777b538SAndroid Build Coastguard Worker const int kCount = 5;
135*6777b538SAndroid Build Coastguard Worker TestObject obj[kCount];
136*6777b538SAndroid Build Coastguard Worker
137*6777b538SAndroid Build Coastguard Worker for (auto& i : obj) {
138*6777b538SAndroid Build Coastguard Worker map.Add(&i);
139*6777b538SAndroid Build Coastguard Worker }
140*6777b538SAndroid Build Coastguard Worker
141*6777b538SAndroid Build Coastguard Worker // IDMap has no predictable iteration order.
142*6777b538SAndroid Build Coastguard Worker int32_t ids_in_iteration_order[kCount];
143*6777b538SAndroid Build Coastguard Worker const TestObject* objs_in_iteration_order[kCount];
144*6777b538SAndroid Build Coastguard Worker int counter = 0;
145*6777b538SAndroid Build Coastguard Worker for (IDMap<TestObject*>::const_iterator iter(&map); !iter.IsAtEnd();
146*6777b538SAndroid Build Coastguard Worker iter.Advance()) {
147*6777b538SAndroid Build Coastguard Worker ids_in_iteration_order[counter] = iter.GetCurrentKey();
148*6777b538SAndroid Build Coastguard Worker objs_in_iteration_order[counter] = iter.GetCurrentValue();
149*6777b538SAndroid Build Coastguard Worker counter++;
150*6777b538SAndroid Build Coastguard Worker }
151*6777b538SAndroid Build Coastguard Worker
152*6777b538SAndroid Build Coastguard Worker counter = 0;
153*6777b538SAndroid Build Coastguard Worker for (IDMap<TestObject*>::const_iterator iter(&map); !iter.IsAtEnd();
154*6777b538SAndroid Build Coastguard Worker iter.Advance()) {
155*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, map.iteration_depth());
156*6777b538SAndroid Build Coastguard Worker
157*6777b538SAndroid Build Coastguard Worker switch (counter) {
158*6777b538SAndroid Build Coastguard Worker case 0:
159*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(ids_in_iteration_order[0], iter.GetCurrentKey());
160*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(objs_in_iteration_order[0], iter.GetCurrentValue());
161*6777b538SAndroid Build Coastguard Worker map.Remove(ids_in_iteration_order[1]);
162*6777b538SAndroid Build Coastguard Worker break;
163*6777b538SAndroid Build Coastguard Worker case 1:
164*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(ids_in_iteration_order[2], iter.GetCurrentKey());
165*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(objs_in_iteration_order[2], iter.GetCurrentValue());
166*6777b538SAndroid Build Coastguard Worker map.Remove(ids_in_iteration_order[3]);
167*6777b538SAndroid Build Coastguard Worker break;
168*6777b538SAndroid Build Coastguard Worker case 2:
169*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(ids_in_iteration_order[4], iter.GetCurrentKey());
170*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(objs_in_iteration_order[4], iter.GetCurrentValue());
171*6777b538SAndroid Build Coastguard Worker map.Remove(ids_in_iteration_order[0]);
172*6777b538SAndroid Build Coastguard Worker break;
173*6777b538SAndroid Build Coastguard Worker default:
174*6777b538SAndroid Build Coastguard Worker FAIL() << "should not have that many elements";
175*6777b538SAndroid Build Coastguard Worker }
176*6777b538SAndroid Build Coastguard Worker
177*6777b538SAndroid Build Coastguard Worker counter++;
178*6777b538SAndroid Build Coastguard Worker }
179*6777b538SAndroid Build Coastguard Worker
180*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0, map.iteration_depth());
181*6777b538SAndroid Build Coastguard Worker }
182*6777b538SAndroid Build Coastguard Worker
TEST(IDMapTest,CopyIterator)183*6777b538SAndroid Build Coastguard Worker TEST(IDMapTest, CopyIterator) {
184*6777b538SAndroid Build Coastguard Worker IDMap<TestObject*> map;
185*6777b538SAndroid Build Coastguard Worker
186*6777b538SAndroid Build Coastguard Worker TestObject obj1;
187*6777b538SAndroid Build Coastguard Worker TestObject obj2;
188*6777b538SAndroid Build Coastguard Worker TestObject obj3;
189*6777b538SAndroid Build Coastguard Worker
190*6777b538SAndroid Build Coastguard Worker map.Add(&obj1);
191*6777b538SAndroid Build Coastguard Worker map.Add(&obj2);
192*6777b538SAndroid Build Coastguard Worker map.Add(&obj3);
193*6777b538SAndroid Build Coastguard Worker
194*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0, map.iteration_depth());
195*6777b538SAndroid Build Coastguard Worker
196*6777b538SAndroid Build Coastguard Worker {
197*6777b538SAndroid Build Coastguard Worker IDMap<TestObject*>::const_iterator iter1(&map);
198*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, map.iteration_depth());
199*6777b538SAndroid Build Coastguard Worker
200*6777b538SAndroid Build Coastguard Worker // Make sure that copying the iterator correctly increments
201*6777b538SAndroid Build Coastguard Worker // map's iteration depth.
202*6777b538SAndroid Build Coastguard Worker IDMap<TestObject*>::const_iterator iter2(iter1);
203*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(2, map.iteration_depth());
204*6777b538SAndroid Build Coastguard Worker }
205*6777b538SAndroid Build Coastguard Worker
206*6777b538SAndroid Build Coastguard Worker // Make sure after destroying all iterators the map's iteration depth
207*6777b538SAndroid Build Coastguard Worker // returns to initial state.
208*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0, map.iteration_depth());
209*6777b538SAndroid Build Coastguard Worker }
210*6777b538SAndroid Build Coastguard Worker
TEST(IDMapTest,AssignIterator)211*6777b538SAndroid Build Coastguard Worker TEST(IDMapTest, AssignIterator) {
212*6777b538SAndroid Build Coastguard Worker IDMap<TestObject*> map;
213*6777b538SAndroid Build Coastguard Worker
214*6777b538SAndroid Build Coastguard Worker TestObject obj1;
215*6777b538SAndroid Build Coastguard Worker TestObject obj2;
216*6777b538SAndroid Build Coastguard Worker TestObject obj3;
217*6777b538SAndroid Build Coastguard Worker
218*6777b538SAndroid Build Coastguard Worker map.Add(&obj1);
219*6777b538SAndroid Build Coastguard Worker map.Add(&obj2);
220*6777b538SAndroid Build Coastguard Worker map.Add(&obj3);
221*6777b538SAndroid Build Coastguard Worker
222*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0, map.iteration_depth());
223*6777b538SAndroid Build Coastguard Worker
224*6777b538SAndroid Build Coastguard Worker {
225*6777b538SAndroid Build Coastguard Worker IDMap<TestObject*>::const_iterator iter1(&map);
226*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, map.iteration_depth());
227*6777b538SAndroid Build Coastguard Worker
228*6777b538SAndroid Build Coastguard Worker IDMap<TestObject*>::const_iterator iter2(&map);
229*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(2, map.iteration_depth());
230*6777b538SAndroid Build Coastguard Worker
231*6777b538SAndroid Build Coastguard Worker // Make sure that assigning the iterator correctly updates
232*6777b538SAndroid Build Coastguard Worker // map's iteration depth (-1 for destruction, +1 for assignment).
233*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(2, map.iteration_depth());
234*6777b538SAndroid Build Coastguard Worker }
235*6777b538SAndroid Build Coastguard Worker
236*6777b538SAndroid Build Coastguard Worker // Make sure after destroying all iterators the map's iteration depth
237*6777b538SAndroid Build Coastguard Worker // returns to initial state.
238*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0, map.iteration_depth());
239*6777b538SAndroid Build Coastguard Worker }
240*6777b538SAndroid Build Coastguard Worker
TEST(IDMapTest,IteratorRemainsValidWhenClearing)241*6777b538SAndroid Build Coastguard Worker TEST(IDMapTest, IteratorRemainsValidWhenClearing) {
242*6777b538SAndroid Build Coastguard Worker IDMap<TestObject*> map;
243*6777b538SAndroid Build Coastguard Worker
244*6777b538SAndroid Build Coastguard Worker const int kCount = 5;
245*6777b538SAndroid Build Coastguard Worker TestObject obj[kCount];
246*6777b538SAndroid Build Coastguard Worker
247*6777b538SAndroid Build Coastguard Worker for (auto& i : obj) {
248*6777b538SAndroid Build Coastguard Worker map.Add(&i);
249*6777b538SAndroid Build Coastguard Worker }
250*6777b538SAndroid Build Coastguard Worker
251*6777b538SAndroid Build Coastguard Worker // IDMap has no predictable iteration order.
252*6777b538SAndroid Build Coastguard Worker int32_t ids_in_iteration_order[kCount];
253*6777b538SAndroid Build Coastguard Worker const TestObject* objs_in_iteration_order[kCount];
254*6777b538SAndroid Build Coastguard Worker int counter = 0;
255*6777b538SAndroid Build Coastguard Worker for (IDMap<TestObject*>::const_iterator iter(&map); !iter.IsAtEnd();
256*6777b538SAndroid Build Coastguard Worker iter.Advance()) {
257*6777b538SAndroid Build Coastguard Worker ids_in_iteration_order[counter] = iter.GetCurrentKey();
258*6777b538SAndroid Build Coastguard Worker objs_in_iteration_order[counter] = iter.GetCurrentValue();
259*6777b538SAndroid Build Coastguard Worker counter++;
260*6777b538SAndroid Build Coastguard Worker }
261*6777b538SAndroid Build Coastguard Worker
262*6777b538SAndroid Build Coastguard Worker counter = 0;
263*6777b538SAndroid Build Coastguard Worker for (IDMap<TestObject*>::const_iterator iter(&map); !iter.IsAtEnd();
264*6777b538SAndroid Build Coastguard Worker iter.Advance()) {
265*6777b538SAndroid Build Coastguard Worker switch (counter) {
266*6777b538SAndroid Build Coastguard Worker case 0:
267*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(ids_in_iteration_order[0], iter.GetCurrentKey());
268*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(objs_in_iteration_order[0], iter.GetCurrentValue());
269*6777b538SAndroid Build Coastguard Worker break;
270*6777b538SAndroid Build Coastguard Worker case 1:
271*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(ids_in_iteration_order[1], iter.GetCurrentKey());
272*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(objs_in_iteration_order[1], iter.GetCurrentValue());
273*6777b538SAndroid Build Coastguard Worker map.Clear();
274*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(map.IsEmpty());
275*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0U, map.size());
276*6777b538SAndroid Build Coastguard Worker break;
277*6777b538SAndroid Build Coastguard Worker default:
278*6777b538SAndroid Build Coastguard Worker FAIL() << "should not have that many elements";
279*6777b538SAndroid Build Coastguard Worker }
280*6777b538SAndroid Build Coastguard Worker counter++;
281*6777b538SAndroid Build Coastguard Worker }
282*6777b538SAndroid Build Coastguard Worker
283*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(map.IsEmpty());
284*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0U, map.size());
285*6777b538SAndroid Build Coastguard Worker }
286*6777b538SAndroid Build Coastguard Worker
TEST(IDMapTest,OwningPointersDeletesThemOnRemove)287*6777b538SAndroid Build Coastguard Worker TEST(IDMapTest, OwningPointersDeletesThemOnRemove) {
288*6777b538SAndroid Build Coastguard Worker const int kCount = 3;
289*6777b538SAndroid Build Coastguard Worker
290*6777b538SAndroid Build Coastguard Worker int external_del_count = 0;
291*6777b538SAndroid Build Coastguard Worker DestructorCounter* external_obj[kCount];
292*6777b538SAndroid Build Coastguard Worker int map_external_ids[kCount];
293*6777b538SAndroid Build Coastguard Worker
294*6777b538SAndroid Build Coastguard Worker int owned_del_count = 0;
295*6777b538SAndroid Build Coastguard Worker int map_owned_ids[kCount];
296*6777b538SAndroid Build Coastguard Worker
297*6777b538SAndroid Build Coastguard Worker IDMap<DestructorCounter*> map_external;
298*6777b538SAndroid Build Coastguard Worker IDMap<std::unique_ptr<DestructorCounter>> map_owned;
299*6777b538SAndroid Build Coastguard Worker
300*6777b538SAndroid Build Coastguard Worker for (int i = 0; i < kCount; ++i) {
301*6777b538SAndroid Build Coastguard Worker external_obj[i] = new DestructorCounter(&external_del_count);
302*6777b538SAndroid Build Coastguard Worker map_external_ids[i] = map_external.Add(external_obj[i]);
303*6777b538SAndroid Build Coastguard Worker
304*6777b538SAndroid Build Coastguard Worker map_owned_ids[i] =
305*6777b538SAndroid Build Coastguard Worker map_owned.Add(std::make_unique<DestructorCounter>(&owned_del_count));
306*6777b538SAndroid Build Coastguard Worker }
307*6777b538SAndroid Build Coastguard Worker
308*6777b538SAndroid Build Coastguard Worker for (int i = 0; i < kCount; ++i) {
309*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(external_del_count, 0);
310*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(owned_del_count, i);
311*6777b538SAndroid Build Coastguard Worker
312*6777b538SAndroid Build Coastguard Worker map_external.Remove(map_external_ids[i]);
313*6777b538SAndroid Build Coastguard Worker map_owned.Remove(map_owned_ids[i]);
314*6777b538SAndroid Build Coastguard Worker }
315*6777b538SAndroid Build Coastguard Worker
316*6777b538SAndroid Build Coastguard Worker for (auto* i : external_obj) {
317*6777b538SAndroid Build Coastguard Worker delete i;
318*6777b538SAndroid Build Coastguard Worker }
319*6777b538SAndroid Build Coastguard Worker
320*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(external_del_count, kCount);
321*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(owned_del_count, kCount);
322*6777b538SAndroid Build Coastguard Worker }
323*6777b538SAndroid Build Coastguard Worker
TEST(IDMapTest,OwningPointersDeletesThemOnClear)324*6777b538SAndroid Build Coastguard Worker TEST(IDMapTest, OwningPointersDeletesThemOnClear) {
325*6777b538SAndroid Build Coastguard Worker const int kCount = 3;
326*6777b538SAndroid Build Coastguard Worker
327*6777b538SAndroid Build Coastguard Worker int external_del_count = 0;
328*6777b538SAndroid Build Coastguard Worker DestructorCounter* external_obj[kCount];
329*6777b538SAndroid Build Coastguard Worker
330*6777b538SAndroid Build Coastguard Worker int owned_del_count = 0;
331*6777b538SAndroid Build Coastguard Worker
332*6777b538SAndroid Build Coastguard Worker IDMap<DestructorCounter*> map_external;
333*6777b538SAndroid Build Coastguard Worker IDMap<std::unique_ptr<DestructorCounter>> map_owned;
334*6777b538SAndroid Build Coastguard Worker
335*6777b538SAndroid Build Coastguard Worker for (auto*& i : external_obj) {
336*6777b538SAndroid Build Coastguard Worker i = new DestructorCounter(&external_del_count);
337*6777b538SAndroid Build Coastguard Worker map_external.Add(i);
338*6777b538SAndroid Build Coastguard Worker
339*6777b538SAndroid Build Coastguard Worker map_owned.Add(std::make_unique<DestructorCounter>(&owned_del_count));
340*6777b538SAndroid Build Coastguard Worker }
341*6777b538SAndroid Build Coastguard Worker
342*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(external_del_count, 0);
343*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(owned_del_count, 0);
344*6777b538SAndroid Build Coastguard Worker
345*6777b538SAndroid Build Coastguard Worker map_external.Clear();
346*6777b538SAndroid Build Coastguard Worker map_owned.Clear();
347*6777b538SAndroid Build Coastguard Worker
348*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(external_del_count, 0);
349*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(owned_del_count, kCount);
350*6777b538SAndroid Build Coastguard Worker
351*6777b538SAndroid Build Coastguard Worker for (auto* i : external_obj) {
352*6777b538SAndroid Build Coastguard Worker delete i;
353*6777b538SAndroid Build Coastguard Worker }
354*6777b538SAndroid Build Coastguard Worker
355*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(external_del_count, kCount);
356*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(owned_del_count, kCount);
357*6777b538SAndroid Build Coastguard Worker }
358*6777b538SAndroid Build Coastguard Worker
TEST(IDMapTest,OwningPointersDeletesThemOnDestruct)359*6777b538SAndroid Build Coastguard Worker TEST(IDMapTest, OwningPointersDeletesThemOnDestruct) {
360*6777b538SAndroid Build Coastguard Worker const int kCount = 3;
361*6777b538SAndroid Build Coastguard Worker
362*6777b538SAndroid Build Coastguard Worker int external_del_count = 0;
363*6777b538SAndroid Build Coastguard Worker DestructorCounter* external_obj[kCount];
364*6777b538SAndroid Build Coastguard Worker
365*6777b538SAndroid Build Coastguard Worker int owned_del_count = 0;
366*6777b538SAndroid Build Coastguard Worker
367*6777b538SAndroid Build Coastguard Worker {
368*6777b538SAndroid Build Coastguard Worker IDMap<DestructorCounter*> map_external;
369*6777b538SAndroid Build Coastguard Worker IDMap<std::unique_ptr<DestructorCounter>> map_owned;
370*6777b538SAndroid Build Coastguard Worker
371*6777b538SAndroid Build Coastguard Worker for (auto*& i : external_obj) {
372*6777b538SAndroid Build Coastguard Worker i = new DestructorCounter(&external_del_count);
373*6777b538SAndroid Build Coastguard Worker map_external.Add(i);
374*6777b538SAndroid Build Coastguard Worker
375*6777b538SAndroid Build Coastguard Worker map_owned.Add(std::make_unique<DestructorCounter>(&owned_del_count));
376*6777b538SAndroid Build Coastguard Worker }
377*6777b538SAndroid Build Coastguard Worker }
378*6777b538SAndroid Build Coastguard Worker
379*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(external_del_count, 0);
380*6777b538SAndroid Build Coastguard Worker
381*6777b538SAndroid Build Coastguard Worker for (auto* i : external_obj) {
382*6777b538SAndroid Build Coastguard Worker delete i;
383*6777b538SAndroid Build Coastguard Worker }
384*6777b538SAndroid Build Coastguard Worker
385*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(external_del_count, kCount);
386*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(owned_del_count, kCount);
387*6777b538SAndroid Build Coastguard Worker }
388*6777b538SAndroid Build Coastguard Worker
TEST(IDMapTest,Int64KeyType)389*6777b538SAndroid Build Coastguard Worker TEST(IDMapTest, Int64KeyType) {
390*6777b538SAndroid Build Coastguard Worker IDMap<TestObject*, int64_t> map;
391*6777b538SAndroid Build Coastguard Worker TestObject obj1;
392*6777b538SAndroid Build Coastguard Worker const int64_t kId1 = 999999999999999999;
393*6777b538SAndroid Build Coastguard Worker
394*6777b538SAndroid Build Coastguard Worker map.AddWithID(&obj1, kId1);
395*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(&obj1, map.Lookup(kId1));
396*6777b538SAndroid Build Coastguard Worker
397*6777b538SAndroid Build Coastguard Worker IDMap<TestObject*, int64_t>::const_iterator iter(&map);
398*6777b538SAndroid Build Coastguard Worker ASSERT_FALSE(iter.IsAtEnd());
399*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(kId1, iter.GetCurrentKey());
400*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(&obj1, iter.GetCurrentValue());
401*6777b538SAndroid Build Coastguard Worker iter.Advance();
402*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(iter.IsAtEnd());
403*6777b538SAndroid Build Coastguard Worker
404*6777b538SAndroid Build Coastguard Worker map.Remove(kId1);
405*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(map.IsEmpty());
406*6777b538SAndroid Build Coastguard Worker }
407*6777b538SAndroid Build Coastguard Worker
TEST(IDMapTest,RemovedValueHandling)408*6777b538SAndroid Build Coastguard Worker TEST(IDMapTest, RemovedValueHandling) {
409*6777b538SAndroid Build Coastguard Worker TestObject obj;
410*6777b538SAndroid Build Coastguard Worker {
411*6777b538SAndroid Build Coastguard Worker IDMap<TestObject*> map;
412*6777b538SAndroid Build Coastguard Worker int key = map.Add(&obj);
413*6777b538SAndroid Build Coastguard Worker
414*6777b538SAndroid Build Coastguard Worker IDMap<TestObject*>::iterator itr(&map);
415*6777b538SAndroid Build Coastguard Worker // Queues the `key` for removal.
416*6777b538SAndroid Build Coastguard Worker map.Clear();
417*6777b538SAndroid Build Coastguard Worker // Removes nothing, already queued.
418*6777b538SAndroid Build Coastguard Worker map.Remove(key);
419*6777b538SAndroid Build Coastguard Worker // Can not replace a key that is not present. If it's queued for removal
420*6777b538SAndroid Build Coastguard Worker // it's not present.
421*6777b538SAndroid Build Coastguard Worker EXPECT_CHECK_DEATH(map.Replace(key, &obj));
422*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(map.Lookup(key));
423*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(itr.IsAtEnd());
424*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(itr.GetCurrentValue());
425*6777b538SAndroid Build Coastguard Worker
426*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(map.IsEmpty());
427*6777b538SAndroid Build Coastguard Worker // Replaces the element that's queued for removal when `itr` is destroyed.
428*6777b538SAndroid Build Coastguard Worker map.AddWithID(&obj, key);
429*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1u, map.size());
430*6777b538SAndroid Build Coastguard Worker }
431*6777b538SAndroid Build Coastguard Worker
432*6777b538SAndroid Build Coastguard Worker {
433*6777b538SAndroid Build Coastguard Worker using base::test::id_map::RepeatingKeyType;
434*6777b538SAndroid Build Coastguard Worker
435*6777b538SAndroid Build Coastguard Worker IDMap<TestObject*, RepeatingKeyType> map;
436*6777b538SAndroid Build Coastguard Worker RepeatingKeyType key = map.Add(&obj);
437*6777b538SAndroid Build Coastguard Worker IDMap<TestObject*, RepeatingKeyType>::iterator itr(&map);
438*6777b538SAndroid Build Coastguard Worker map.Remove(key); // Queues it for removal.
439*6777b538SAndroid Build Coastguard Worker
440*6777b538SAndroid Build Coastguard Worker // The RepeatingKeyType's operator++ does not always return a unique id. The
441*6777b538SAndroid Build Coastguard Worker // Add() method does not make extra assumptions about this, and can replace
442*6777b538SAndroid Build Coastguard Worker // a queued-for-removal item just like AddWithID().
443*6777b538SAndroid Build Coastguard Worker
444*6777b538SAndroid Build Coastguard Worker // Replaces the element that's queued for removal when `itr` is destroyed.
445*6777b538SAndroid Build Coastguard Worker RepeatingKeyType key2 = map.Add(&obj);
446*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(key, key2);
447*6777b538SAndroid Build Coastguard Worker }
448*6777b538SAndroid Build Coastguard Worker }
449*6777b538SAndroid Build Coastguard Worker
450*6777b538SAndroid Build Coastguard Worker } // namespace base
451