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