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
15namespace {
16
17// The LifeCycleObject notifies its Observer upon construction & destruction.
18class 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.
53enum 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.
70class 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  scoped_ptr<LifeCycleObject> constructed_life_cycle_object_;
116
117  DISALLOW_COPY_AND_ASSIGN(LifeCycleWatcher);
118};
119
120TEST(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
129TEST(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
141TEST(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
153TEST(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
165TEST(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
192TEST(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
210TEST(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
222TEST(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
241TEST(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
261class 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
279template <typename T>
280ScopedVector<T> PassThru(ScopedVector<T> scoper) {
281  return scoper;
282}
283
284TEST(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
298TEST(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).
326TEST(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