scoped_vector_unittest.cc revision ddb351dbec246cf1fab5ec20d2d5520909041de1
1// Copyright (c) 2011 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_ptr.h"
6#include "base/memory/scoped_vector.h"
7#include "testing/gtest/include/gtest/gtest.h"
8
9namespace {
10
11// The LifeCycleObject notifies its Observer upon construction & destruction.
12class LifeCycleObject {
13 public:
14  class Observer {
15   public:
16    virtual void OnLifeCycleConstruct(LifeCycleObject* o) = 0;
17    virtual void OnLifeCycleDestroy(LifeCycleObject* o) = 0;
18
19   protected:
20    virtual ~Observer() {}
21  };
22
23  explicit LifeCycleObject(Observer* observer)
24      : observer_(observer) {
25    observer_->OnLifeCycleConstruct(this);
26  }
27
28  ~LifeCycleObject() {
29    observer_->OnLifeCycleDestroy(this);
30  }
31
32 private:
33  Observer* observer_;
34
35  DISALLOW_COPY_AND_ASSIGN(LifeCycleObject);
36};
37
38// The life cycle states we care about for the purposes of testing ScopedVector
39// against objects.
40enum LifeCycleState {
41  LC_INITIAL,
42  LC_CONSTRUCTED,
43  LC_DESTROYED,
44};
45
46// Because we wish to watch the life cycle of an object being constructed and
47// destroyed, and further wish to test expectations against the state of that
48// object, we cannot save state in that object itself. Instead, we use this
49// pairing of the watcher, which observes the object and notifies of
50// construction & destruction. Since we also may be testing assumptions about
51// things not getting freed, this class also acts like a scoping object and
52// deletes the |constructed_life_cycle_object_|, if any when the
53// LifeCycleWatcher is destroyed. To keep this simple, the only expected state
54// changes are:
55//   INITIAL -> CONSTRUCTED -> DESTROYED.
56// Anything more complicated than that should start another test.
57class LifeCycleWatcher : public LifeCycleObject::Observer {
58 public:
59  LifeCycleWatcher()
60      : life_cycle_state_(LC_INITIAL),
61        constructed_life_cycle_object_(NULL) {}
62  ~LifeCycleWatcher() {
63  }
64
65  // Assert INITIAL -> CONSTRUCTED and no LifeCycleObject associated with this
66  // LifeCycleWatcher.
67  virtual void OnLifeCycleConstruct(LifeCycleObject* object) {
68    ASSERT_EQ(LC_INITIAL, life_cycle_state_);
69    ASSERT_EQ(NULL, constructed_life_cycle_object_.get());
70    life_cycle_state_ = LC_CONSTRUCTED;
71    constructed_life_cycle_object_.reset(object);
72  }
73
74  // Assert CONSTRUCTED -> DESTROYED and the |object| being destroyed is the
75  // same one we saw constructed.
76  virtual void OnLifeCycleDestroy(LifeCycleObject* object) {
77    ASSERT_EQ(LC_CONSTRUCTED, life_cycle_state_);
78    LifeCycleObject* constructed_life_cycle_object =
79        constructed_life_cycle_object_.release();
80    ASSERT_EQ(constructed_life_cycle_object, object);
81    life_cycle_state_ = LC_DESTROYED;
82  }
83
84  LifeCycleState life_cycle_state() const { return life_cycle_state_; }
85
86  // Factory method for creating a new LifeCycleObject tied to this
87  // LifeCycleWatcher.
88  LifeCycleObject* NewLifeCycleObject() {
89    return new LifeCycleObject(this);
90  }
91
92 private:
93  LifeCycleState life_cycle_state_;
94  scoped_ptr<LifeCycleObject> constructed_life_cycle_object_;
95
96  DISALLOW_COPY_AND_ASSIGN(LifeCycleWatcher);
97};
98
99TEST(ScopedVectorTest, LifeCycleWatcher) {
100  LifeCycleWatcher watcher;
101  EXPECT_EQ(LC_INITIAL, watcher.life_cycle_state());
102  LifeCycleObject* object = watcher.NewLifeCycleObject();
103  EXPECT_EQ(LC_CONSTRUCTED, watcher.life_cycle_state());
104  delete object;
105  EXPECT_EQ(LC_DESTROYED, watcher.life_cycle_state());
106}
107
108TEST(ScopedVectorTest, Reset) {
109  LifeCycleWatcher watcher;
110  EXPECT_EQ(LC_INITIAL, watcher.life_cycle_state());
111  ScopedVector<LifeCycleObject> scoped_vector;
112  scoped_vector.push_back(watcher.NewLifeCycleObject());
113  EXPECT_EQ(LC_CONSTRUCTED, watcher.life_cycle_state());
114  scoped_vector.reset();
115  EXPECT_EQ(LC_DESTROYED, watcher.life_cycle_state());
116}
117
118TEST(ScopedVectorTest, Scope) {
119  LifeCycleWatcher watcher;
120  EXPECT_EQ(LC_INITIAL, watcher.life_cycle_state());
121  {
122    ScopedVector<LifeCycleObject> scoped_vector;
123    scoped_vector.push_back(watcher.NewLifeCycleObject());
124    EXPECT_EQ(LC_CONSTRUCTED, watcher.life_cycle_state());
125  }
126  EXPECT_EQ(LC_DESTROYED, watcher.life_cycle_state());
127}
128
129TEST(ScopedVectorTest, InsertRange) {
130  LifeCycleWatcher watchers[5];
131
132  std::vector<LifeCycleObject*> vec;
133  for(LifeCycleWatcher* it = watchers; it != watchers + arraysize(watchers);
134      ++it) {
135    EXPECT_EQ(LC_INITIAL, it->life_cycle_state());
136    vec.push_back(it->NewLifeCycleObject());
137    EXPECT_EQ(LC_CONSTRUCTED, it->life_cycle_state());
138  }
139  // Start scope for ScopedVector.
140  {
141    ScopedVector<LifeCycleObject> scoped_vector;
142    scoped_vector.insert(scoped_vector.end(), vec.begin() + 1, vec.begin() + 3);
143    for(LifeCycleWatcher* it = watchers; it != watchers + arraysize(watchers);
144        ++it)
145      EXPECT_EQ(LC_CONSTRUCTED, it->life_cycle_state());
146  }
147  for(LifeCycleWatcher* it = watchers; it != watchers + 1; ++it)
148    EXPECT_EQ(LC_CONSTRUCTED, it->life_cycle_state());
149  for(LifeCycleWatcher* it = watchers + 1; it != watchers + 3; ++it)
150    EXPECT_EQ(LC_DESTROYED, it->life_cycle_state());
151  for(LifeCycleWatcher* it = watchers + 3; it != watchers + arraysize(watchers);
152      ++it)
153    EXPECT_EQ(LC_CONSTRUCTED, it->life_cycle_state());
154}
155
156}  // namespace
157