1 // Copyright (c) 2012 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/memory/scoped_vector.h" 6 7 #include "base/bind.h" 8 #include "base/callback.h" 9 #include "base/memory/scoped_ptr.h" 10 #include "testing/gtest/include/gtest/gtest.h" 11 12 namespace { 13 14 // The LifeCycleObject notifies its Observer upon construction & destruction. 15 class LifeCycleObject { 16 public: 17 class Observer { 18 public: 19 virtual void OnLifeCycleConstruct(LifeCycleObject* o) = 0; 20 virtual void OnLifeCycleDestroy(LifeCycleObject* o) = 0; 21 22 protected: 23 virtual ~Observer() {} 24 }; 25 26 ~LifeCycleObject() { 27 observer_->OnLifeCycleDestroy(this); 28 } 29 30 private: 31 friend class LifeCycleWatcher; 32 33 explicit LifeCycleObject(Observer* observer) 34 : observer_(observer) { 35 observer_->OnLifeCycleConstruct(this); 36 } 37 38 Observer* observer_; 39 40 DISALLOW_COPY_AND_ASSIGN(LifeCycleObject); 41 }; 42 43 // The life cycle states we care about for the purposes of testing ScopedVector 44 // against objects. 45 enum LifeCycleState { 46 LC_INITIAL, 47 LC_CONSTRUCTED, 48 LC_DESTROYED, 49 }; 50 51 // Because we wish to watch the life cycle of an object being constructed and 52 // destroyed, and further wish to test expectations against the state of that 53 // object, we cannot save state in that object itself. Instead, we use this 54 // pairing of the watcher, which observes the object and notifies of 55 // construction & destruction. Since we also may be testing assumptions about 56 // things not getting freed, this class also acts like a scoping object and 57 // deletes the |constructed_life_cycle_object_|, if any when the 58 // LifeCycleWatcher is destroyed. To keep this simple, the only expected state 59 // changes are: 60 // INITIAL -> CONSTRUCTED -> DESTROYED. 61 // Anything more complicated than that should start another test. 62 class LifeCycleWatcher : public LifeCycleObject::Observer { 63 public: 64 LifeCycleWatcher() : life_cycle_state_(LC_INITIAL) {} 65 virtual ~LifeCycleWatcher() {} 66 67 // Assert INITIAL -> CONSTRUCTED and no LifeCycleObject associated with this 68 // LifeCycleWatcher. 69 virtual void OnLifeCycleConstruct(LifeCycleObject* object) OVERRIDE { 70 ASSERT_EQ(LC_INITIAL, life_cycle_state_); 71 ASSERT_EQ(NULL, constructed_life_cycle_object_.get()); 72 life_cycle_state_ = LC_CONSTRUCTED; 73 constructed_life_cycle_object_.reset(object); 74 } 75 76 // Assert CONSTRUCTED -> DESTROYED and the |object| being destroyed is the 77 // same one we saw constructed. 78 virtual void OnLifeCycleDestroy(LifeCycleObject* object) OVERRIDE { 79 ASSERT_EQ(LC_CONSTRUCTED, life_cycle_state_); 80 LifeCycleObject* constructed_life_cycle_object = 81 constructed_life_cycle_object_.release(); 82 ASSERT_EQ(constructed_life_cycle_object, object); 83 life_cycle_state_ = LC_DESTROYED; 84 } 85 86 LifeCycleState life_cycle_state() const { return life_cycle_state_; } 87 88 // Factory method for creating a new LifeCycleObject tied to this 89 // LifeCycleWatcher. 90 LifeCycleObject* NewLifeCycleObject() { 91 return new LifeCycleObject(this); 92 } 93 94 // Returns true iff |object| is the same object that this watcher is tracking. 95 bool IsWatching(LifeCycleObject* object) const { 96 return object == constructed_life_cycle_object_.get(); 97 } 98 99 private: 100 LifeCycleState life_cycle_state_; 101 scoped_ptr<LifeCycleObject> constructed_life_cycle_object_; 102 103 DISALLOW_COPY_AND_ASSIGN(LifeCycleWatcher); 104 }; 105 106 TEST(ScopedVectorTest, LifeCycleWatcher) { 107 LifeCycleWatcher watcher; 108 EXPECT_EQ(LC_INITIAL, watcher.life_cycle_state()); 109 LifeCycleObject* object = watcher.NewLifeCycleObject(); 110 EXPECT_EQ(LC_CONSTRUCTED, watcher.life_cycle_state()); 111 delete object; 112 EXPECT_EQ(LC_DESTROYED, watcher.life_cycle_state()); 113 } 114 115 TEST(ScopedVectorTest, PopBack) { 116 LifeCycleWatcher watcher; 117 EXPECT_EQ(LC_INITIAL, watcher.life_cycle_state()); 118 ScopedVector<LifeCycleObject> scoped_vector; 119 scoped_vector.push_back(watcher.NewLifeCycleObject()); 120 EXPECT_EQ(LC_CONSTRUCTED, watcher.life_cycle_state()); 121 EXPECT_TRUE(watcher.IsWatching(scoped_vector.back())); 122 scoped_vector.pop_back(); 123 EXPECT_EQ(LC_DESTROYED, watcher.life_cycle_state()); 124 EXPECT_TRUE(scoped_vector.empty()); 125 } 126 127 TEST(ScopedVectorTest, Clear) { 128 LifeCycleWatcher watcher; 129 EXPECT_EQ(LC_INITIAL, watcher.life_cycle_state()); 130 ScopedVector<LifeCycleObject> scoped_vector; 131 scoped_vector.push_back(watcher.NewLifeCycleObject()); 132 EXPECT_EQ(LC_CONSTRUCTED, watcher.life_cycle_state()); 133 EXPECT_TRUE(watcher.IsWatching(scoped_vector.back())); 134 scoped_vector.clear(); 135 EXPECT_EQ(LC_DESTROYED, watcher.life_cycle_state()); 136 EXPECT_TRUE(scoped_vector.empty()); 137 } 138 139 TEST(ScopedVectorTest, WeakClear) { 140 LifeCycleWatcher watcher; 141 EXPECT_EQ(LC_INITIAL, watcher.life_cycle_state()); 142 ScopedVector<LifeCycleObject> scoped_vector; 143 scoped_vector.push_back(watcher.NewLifeCycleObject()); 144 EXPECT_EQ(LC_CONSTRUCTED, watcher.life_cycle_state()); 145 EXPECT_TRUE(watcher.IsWatching(scoped_vector.back())); 146 scoped_vector.weak_clear(); 147 EXPECT_EQ(LC_CONSTRUCTED, watcher.life_cycle_state()); 148 EXPECT_TRUE(scoped_vector.empty()); 149 } 150 151 TEST(ScopedVectorTest, ResizeShrink) { 152 LifeCycleWatcher first_watcher; 153 EXPECT_EQ(LC_INITIAL, first_watcher.life_cycle_state()); 154 LifeCycleWatcher second_watcher; 155 EXPECT_EQ(LC_INITIAL, second_watcher.life_cycle_state()); 156 ScopedVector<LifeCycleObject> scoped_vector; 157 158 scoped_vector.push_back(first_watcher.NewLifeCycleObject()); 159 EXPECT_EQ(LC_CONSTRUCTED, first_watcher.life_cycle_state()); 160 EXPECT_EQ(LC_INITIAL, second_watcher.life_cycle_state()); 161 EXPECT_TRUE(first_watcher.IsWatching(scoped_vector[0])); 162 EXPECT_FALSE(second_watcher.IsWatching(scoped_vector[0])); 163 164 scoped_vector.push_back(second_watcher.NewLifeCycleObject()); 165 EXPECT_EQ(LC_CONSTRUCTED, first_watcher.life_cycle_state()); 166 EXPECT_EQ(LC_CONSTRUCTED, second_watcher.life_cycle_state()); 167 EXPECT_FALSE(first_watcher.IsWatching(scoped_vector[1])); 168 EXPECT_TRUE(second_watcher.IsWatching(scoped_vector[1])); 169 170 // Test that shrinking a vector deletes elements in the disappearing range. 171 scoped_vector.resize(1); 172 EXPECT_EQ(LC_CONSTRUCTED, first_watcher.life_cycle_state()); 173 EXPECT_EQ(LC_DESTROYED, second_watcher.life_cycle_state()); 174 EXPECT_EQ(1u, scoped_vector.size()); 175 EXPECT_TRUE(first_watcher.IsWatching(scoped_vector[0])); 176 } 177 178 TEST(ScopedVectorTest, ResizeGrow) { 179 LifeCycleWatcher watcher; 180 EXPECT_EQ(LC_INITIAL, watcher.life_cycle_state()); 181 ScopedVector<LifeCycleObject> scoped_vector; 182 scoped_vector.push_back(watcher.NewLifeCycleObject()); 183 EXPECT_EQ(LC_CONSTRUCTED, watcher.life_cycle_state()); 184 EXPECT_TRUE(watcher.IsWatching(scoped_vector.back())); 185 186 scoped_vector.resize(5); 187 EXPECT_EQ(LC_CONSTRUCTED, watcher.life_cycle_state()); 188 ASSERT_EQ(5u, scoped_vector.size()); 189 EXPECT_TRUE(watcher.IsWatching(scoped_vector[0])); 190 EXPECT_FALSE(watcher.IsWatching(scoped_vector[1])); 191 EXPECT_FALSE(watcher.IsWatching(scoped_vector[2])); 192 EXPECT_FALSE(watcher.IsWatching(scoped_vector[3])); 193 EXPECT_FALSE(watcher.IsWatching(scoped_vector[4])); 194 } 195 196 TEST(ScopedVectorTest, Scope) { 197 LifeCycleWatcher watcher; 198 EXPECT_EQ(LC_INITIAL, watcher.life_cycle_state()); 199 { 200 ScopedVector<LifeCycleObject> scoped_vector; 201 scoped_vector.push_back(watcher.NewLifeCycleObject()); 202 EXPECT_EQ(LC_CONSTRUCTED, watcher.life_cycle_state()); 203 EXPECT_TRUE(watcher.IsWatching(scoped_vector.back())); 204 } 205 EXPECT_EQ(LC_DESTROYED, watcher.life_cycle_state()); 206 } 207 208 TEST(ScopedVectorTest, MoveConstruct) { 209 LifeCycleWatcher watcher; 210 EXPECT_EQ(LC_INITIAL, watcher.life_cycle_state()); 211 { 212 ScopedVector<LifeCycleObject> scoped_vector; 213 scoped_vector.push_back(watcher.NewLifeCycleObject()); 214 EXPECT_FALSE(scoped_vector.empty()); 215 EXPECT_TRUE(watcher.IsWatching(scoped_vector.back())); 216 217 ScopedVector<LifeCycleObject> scoped_vector_copy(scoped_vector.Pass()); 218 EXPECT_TRUE(scoped_vector.empty()); 219 EXPECT_FALSE(scoped_vector_copy.empty()); 220 EXPECT_TRUE(watcher.IsWatching(scoped_vector_copy.back())); 221 222 EXPECT_EQ(LC_CONSTRUCTED, watcher.life_cycle_state()); 223 } 224 EXPECT_EQ(LC_DESTROYED, watcher.life_cycle_state()); 225 } 226 227 TEST(ScopedVectorTest, MoveAssign) { 228 LifeCycleWatcher watcher; 229 EXPECT_EQ(LC_INITIAL, watcher.life_cycle_state()); 230 { 231 ScopedVector<LifeCycleObject> scoped_vector; 232 scoped_vector.push_back(watcher.NewLifeCycleObject()); 233 ScopedVector<LifeCycleObject> scoped_vector_assign; 234 EXPECT_FALSE(scoped_vector.empty()); 235 EXPECT_TRUE(watcher.IsWatching(scoped_vector.back())); 236 237 scoped_vector_assign = scoped_vector.Pass(); 238 EXPECT_TRUE(scoped_vector.empty()); 239 EXPECT_FALSE(scoped_vector_assign.empty()); 240 EXPECT_TRUE(watcher.IsWatching(scoped_vector_assign.back())); 241 242 EXPECT_EQ(LC_CONSTRUCTED, watcher.life_cycle_state()); 243 } 244 EXPECT_EQ(LC_DESTROYED, watcher.life_cycle_state()); 245 } 246 247 class DeleteCounter { 248 public: 249 explicit DeleteCounter(int* deletes) 250 : deletes_(deletes) { 251 } 252 253 ~DeleteCounter() { 254 (*deletes_)++; 255 } 256 257 void VoidMethod0() {} 258 259 private: 260 int* const deletes_; 261 262 DISALLOW_COPY_AND_ASSIGN(DeleteCounter); 263 }; 264 265 template <typename T> 266 ScopedVector<T> PassThru(ScopedVector<T> scoper) { 267 return scoper.Pass(); 268 } 269 270 TEST(ScopedVectorTest, Passed) { 271 int deletes = 0; 272 ScopedVector<DeleteCounter> deleter_vector; 273 deleter_vector.push_back(new DeleteCounter(&deletes)); 274 EXPECT_EQ(0, deletes); 275 base::Callback<ScopedVector<DeleteCounter>(void)> callback = 276 base::Bind(&PassThru<DeleteCounter>, base::Passed(&deleter_vector)); 277 EXPECT_EQ(0, deletes); 278 ScopedVector<DeleteCounter> result = callback.Run(); 279 EXPECT_EQ(0, deletes); 280 result.clear(); 281 EXPECT_EQ(1, deletes); 282 }; 283 284 TEST(ScopedVectorTest, InsertRange) { 285 LifeCycleWatcher watchers[5]; 286 287 std::vector<LifeCycleObject*> vec; 288 for(LifeCycleWatcher* it = watchers; it != watchers + arraysize(watchers); 289 ++it) { 290 EXPECT_EQ(LC_INITIAL, it->life_cycle_state()); 291 vec.push_back(it->NewLifeCycleObject()); 292 EXPECT_EQ(LC_CONSTRUCTED, it->life_cycle_state()); 293 } 294 // Start scope for ScopedVector. 295 { 296 ScopedVector<LifeCycleObject> scoped_vector; 297 scoped_vector.insert(scoped_vector.end(), vec.begin() + 1, vec.begin() + 3); 298 for(LifeCycleWatcher* it = watchers; it != watchers + arraysize(watchers); 299 ++it) 300 EXPECT_EQ(LC_CONSTRUCTED, it->life_cycle_state()); 301 } 302 for(LifeCycleWatcher* it = watchers; it != watchers + 1; ++it) 303 EXPECT_EQ(LC_CONSTRUCTED, it->life_cycle_state()); 304 for(LifeCycleWatcher* it = watchers + 1; it != watchers + 3; ++it) 305 EXPECT_EQ(LC_DESTROYED, it->life_cycle_state()); 306 for(LifeCycleWatcher* it = watchers + 3; it != watchers + arraysize(watchers); 307 ++it) 308 EXPECT_EQ(LC_CONSTRUCTED, it->life_cycle_state()); 309 } 310 311 } // namespace 312