Home | History | Annotate | Download | only in memory
      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:
     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.
     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:
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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:
    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 
    265 template <typename T>
    266 ScopedVector<T> PassThru(ScopedVector<T> scoper) {
    267   return scoper.Pass();
    268 }
    269 
    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 
    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