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