• 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 "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:
~Observer()23     virtual ~Observer() {}
24   };
25 
~LifeCycleObject()26   ~LifeCycleObject() {
27     observer_->OnLifeCycleDestroy(this);
28   }
29 
30  private:
31   friend class LifeCycleWatcher;
32 
LifeCycleObject(Observer * observer)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:
LifeCycleWatcher()64   LifeCycleWatcher() : life_cycle_state_(LC_INITIAL) {}
~LifeCycleWatcher()65   virtual ~LifeCycleWatcher() {}
66 
67   // Assert INITIAL -> CONSTRUCTED and no LifeCycleObject associated with this
68   // LifeCycleWatcher.
OnLifeCycleConstruct(LifeCycleObject * object)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.
OnLifeCycleDestroy(LifeCycleObject * object)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 
life_cycle_state() const86   LifeCycleState life_cycle_state() const { return life_cycle_state_; }
87 
88   // Factory method for creating a new LifeCycleObject tied to this
89   // LifeCycleWatcher.
NewLifeCycleObject()90   LifeCycleObject* NewLifeCycleObject() {
91     return new LifeCycleObject(this);
92   }
93 
94   // Returns true iff |object| is the same object that this watcher is tracking.
IsWatching(LifeCycleObject * object) const95   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 
TEST(ScopedVectorTest,LifeCycleWatcher)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 
TEST(ScopedVectorTest,PopBack)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 
TEST(ScopedVectorTest,Clear)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 
TEST(ScopedVectorTest,WeakClear)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 
TEST(ScopedVectorTest,ResizeShrink)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 
TEST(ScopedVectorTest,ResizeGrow)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 
TEST(ScopedVectorTest,Scope)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 
TEST(ScopedVectorTest,MoveConstruct)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 
TEST(ScopedVectorTest,MoveAssign)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:
DeleteCounter(int * deletes)249   explicit DeleteCounter(int* deletes)
250       : deletes_(deletes) {
251   }
252 
~DeleteCounter()253   ~DeleteCounter() {
254     (*deletes_)++;
255   }
256 
VoidMethod0()257   void VoidMethod0() {}
258 
259  private:
260   int* const deletes_;
261 
262   DISALLOW_COPY_AND_ASSIGN(DeleteCounter);
263 };
264 
265 template <typename T>
PassThru(ScopedVector<T> scoper)266 ScopedVector<T> PassThru(ScopedVector<T> scoper) {
267   return scoper.Pass();
268 }
269 
TEST(ScopedVectorTest,Passed)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 
TEST(ScopedVectorTest,InsertRange)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