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