Home | History | Annotate | Download | only in source
      1 /*
      2  *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 // Borrowed from Chromium's src/base/memory/scoped_vector_unittest.cc
     12 
     13 #include "webrtc/system_wrappers/include/scoped_vector.h"
     14 
     15 #include "testing/gtest/include/gtest/gtest.h"
     16 #include "webrtc/base/scoped_ptr.h"
     17 
     18 namespace webrtc {
     19 namespace {
     20 
     21 // The LifeCycleObject notifies its Observer upon construction & destruction.
     22 class LifeCycleObject {
     23  public:
     24   class Observer {
     25    public:
     26     virtual void OnLifeCycleConstruct(LifeCycleObject* o) = 0;
     27     virtual void OnLifeCycleDestroy(LifeCycleObject* o) = 0;
     28 
     29    protected:
     30     virtual ~Observer() {}
     31   };
     32 
     33   ~LifeCycleObject() {
     34     observer_->OnLifeCycleDestroy(this);
     35   }
     36 
     37  private:
     38   friend class LifeCycleWatcher;
     39 
     40   explicit LifeCycleObject(Observer* observer)
     41       : observer_(observer) {
     42     observer_->OnLifeCycleConstruct(this);
     43   }
     44 
     45   Observer* observer_;
     46 
     47   RTC_DISALLOW_COPY_AND_ASSIGN(LifeCycleObject);
     48 };
     49 
     50 // The life cycle states we care about for the purposes of testing ScopedVector
     51 // against objects.
     52 enum LifeCycleState {
     53   LC_INITIAL,
     54   LC_CONSTRUCTED,
     55   LC_DESTROYED,
     56 };
     57 
     58 // Because we wish to watch the life cycle of an object being constructed and
     59 // destroyed, and further wish to test expectations against the state of that
     60 // object, we cannot save state in that object itself. Instead, we use this
     61 // pairing of the watcher, which observes the object and notifies of
     62 // construction & destruction. Since we also may be testing assumptions about
     63 // things not getting freed, this class also acts like a scoping object and
     64 // deletes the |constructed_life_cycle_object_|, if any when the
     65 // LifeCycleWatcher is destroyed. To keep this simple, the only expected state
     66 // changes are:
     67 //   INITIAL -> CONSTRUCTED -> DESTROYED.
     68 // Anything more complicated than that should start another test.
     69 class LifeCycleWatcher : public LifeCycleObject::Observer {
     70  public:
     71   LifeCycleWatcher() : life_cycle_state_(LC_INITIAL) {}
     72   virtual ~LifeCycleWatcher() {}
     73 
     74   // Assert INITIAL -> CONSTRUCTED and no LifeCycleObject associated with this
     75   // LifeCycleWatcher.
     76   void OnLifeCycleConstruct(LifeCycleObject* object) override {
     77     ASSERT_EQ(LC_INITIAL, life_cycle_state_);
     78     ASSERT_EQ(NULL, constructed_life_cycle_object_.get());
     79     life_cycle_state_ = LC_CONSTRUCTED;
     80     constructed_life_cycle_object_.reset(object);
     81   }
     82 
     83   // Assert CONSTRUCTED -> DESTROYED and the |object| being destroyed is the
     84   // same one we saw constructed.
     85   void OnLifeCycleDestroy(LifeCycleObject* object) override {
     86     ASSERT_EQ(LC_CONSTRUCTED, life_cycle_state_);
     87     LifeCycleObject* constructed_life_cycle_object =
     88         constructed_life_cycle_object_.release();
     89     ASSERT_EQ(constructed_life_cycle_object, object);
     90     life_cycle_state_ = LC_DESTROYED;
     91   }
     92 
     93   LifeCycleState life_cycle_state() const { return life_cycle_state_; }
     94 
     95   // Factory method for creating a new LifeCycleObject tied to this
     96   // LifeCycleWatcher.
     97   LifeCycleObject* NewLifeCycleObject() {
     98     return new LifeCycleObject(this);
     99   }
    100 
    101   // Returns true iff |object| is the same object that this watcher is tracking.
    102   bool IsWatching(LifeCycleObject* object) const {
    103     return object == constructed_life_cycle_object_.get();
    104   }
    105 
    106  private:
    107   LifeCycleState life_cycle_state_;
    108   rtc::scoped_ptr<LifeCycleObject> constructed_life_cycle_object_;
    109 
    110   RTC_DISALLOW_COPY_AND_ASSIGN(LifeCycleWatcher);
    111 };
    112 
    113 TEST(ScopedVectorTest, LifeCycleWatcher) {
    114   LifeCycleWatcher watcher;
    115   EXPECT_EQ(LC_INITIAL, watcher.life_cycle_state());
    116   LifeCycleObject* object = watcher.NewLifeCycleObject();
    117   EXPECT_EQ(LC_CONSTRUCTED, watcher.life_cycle_state());
    118   delete object;
    119   EXPECT_EQ(LC_DESTROYED, watcher.life_cycle_state());
    120 }
    121 
    122 TEST(ScopedVectorTest, PopBack) {
    123   LifeCycleWatcher watcher;
    124   EXPECT_EQ(LC_INITIAL, watcher.life_cycle_state());
    125   ScopedVector<LifeCycleObject> scoped_vector;
    126   scoped_vector.push_back(watcher.NewLifeCycleObject());
    127   EXPECT_EQ(LC_CONSTRUCTED, watcher.life_cycle_state());
    128   EXPECT_TRUE(watcher.IsWatching(scoped_vector.back()));
    129   scoped_vector.pop_back();
    130   EXPECT_EQ(LC_DESTROYED, watcher.life_cycle_state());
    131   EXPECT_TRUE(scoped_vector.empty());
    132 }
    133 
    134 TEST(ScopedVectorTest, Clear) {
    135   LifeCycleWatcher watcher;
    136   EXPECT_EQ(LC_INITIAL, watcher.life_cycle_state());
    137   ScopedVector<LifeCycleObject> scoped_vector;
    138   scoped_vector.push_back(watcher.NewLifeCycleObject());
    139   EXPECT_EQ(LC_CONSTRUCTED, watcher.life_cycle_state());
    140   EXPECT_TRUE(watcher.IsWatching(scoped_vector.back()));
    141   scoped_vector.clear();
    142   EXPECT_EQ(LC_DESTROYED, watcher.life_cycle_state());
    143   EXPECT_TRUE(scoped_vector.empty());
    144 }
    145 
    146 TEST(ScopedVectorTest, WeakClear) {
    147   LifeCycleWatcher watcher;
    148   EXPECT_EQ(LC_INITIAL, watcher.life_cycle_state());
    149   ScopedVector<LifeCycleObject> scoped_vector;
    150   scoped_vector.push_back(watcher.NewLifeCycleObject());
    151   EXPECT_EQ(LC_CONSTRUCTED, watcher.life_cycle_state());
    152   EXPECT_TRUE(watcher.IsWatching(scoped_vector.back()));
    153   scoped_vector.weak_clear();
    154   EXPECT_EQ(LC_CONSTRUCTED, watcher.life_cycle_state());
    155   EXPECT_TRUE(scoped_vector.empty());
    156 }
    157 
    158 TEST(ScopedVectorTest, ResizeShrink) {
    159   LifeCycleWatcher first_watcher;
    160   EXPECT_EQ(LC_INITIAL, first_watcher.life_cycle_state());
    161   LifeCycleWatcher second_watcher;
    162   EXPECT_EQ(LC_INITIAL, second_watcher.life_cycle_state());
    163   ScopedVector<LifeCycleObject> scoped_vector;
    164 
    165   scoped_vector.push_back(first_watcher.NewLifeCycleObject());
    166   EXPECT_EQ(LC_CONSTRUCTED, first_watcher.life_cycle_state());
    167   EXPECT_EQ(LC_INITIAL, second_watcher.life_cycle_state());
    168   EXPECT_TRUE(first_watcher.IsWatching(scoped_vector[0]));
    169   EXPECT_FALSE(second_watcher.IsWatching(scoped_vector[0]));
    170 
    171   scoped_vector.push_back(second_watcher.NewLifeCycleObject());
    172   EXPECT_EQ(LC_CONSTRUCTED, first_watcher.life_cycle_state());
    173   EXPECT_EQ(LC_CONSTRUCTED, second_watcher.life_cycle_state());
    174   EXPECT_FALSE(first_watcher.IsWatching(scoped_vector[1]));
    175   EXPECT_TRUE(second_watcher.IsWatching(scoped_vector[1]));
    176 
    177   // Test that shrinking a vector deletes elements in the disappearing range.
    178   scoped_vector.resize(1);
    179   EXPECT_EQ(LC_CONSTRUCTED, first_watcher.life_cycle_state());
    180   EXPECT_EQ(LC_DESTROYED, second_watcher.life_cycle_state());
    181   EXPECT_EQ(1u, scoped_vector.size());
    182   EXPECT_TRUE(first_watcher.IsWatching(scoped_vector[0]));
    183 }
    184 
    185 TEST(ScopedVectorTest, ResizeGrow) {
    186   LifeCycleWatcher watcher;
    187   EXPECT_EQ(LC_INITIAL, watcher.life_cycle_state());
    188   ScopedVector<LifeCycleObject> scoped_vector;
    189   scoped_vector.push_back(watcher.NewLifeCycleObject());
    190   EXPECT_EQ(LC_CONSTRUCTED, watcher.life_cycle_state());
    191   EXPECT_TRUE(watcher.IsWatching(scoped_vector.back()));
    192 
    193   scoped_vector.resize(5);
    194   EXPECT_EQ(LC_CONSTRUCTED, watcher.life_cycle_state());
    195   ASSERT_EQ(5u, scoped_vector.size());
    196   EXPECT_TRUE(watcher.IsWatching(scoped_vector[0]));
    197   EXPECT_FALSE(watcher.IsWatching(scoped_vector[1]));
    198   EXPECT_FALSE(watcher.IsWatching(scoped_vector[2]));
    199   EXPECT_FALSE(watcher.IsWatching(scoped_vector[3]));
    200   EXPECT_FALSE(watcher.IsWatching(scoped_vector[4]));
    201 }
    202 
    203 TEST(ScopedVectorTest, Scope) {
    204   LifeCycleWatcher watcher;
    205   EXPECT_EQ(LC_INITIAL, watcher.life_cycle_state());
    206   {
    207     ScopedVector<LifeCycleObject> scoped_vector;
    208     scoped_vector.push_back(watcher.NewLifeCycleObject());
    209     EXPECT_EQ(LC_CONSTRUCTED, watcher.life_cycle_state());
    210     EXPECT_TRUE(watcher.IsWatching(scoped_vector.back()));
    211   }
    212   EXPECT_EQ(LC_DESTROYED, watcher.life_cycle_state());
    213 }
    214 
    215 TEST(ScopedVectorTest, MoveConstruct) {
    216   LifeCycleWatcher watcher;
    217   EXPECT_EQ(LC_INITIAL, watcher.life_cycle_state());
    218   {
    219     ScopedVector<LifeCycleObject> scoped_vector;
    220     scoped_vector.push_back(watcher.NewLifeCycleObject());
    221     EXPECT_FALSE(scoped_vector.empty());
    222     EXPECT_TRUE(watcher.IsWatching(scoped_vector.back()));
    223 
    224     ScopedVector<LifeCycleObject> scoped_vector_copy(
    225         scoped_vector.DEPRECATED_Pass());
    226     EXPECT_TRUE(scoped_vector.empty());
    227     EXPECT_FALSE(scoped_vector_copy.empty());
    228     EXPECT_TRUE(watcher.IsWatching(scoped_vector_copy.back()));
    229 
    230     EXPECT_EQ(LC_CONSTRUCTED, watcher.life_cycle_state());
    231   }
    232   EXPECT_EQ(LC_DESTROYED, watcher.life_cycle_state());
    233 }
    234 
    235 TEST(ScopedVectorTest, MoveAssign) {
    236   LifeCycleWatcher watcher;
    237   EXPECT_EQ(LC_INITIAL, watcher.life_cycle_state());
    238   {
    239     ScopedVector<LifeCycleObject> scoped_vector;
    240     scoped_vector.push_back(watcher.NewLifeCycleObject());
    241     ScopedVector<LifeCycleObject> scoped_vector_assign;
    242     EXPECT_FALSE(scoped_vector.empty());
    243     EXPECT_TRUE(watcher.IsWatching(scoped_vector.back()));
    244 
    245     scoped_vector_assign = scoped_vector.DEPRECATED_Pass();
    246     EXPECT_TRUE(scoped_vector.empty());
    247     EXPECT_FALSE(scoped_vector_assign.empty());
    248     EXPECT_TRUE(watcher.IsWatching(scoped_vector_assign.back()));
    249 
    250     EXPECT_EQ(LC_CONSTRUCTED, watcher.life_cycle_state());
    251   }
    252   EXPECT_EQ(LC_DESTROYED, watcher.life_cycle_state());
    253 }
    254 
    255 class DeleteCounter {
    256  public:
    257   explicit DeleteCounter(int* deletes)
    258       : deletes_(deletes) {
    259   }
    260 
    261   ~DeleteCounter() {
    262     (*deletes_)++;
    263   }
    264 
    265   void VoidMethod0() {}
    266 
    267  private:
    268   int* const deletes_;
    269 
    270   RTC_DISALLOW_COPY_AND_ASSIGN(DeleteCounter);
    271 };
    272 
    273 // This class is used in place of Chromium's base::Callback.
    274 template <typename T>
    275 class PassThru  {
    276  public:
    277   explicit PassThru(ScopedVector<T> scoper)
    278       : scoper_(scoper.DEPRECATED_Pass()) {}
    279 
    280   ScopedVector<T> Run() {
    281     return scoper_.DEPRECATED_Pass();
    282   }
    283 
    284  private:
    285   ScopedVector<T> scoper_;
    286 };
    287 
    288 TEST(ScopedVectorTest, Passed) {
    289   int deletes = 0;
    290   ScopedVector<DeleteCounter> deleter_vector;
    291   deleter_vector.push_back(new DeleteCounter(&deletes));
    292   EXPECT_EQ(0, deletes);
    293   PassThru<DeleteCounter> pass_thru(deleter_vector.DEPRECATED_Pass());
    294   EXPECT_EQ(0, deletes);
    295   ScopedVector<DeleteCounter> result = pass_thru.Run();
    296   EXPECT_EQ(0, deletes);
    297   result.clear();
    298   EXPECT_EQ(1, deletes);
    299 };
    300 
    301 TEST(ScopedVectorTest, InsertRange) {
    302   LifeCycleWatcher watchers[5];
    303   size_t watchers_size = sizeof(watchers) / sizeof(*watchers);
    304 
    305   std::vector<LifeCycleObject*> vec;
    306   for (LifeCycleWatcher* it = watchers; it != watchers + watchers_size;
    307        ++it) {
    308     EXPECT_EQ(LC_INITIAL, it->life_cycle_state());
    309     vec.push_back(it->NewLifeCycleObject());
    310     EXPECT_EQ(LC_CONSTRUCTED, it->life_cycle_state());
    311   }
    312   // Start scope for ScopedVector.
    313   {
    314     ScopedVector<LifeCycleObject> scoped_vector;
    315     scoped_vector.insert(scoped_vector.end(), vec.begin() + 1, vec.begin() + 3);
    316     for (LifeCycleWatcher* it = watchers; it != watchers + watchers_size;
    317          ++it)
    318       EXPECT_EQ(LC_CONSTRUCTED, it->life_cycle_state());
    319   }
    320   for (LifeCycleWatcher* it = watchers; it != watchers + 1; ++it)
    321     EXPECT_EQ(LC_CONSTRUCTED, it->life_cycle_state());
    322   for (LifeCycleWatcher* it = watchers + 1; it != watchers + 3; ++it)
    323     EXPECT_EQ(LC_DESTROYED, it->life_cycle_state());
    324   for (LifeCycleWatcher* it = watchers + 3; it != watchers + watchers_size;
    325       ++it)
    326     EXPECT_EQ(LC_CONSTRUCTED, it->life_cycle_state());
    327 }
    328 
    329 }  // namespace
    330 }  // namespace webrtc
    331