• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2009 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.
4 
5 #include "base/id_map.h"
6 
7 #include "testing/gtest/include/gtest/gtest.h"
8 
9 namespace {
10 
11 class IDMapTest : public testing::Test {
12 };
13 
14 class TestObject {
15 };
16 
17 class DestructorCounter {
18  public:
DestructorCounter(int * counter)19   explicit DestructorCounter(int* counter) : counter_(counter) {}
~DestructorCounter()20   ~DestructorCounter() { ++(*counter_); }
21  private:
22   int* counter_;
23 };
24 
TEST_F(IDMapTest,Basic)25 TEST_F(IDMapTest, Basic) {
26   IDMap<TestObject> map;
27   EXPECT_TRUE(map.IsEmpty());
28   EXPECT_EQ(0U, map.size());
29 
30   TestObject obj1;
31   TestObject obj2;
32 
33   int32 id1 = map.Add(&obj1);
34   EXPECT_FALSE(map.IsEmpty());
35   EXPECT_EQ(1U, map.size());
36   EXPECT_EQ(&obj1, map.Lookup(id1));
37 
38   int32 id2 = map.Add(&obj2);
39   EXPECT_FALSE(map.IsEmpty());
40   EXPECT_EQ(2U, map.size());
41 
42   EXPECT_EQ(&obj1, map.Lookup(id1));
43   EXPECT_EQ(&obj2, map.Lookup(id2));
44 
45   map.Remove(id1);
46   EXPECT_FALSE(map.IsEmpty());
47   EXPECT_EQ(1U, map.size());
48 
49   map.Remove(id2);
50   EXPECT_TRUE(map.IsEmpty());
51   EXPECT_EQ(0U, map.size());
52 
53   map.AddWithID(&obj1, 1);
54   map.AddWithID(&obj2, 2);
55   EXPECT_EQ(&obj1, map.Lookup(1));
56   EXPECT_EQ(&obj2, map.Lookup(2));
57 }
58 
TEST_F(IDMapTest,IteratorRemainsValidWhenRemovingCurrentElement)59 TEST_F(IDMapTest, IteratorRemainsValidWhenRemovingCurrentElement) {
60   IDMap<TestObject> map;
61 
62   TestObject obj1;
63   TestObject obj2;
64   TestObject obj3;
65 
66   map.Add(&obj1);
67   map.Add(&obj2);
68   map.Add(&obj3);
69 
70   {
71     IDMap<TestObject>::const_iterator iter(&map);
72     while (!iter.IsAtEnd()) {
73       map.Remove(iter.GetCurrentKey());
74       iter.Advance();
75     }
76 
77     // Test that while an iterator is still in scope, we get the map emptiness
78     // right (http://crbug.com/35571).
79     EXPECT_TRUE(map.IsEmpty());
80     EXPECT_EQ(0U, map.size());
81   }
82 
83   EXPECT_TRUE(map.IsEmpty());
84   EXPECT_EQ(0U, map.size());
85 }
86 
TEST_F(IDMapTest,IteratorRemainsValidWhenRemovingOtherElements)87 TEST_F(IDMapTest, IteratorRemainsValidWhenRemovingOtherElements) {
88   IDMap<TestObject> map;
89 
90   const int kCount = 5;
91   TestObject obj[kCount];
92   int32 ids[kCount];
93 
94   for (int i = 0; i < kCount; i++)
95     ids[i] = map.Add(&obj[i]);
96 
97   int counter = 0;
98   for (IDMap<TestObject>::const_iterator iter(&map);
99        !iter.IsAtEnd(); iter.Advance()) {
100     switch (counter) {
101       case 0:
102         EXPECT_EQ(ids[0], iter.GetCurrentKey());
103         EXPECT_EQ(&obj[0], iter.GetCurrentValue());
104         map.Remove(ids[1]);
105         break;
106       case 1:
107         EXPECT_EQ(ids[2], iter.GetCurrentKey());
108         EXPECT_EQ(&obj[2], iter.GetCurrentValue());
109         map.Remove(ids[3]);
110         break;
111       case 2:
112         EXPECT_EQ(ids[4], iter.GetCurrentKey());
113         EXPECT_EQ(&obj[4], iter.GetCurrentValue());
114         map.Remove(ids[0]);
115         break;
116       default:
117         FAIL() << "should not have that many elements";
118         break;
119     }
120 
121     counter++;
122   }
123 }
124 
TEST_F(IDMapTest,OwningPointersDeletesThemOnRemove)125 TEST_F(IDMapTest, OwningPointersDeletesThemOnRemove) {
126   const int kCount = 3;
127 
128   int external_del_count = 0;
129   DestructorCounter* external_obj[kCount];
130   int map_external_ids[kCount];
131 
132   int owned_del_count = 0;
133   DestructorCounter* owned_obj[kCount];
134   int map_owned_ids[kCount];
135 
136   IDMap<DestructorCounter> map_external;
137   IDMap<DestructorCounter, IDMapOwnPointer> map_owned;
138 
139   for (int i = 0; i < kCount; ++i) {
140     external_obj[i] = new DestructorCounter(&external_del_count);
141     map_external_ids[i] = map_external.Add(external_obj[i]);
142 
143     owned_obj[i] = new DestructorCounter(&owned_del_count);
144     map_owned_ids[i] = map_owned.Add(owned_obj[i]);
145   }
146 
147   for (int i = 0; i < kCount; ++i) {
148     EXPECT_EQ(external_del_count, 0);
149     EXPECT_EQ(owned_del_count, i);
150 
151     map_external.Remove(map_external_ids[i]);
152     map_owned.Remove(map_owned_ids[i]);
153   }
154 
155   for (int i = 0; i < kCount; ++i) {
156     delete external_obj[i];
157   }
158 
159   EXPECT_EQ(external_del_count, kCount);
160   EXPECT_EQ(owned_del_count, kCount);
161 }
162 
TEST_F(IDMapTest,OwningPointersDeletesThemOnDestruct)163 TEST_F(IDMapTest, OwningPointersDeletesThemOnDestruct) {
164   const int kCount = 3;
165 
166   int external_del_count = 0;
167   DestructorCounter* external_obj[kCount];
168   int map_external_ids[kCount];
169 
170   int owned_del_count = 0;
171   DestructorCounter* owned_obj[kCount];
172   int map_owned_ids[kCount];
173 
174   {
175     IDMap<DestructorCounter> map_external;
176     IDMap<DestructorCounter, IDMapOwnPointer> map_owned;
177 
178     for (int i = 0; i < kCount; ++i) {
179       external_obj[i] = new DestructorCounter(&external_del_count);
180       map_external_ids[i] = map_external.Add(external_obj[i]);
181 
182       owned_obj[i] = new DestructorCounter(&owned_del_count);
183       map_owned_ids[i] = map_owned.Add(owned_obj[i]);
184     }
185   }
186 
187   EXPECT_EQ(external_del_count, 0);
188 
189   for (int i = 0; i < kCount; ++i) {
190     delete external_obj[i];
191   }
192 
193   EXPECT_EQ(external_del_count, kCount);
194   EXPECT_EQ(owned_del_count, kCount);
195 }
196 
197 }  // namespace
198