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 <memory>
      8 #include <utility>
      9 
     10 #include "base/bind.h"
     11 #include "base/callback.h"
     12 #include "base/macros.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:
     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.
     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:
     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   std::unique_ptr<LifeCycleObject> constructed_life_cycle_object_;
    116 
    117   DISALLOW_COPY_AND_ASSIGN(LifeCycleWatcher);
    118 };
    119 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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:
    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 
    279 template <typename T>
    280 ScopedVector<T> PassThru(ScopedVector<T> scoper) {
    281   return scoper;
    282 }
    283 
    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 
    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(unique_ptr).
    326 TEST(ScopedVectorTest, PushBackScopedPtr) {
    327   int delete_counter = 0;
    328   std::unique_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