xref: /aosp_15_r20/external/cronet/base/containers/id_map_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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