• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <utility>
8 
9 #include "base/bind.h"
10 #include "base/callback.h"
11 #include "base/macros.h"
12 #include "base/memory/scoped_ptr.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:
~Observer()26     virtual ~Observer() {}
27   };
28 
~LifeCycleObject()29   ~LifeCycleObject() {
30     if (observer_)
31       observer_->OnLifeCycleDestroy(this);
32   }
33 
34  private:
35   friend class LifeCycleWatcher;
36 
LifeCycleObject(Observer * observer)37   explicit LifeCycleObject(Observer* observer)
38       : observer_(observer) {
39     observer_->OnLifeCycleConstruct(this);
40   }
41 
DisconnectObserver()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:
LifeCycleWatcher()72   LifeCycleWatcher() : life_cycle_state_(LC_INITIAL) {}
~LifeCycleWatcher()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.
OnLifeCycleConstruct(LifeCycleObject * object)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.
OnLifeCycleDestroy(LifeCycleObject * object)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 
life_cycle_state() const100   LifeCycleState life_cycle_state() const { return life_cycle_state_; }
101 
102   // Factory method for creating a new LifeCycleObject tied to this
103   // LifeCycleWatcher.
NewLifeCycleObject()104   LifeCycleObject* NewLifeCycleObject() {
105     return new LifeCycleObject(this);
106   }
107 
108   // Returns true iff |object| is the same object that this watcher is tracking.
IsWatching(LifeCycleObject * object) const109   bool IsWatching(LifeCycleObject* object) const {
110     return object == constructed_life_cycle_object_.get();
111   }
112 
113  private:
114   LifeCycleState life_cycle_state_;
115   scoped_ptr<LifeCycleObject> constructed_life_cycle_object_;
116 
117   DISALLOW_COPY_AND_ASSIGN(LifeCycleWatcher);
118 };
119 
TEST(ScopedVectorTest,LifeCycleWatcher)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 
TEST(ScopedVectorTest,PopBack)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 
TEST(ScopedVectorTest,Clear)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 
TEST(ScopedVectorTest,WeakClear)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 
TEST(ScopedVectorTest,ResizeShrink)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 
TEST(ScopedVectorTest,ResizeGrow)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 
TEST(ScopedVectorTest,Scope)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 
TEST(ScopedVectorTest,MoveConstruct)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 
TEST(ScopedVectorTest,MoveAssign)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:
DeleteCounter(int * deletes)263   explicit DeleteCounter(int* deletes)
264       : deletes_(deletes) {
265   }
266 
~DeleteCounter()267   ~DeleteCounter() {
268     (*deletes_)++;
269   }
270 
VoidMethod0()271   void VoidMethod0() {}
272 
273  private:
274   int* const deletes_;
275 
276   DISALLOW_COPY_AND_ASSIGN(DeleteCounter);
277 };
278 
279 template <typename T>
PassThru(ScopedVector<T> scoper)280 ScopedVector<T> PassThru(ScopedVector<T> scoper) {
281   return scoper;
282 }
283 
TEST(ScopedVectorTest,Passed)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 
TEST(ScopedVectorTest,InsertRange)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).
TEST(ScopedVectorTest,PushBackScopedPtr)326 TEST(ScopedVectorTest, PushBackScopedPtr) {
327   int delete_counter = 0;
328   scoped_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