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: 19 explicit DestructorCounter(int* counter) : counter_(counter) {} 20 ~DestructorCounter() { ++(*counter_); } 21 private: 22 int* counter_; 23 }; 24 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 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 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 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 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