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
12namespace {
13
14// The LifeCycleObject notifies its Observer upon construction & destruction.
15class 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:
23    virtual ~Observer() {}
24  };
25
26  ~LifeCycleObject() {
27    observer_->OnLifeCycleDestroy(this);
28  }
29
30 private:
31  friend class LifeCycleWatcher;
32
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.
45enum 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.
62class LifeCycleWatcher : public LifeCycleObject::Observer {
63 public:
64  LifeCycleWatcher() : life_cycle_state_(LC_INITIAL) {}
65  virtual ~LifeCycleWatcher() {}
66
67  // Assert INITIAL -> CONSTRUCTED and no LifeCycleObject associated with this
68  // LifeCycleWatcher.
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.
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
86  LifeCycleState life_cycle_state() const { return life_cycle_state_; }
87
88  // Factory method for creating a new LifeCycleObject tied to this
89  // LifeCycleWatcher.
90  LifeCycleObject* NewLifeCycleObject() {
91    return new LifeCycleObject(this);
92  }
93
94  // Returns true iff |object| is the same object that this watcher is tracking.
95  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
106TEST(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
115TEST(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
127TEST(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
139TEST(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
151TEST(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
178TEST(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
196TEST(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
208TEST(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
227TEST(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
247class DeleteCounter {
248 public:
249  explicit DeleteCounter(int* deletes)
250      : deletes_(deletes) {
251  }
252
253  ~DeleteCounter() {
254    (*deletes_)++;
255  }
256
257  void VoidMethod0() {}
258
259 private:
260  int* const deletes_;
261
262  DISALLOW_COPY_AND_ASSIGN(DeleteCounter);
263};
264
265template <typename T>
266ScopedVector<T> PassThru(ScopedVector<T> scoper) {
267  return scoper.Pass();
268}
269
270TEST(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
284TEST(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