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. 4 5 #include "base/id_map.h" 6 7 #include "testing/gtest/include/gtest/gtest.h" 8 9 namespace { 10 11 class TestObject { 12 }; 13 14 class DestructorCounter { 15 public: 16 explicit DestructorCounter(int* counter) : counter_(counter) {} 17 ~DestructorCounter() { ++(*counter_); } 18 19 private: 20 int* counter_; 21 }; 22 23 TEST(IDMapTest, Basic) { 24 IDMap<TestObject> map; 25 EXPECT_TRUE(map.IsEmpty()); 26 EXPECT_EQ(0U, map.size()); 27 28 TestObject obj1; 29 TestObject obj2; 30 31 int32 id1 = map.Add(&obj1); 32 EXPECT_FALSE(map.IsEmpty()); 33 EXPECT_EQ(1U, map.size()); 34 EXPECT_EQ(&obj1, map.Lookup(id1)); 35 36 int32 id2 = map.Add(&obj2); 37 EXPECT_FALSE(map.IsEmpty()); 38 EXPECT_EQ(2U, map.size()); 39 40 EXPECT_EQ(&obj1, map.Lookup(id1)); 41 EXPECT_EQ(&obj2, map.Lookup(id2)); 42 43 map.Remove(id1); 44 EXPECT_FALSE(map.IsEmpty()); 45 EXPECT_EQ(1U, map.size()); 46 47 map.Remove(id2); 48 EXPECT_TRUE(map.IsEmpty()); 49 EXPECT_EQ(0U, map.size()); 50 51 map.AddWithID(&obj1, 1); 52 map.AddWithID(&obj2, 2); 53 EXPECT_EQ(&obj1, map.Lookup(1)); 54 EXPECT_EQ(&obj2, map.Lookup(2)); 55 56 EXPECT_EQ(0, map.iteration_depth()); 57 } 58 59 TEST(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 73 EXPECT_EQ(1, map.iteration_depth()); 74 75 while (!iter.IsAtEnd()) { 76 map.Remove(iter.GetCurrentKey()); 77 iter.Advance(); 78 } 79 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()); 84 } 85 86 EXPECT_TRUE(map.IsEmpty()); 87 EXPECT_EQ(0U, map.size()); 88 89 EXPECT_EQ(0, map.iteration_depth()); 90 } 91 92 TEST(IDMapTest, IteratorRemainsValidWhenRemovingOtherElements) { 93 IDMap<TestObject> map; 94 95 const int kCount = 5; 96 TestObject obj[kCount]; 97 int32 ids[kCount]; 98 99 for (int i = 0; i < kCount; i++) 100 ids[i] = map.Add(&obj[i]); 101 102 int counter = 0; 103 for (IDMap<TestObject>::const_iterator iter(&map); 104 !iter.IsAtEnd(); iter.Advance()) { 105 EXPECT_EQ(1, map.iteration_depth()); 106 107 switch (counter) { 108 case 0: 109 EXPECT_EQ(ids[0], iter.GetCurrentKey()); 110 EXPECT_EQ(&obj[0], iter.GetCurrentValue()); 111 map.Remove(ids[1]); 112 break; 113 case 1: 114 EXPECT_EQ(ids[2], iter.GetCurrentKey()); 115 EXPECT_EQ(&obj[2], iter.GetCurrentValue()); 116 map.Remove(ids[3]); 117 break; 118 case 2: 119 EXPECT_EQ(ids[4], iter.GetCurrentKey()); 120 EXPECT_EQ(&obj[4], iter.GetCurrentValue()); 121 map.Remove(ids[0]); 122 break; 123 default: 124 FAIL() << "should not have that many elements"; 125 break; 126 } 127 128 counter++; 129 } 130 131 EXPECT_EQ(0, map.iteration_depth()); 132 } 133 134 TEST(IDMapTest, CopyIterator) { 135 IDMap<TestObject> map; 136 137 TestObject obj1; 138 TestObject obj2; 139 TestObject obj3; 140 141 map.Add(&obj1); 142 map.Add(&obj2); 143 map.Add(&obj3); 144 145 EXPECT_EQ(0, map.iteration_depth()); 146 147 { 148 IDMap<TestObject>::const_iterator iter1(&map); 149 EXPECT_EQ(1, map.iteration_depth()); 150 151 // Make sure that copying the iterator correctly increments 152 // map's iteration depth. 153 IDMap<TestObject>::const_iterator iter2(iter1); 154 EXPECT_EQ(2, map.iteration_depth()); 155 } 156 157 // Make sure after destroying all iterators the map's iteration depth 158 // returns to initial state. 159 EXPECT_EQ(0, map.iteration_depth()); 160 } 161 162 TEST(IDMapTest, AssignIterator) { 163 IDMap<TestObject> map; 164 165 TestObject obj1; 166 TestObject obj2; 167 TestObject obj3; 168 169 map.Add(&obj1); 170 map.Add(&obj2); 171 map.Add(&obj3); 172 173 EXPECT_EQ(0, map.iteration_depth()); 174 175 { 176 IDMap<TestObject>::const_iterator iter1(&map); 177 EXPECT_EQ(1, map.iteration_depth()); 178 179 IDMap<TestObject>::const_iterator iter2(&map); 180 EXPECT_EQ(2, map.iteration_depth()); 181 182 // Make sure that assigning the iterator correctly updates 183 // map's iteration depth (-1 for destruction, +1 for assignment). 184 EXPECT_EQ(2, map.iteration_depth()); 185 } 186 187 // Make sure after destroying all iterators the map's iteration depth 188 // returns to initial state. 189 EXPECT_EQ(0, map.iteration_depth()); 190 } 191 192 TEST(IDMapTest, IteratorRemainsValidWhenClearing) { 193 IDMap<TestObject> map; 194 195 const int kCount = 5; 196 TestObject obj[kCount]; 197 int32 ids[kCount]; 198 199 for (int i = 0; i < kCount; i++) 200 ids[i] = map.Add(&obj[i]); 201 202 int counter = 0; 203 for (IDMap<TestObject>::const_iterator iter(&map); 204 !iter.IsAtEnd(); iter.Advance()) { 205 switch (counter) { 206 case 0: 207 EXPECT_EQ(ids[0], iter.GetCurrentKey()); 208 EXPECT_EQ(&obj[0], iter.GetCurrentValue()); 209 break; 210 case 1: 211 EXPECT_EQ(ids[1], iter.GetCurrentKey()); 212 EXPECT_EQ(&obj[1], iter.GetCurrentValue()); 213 map.Clear(); 214 EXPECT_TRUE(map.IsEmpty()); 215 EXPECT_EQ(0U, map.size()); 216 break; 217 default: 218 FAIL() << "should not have that many elements"; 219 break; 220 } 221 counter++; 222 } 223 224 EXPECT_TRUE(map.IsEmpty()); 225 EXPECT_EQ(0U, map.size()); 226 } 227 228 TEST(IDMapTest, OwningPointersDeletesThemOnRemove) { 229 const int kCount = 3; 230 231 int external_del_count = 0; 232 DestructorCounter* external_obj[kCount]; 233 int map_external_ids[kCount]; 234 235 int owned_del_count = 0; 236 DestructorCounter* owned_obj[kCount]; 237 int map_owned_ids[kCount]; 238 239 IDMap<DestructorCounter> map_external; 240 IDMap<DestructorCounter, IDMapOwnPointer> map_owned; 241 242 for (int i = 0; i < kCount; ++i) { 243 external_obj[i] = new DestructorCounter(&external_del_count); 244 map_external_ids[i] = map_external.Add(external_obj[i]); 245 246 owned_obj[i] = new DestructorCounter(&owned_del_count); 247 map_owned_ids[i] = map_owned.Add(owned_obj[i]); 248 } 249 250 for (int i = 0; i < kCount; ++i) { 251 EXPECT_EQ(external_del_count, 0); 252 EXPECT_EQ(owned_del_count, i); 253 254 map_external.Remove(map_external_ids[i]); 255 map_owned.Remove(map_owned_ids[i]); 256 } 257 258 for (int i = 0; i < kCount; ++i) { 259 delete external_obj[i]; 260 } 261 262 EXPECT_EQ(external_del_count, kCount); 263 EXPECT_EQ(owned_del_count, kCount); 264 } 265 266 TEST(IDMapTest, OwningPointersDeletesThemOnClear) { 267 const int kCount = 3; 268 269 int external_del_count = 0; 270 DestructorCounter* external_obj[kCount]; 271 272 int owned_del_count = 0; 273 DestructorCounter* owned_obj[kCount]; 274 275 IDMap<DestructorCounter> map_external; 276 IDMap<DestructorCounter, IDMapOwnPointer> map_owned; 277 278 for (int i = 0; i < kCount; ++i) { 279 external_obj[i] = new DestructorCounter(&external_del_count); 280 map_external.Add(external_obj[i]); 281 282 owned_obj[i] = new DestructorCounter(&owned_del_count); 283 map_owned.Add(owned_obj[i]); 284 } 285 286 EXPECT_EQ(external_del_count, 0); 287 EXPECT_EQ(owned_del_count, 0); 288 289 map_external.Clear(); 290 map_owned.Clear(); 291 292 EXPECT_EQ(external_del_count, 0); 293 EXPECT_EQ(owned_del_count, kCount); 294 295 for (int i = 0; i < kCount; ++i) { 296 delete external_obj[i]; 297 } 298 299 EXPECT_EQ(external_del_count, kCount); 300 EXPECT_EQ(owned_del_count, kCount); 301 } 302 303 TEST(IDMapTest, OwningPointersDeletesThemOnDestruct) { 304 const int kCount = 3; 305 306 int external_del_count = 0; 307 DestructorCounter* external_obj[kCount]; 308 309 int owned_del_count = 0; 310 DestructorCounter* owned_obj[kCount]; 311 312 { 313 IDMap<DestructorCounter> map_external; 314 IDMap<DestructorCounter, IDMapOwnPointer> map_owned; 315 316 for (int i = 0; i < kCount; ++i) { 317 external_obj[i] = new DestructorCounter(&external_del_count); 318 map_external.Add(external_obj[i]); 319 320 owned_obj[i] = new DestructorCounter(&owned_del_count); 321 map_owned.Add(owned_obj[i]); 322 } 323 } 324 325 EXPECT_EQ(external_del_count, 0); 326 327 for (int i = 0; i < kCount; ++i) { 328 delete external_obj[i]; 329 } 330 331 EXPECT_EQ(external_del_count, kCount); 332 EXPECT_EQ(owned_del_count, kCount); 333 } 334 335 } // namespace 336