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/ref_counted.h"
      6 
      7 #include "base/test/opaque_ref_counted.h"
      8 #include "testing/gtest/include/gtest/gtest.h"
      9 
     10 namespace {
     11 
     12 class SelfAssign : public base::RefCounted<SelfAssign> {
     13  protected:
     14   virtual ~SelfAssign() {}
     15 
     16  private:
     17   friend class base::RefCounted<SelfAssign>;
     18 };
     19 
     20 class Derived : public SelfAssign {
     21  protected:
     22   ~Derived() override {}
     23 
     24  private:
     25   friend class base::RefCounted<Derived>;
     26 };
     27 
     28 class CheckDerivedMemberAccess : public scoped_refptr<SelfAssign> {
     29  public:
     30   CheckDerivedMemberAccess() {
     31     // This shouldn't compile if we don't have access to the member variable.
     32     SelfAssign** pptr = &ptr_;
     33     EXPECT_EQ(*pptr, ptr_);
     34   }
     35 };
     36 
     37 class ScopedRefPtrToSelf : public base::RefCounted<ScopedRefPtrToSelf> {
     38  public:
     39   ScopedRefPtrToSelf() : self_ptr_(this) {}
     40 
     41   static bool was_destroyed() { return was_destroyed_; }
     42 
     43   static void reset_was_destroyed() { was_destroyed_ = false; }
     44 
     45   scoped_refptr<ScopedRefPtrToSelf> self_ptr_;
     46 
     47  private:
     48   friend class base::RefCounted<ScopedRefPtrToSelf>;
     49   ~ScopedRefPtrToSelf() { was_destroyed_ = true; }
     50 
     51   static bool was_destroyed_;
     52 };
     53 
     54 bool ScopedRefPtrToSelf::was_destroyed_ = false;
     55 
     56 class ScopedRefPtrCountBase : public base::RefCounted<ScopedRefPtrCountBase> {
     57  public:
     58   ScopedRefPtrCountBase() { ++constructor_count_; }
     59 
     60   static int constructor_count() { return constructor_count_; }
     61 
     62   static int destructor_count() { return destructor_count_; }
     63 
     64   static void reset_count() {
     65     constructor_count_ = 0;
     66     destructor_count_ = 0;
     67   }
     68 
     69  protected:
     70   virtual ~ScopedRefPtrCountBase() { ++destructor_count_; }
     71 
     72  private:
     73   friend class base::RefCounted<ScopedRefPtrCountBase>;
     74 
     75   static int constructor_count_;
     76   static int destructor_count_;
     77 };
     78 
     79 int ScopedRefPtrCountBase::constructor_count_ = 0;
     80 int ScopedRefPtrCountBase::destructor_count_ = 0;
     81 
     82 class ScopedRefPtrCountDerived : public ScopedRefPtrCountBase {
     83  public:
     84   ScopedRefPtrCountDerived() { ++constructor_count_; }
     85 
     86   static int constructor_count() { return constructor_count_; }
     87 
     88   static int destructor_count() { return destructor_count_; }
     89 
     90   static void reset_count() {
     91     constructor_count_ = 0;
     92     destructor_count_ = 0;
     93   }
     94 
     95  protected:
     96   ~ScopedRefPtrCountDerived() override { ++destructor_count_; }
     97 
     98  private:
     99   friend class base::RefCounted<ScopedRefPtrCountDerived>;
    100 
    101   static int constructor_count_;
    102   static int destructor_count_;
    103 };
    104 
    105 int ScopedRefPtrCountDerived::constructor_count_ = 0;
    106 int ScopedRefPtrCountDerived::destructor_count_ = 0;
    107 
    108 class Other : public base::RefCounted<Other> {
    109  private:
    110   friend class base::RefCounted<Other>;
    111 
    112   ~Other() {}
    113 };
    114 
    115 scoped_refptr<Other> Overloaded(scoped_refptr<Other> other) {
    116   return other;
    117 }
    118 
    119 scoped_refptr<SelfAssign> Overloaded(scoped_refptr<SelfAssign> self_assign) {
    120   return self_assign;
    121 }
    122 
    123 
    124 }  // end namespace
    125 
    126 TEST(RefCountedUnitTest, TestSelfAssignment) {
    127   SelfAssign* p = new SelfAssign;
    128   scoped_refptr<SelfAssign> var(p);
    129   var = var;
    130   EXPECT_EQ(var.get(), p);
    131 }
    132 
    133 TEST(RefCountedUnitTest, ScopedRefPtrMemberAccess) {
    134   CheckDerivedMemberAccess check;
    135 }
    136 
    137 TEST(RefCountedUnitTest, ScopedRefPtrToSelfPointerAssignment) {
    138   ScopedRefPtrToSelf::reset_was_destroyed();
    139 
    140   ScopedRefPtrToSelf* check = new ScopedRefPtrToSelf();
    141   EXPECT_FALSE(ScopedRefPtrToSelf::was_destroyed());
    142   check->self_ptr_ = nullptr;
    143   EXPECT_TRUE(ScopedRefPtrToSelf::was_destroyed());
    144 }
    145 
    146 TEST(RefCountedUnitTest, ScopedRefPtrToSelfMoveAssignment) {
    147   ScopedRefPtrToSelf::reset_was_destroyed();
    148 
    149   ScopedRefPtrToSelf* check = new ScopedRefPtrToSelf();
    150   EXPECT_FALSE(ScopedRefPtrToSelf::was_destroyed());
    151   // Releasing |check->self_ptr_| will delete |check|.
    152   // The move assignment operator must assign |check->self_ptr_| first then
    153   // release |check->self_ptr_|.
    154   check->self_ptr_ = scoped_refptr<ScopedRefPtrToSelf>();
    155   EXPECT_TRUE(ScopedRefPtrToSelf::was_destroyed());
    156 }
    157 
    158 TEST(RefCountedUnitTest, ScopedRefPtrToOpaque) {
    159   scoped_refptr<base::OpaqueRefCounted> p = base::MakeOpaqueRefCounted();
    160   base::TestOpaqueRefCounted(p);
    161 
    162   scoped_refptr<base::OpaqueRefCounted> q;
    163   q = p;
    164   base::TestOpaqueRefCounted(p);
    165   base::TestOpaqueRefCounted(q);
    166 }
    167 
    168 TEST(RefCountedUnitTest, BooleanTesting) {
    169   scoped_refptr<SelfAssign> ptr_to_an_instance = new SelfAssign;
    170   EXPECT_TRUE(ptr_to_an_instance);
    171   EXPECT_FALSE(!ptr_to_an_instance);
    172 
    173   if (ptr_to_an_instance) {
    174   } else {
    175     ADD_FAILURE() << "Pointer to an instance should result in true.";
    176   }
    177 
    178   if (!ptr_to_an_instance) {  // check for operator!().
    179     ADD_FAILURE() << "Pointer to an instance should result in !x being false.";
    180   }
    181 
    182   scoped_refptr<SelfAssign> null_ptr;
    183   EXPECT_FALSE(null_ptr);
    184   EXPECT_TRUE(!null_ptr);
    185 
    186   if (null_ptr) {
    187     ADD_FAILURE() << "Null pointer should result in false.";
    188   }
    189 
    190   if (!null_ptr) {  // check for operator!().
    191   } else {
    192     ADD_FAILURE() << "Null pointer should result in !x being true.";
    193   }
    194 }
    195 
    196 TEST(RefCountedUnitTest, Equality) {
    197   scoped_refptr<SelfAssign> p1(new SelfAssign);
    198   scoped_refptr<SelfAssign> p2(new SelfAssign);
    199 
    200   EXPECT_EQ(p1, p1);
    201   EXPECT_EQ(p2, p2);
    202 
    203   EXPECT_NE(p1, p2);
    204   EXPECT_NE(p2, p1);
    205 }
    206 
    207 TEST(RefCountedUnitTest, NullptrEquality) {
    208   scoped_refptr<SelfAssign> ptr_to_an_instance(new SelfAssign);
    209   scoped_refptr<SelfAssign> ptr_to_nullptr;
    210 
    211   EXPECT_NE(nullptr, ptr_to_an_instance);
    212   EXPECT_NE(ptr_to_an_instance, nullptr);
    213   EXPECT_EQ(nullptr, ptr_to_nullptr);
    214   EXPECT_EQ(ptr_to_nullptr, nullptr);
    215 }
    216 
    217 TEST(RefCountedUnitTest, ConvertibleEquality) {
    218   scoped_refptr<Derived> p1(new Derived);
    219   scoped_refptr<SelfAssign> p2;
    220 
    221   EXPECT_NE(p1, p2);
    222   EXPECT_NE(p2, p1);
    223 
    224   p2 = p1;
    225 
    226   EXPECT_EQ(p1, p2);
    227   EXPECT_EQ(p2, p1);
    228 }
    229 
    230 TEST(RefCountedUnitTest, MoveAssignment1) {
    231   ScopedRefPtrCountBase::reset_count();
    232 
    233   {
    234     ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
    235     scoped_refptr<ScopedRefPtrCountBase> p1(raw);
    236     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
    237     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
    238 
    239     {
    240       scoped_refptr<ScopedRefPtrCountBase> p2;
    241 
    242       p2 = std::move(p1);
    243       EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
    244       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
    245       EXPECT_EQ(nullptr, p1.get());
    246       EXPECT_EQ(raw, p2.get());
    247 
    248       // p2 goes out of scope.
    249     }
    250     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
    251     EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
    252 
    253     // p1 goes out of scope.
    254   }
    255   EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
    256   EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
    257 }
    258 
    259 TEST(RefCountedUnitTest, MoveAssignment2) {
    260   ScopedRefPtrCountBase::reset_count();
    261 
    262   {
    263     ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
    264     scoped_refptr<ScopedRefPtrCountBase> p1;
    265     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
    266     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
    267 
    268     {
    269       scoped_refptr<ScopedRefPtrCountBase> p2(raw);
    270       EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
    271       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
    272 
    273       p1 = std::move(p2);
    274       EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
    275       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
    276       EXPECT_EQ(raw, p1.get());
    277       EXPECT_EQ(nullptr, p2.get());
    278 
    279       // p2 goes out of scope.
    280     }
    281     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
    282     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
    283 
    284     // p1 goes out of scope.
    285   }
    286   EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
    287   EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
    288 }
    289 
    290 TEST(RefCountedUnitTest, MoveAssignmentSameInstance1) {
    291   ScopedRefPtrCountBase::reset_count();
    292 
    293   {
    294     ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
    295     scoped_refptr<ScopedRefPtrCountBase> p1(raw);
    296     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
    297     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
    298 
    299     {
    300       scoped_refptr<ScopedRefPtrCountBase> p2(p1);
    301       EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
    302       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
    303 
    304       p1 = std::move(p2);
    305       EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
    306       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
    307       EXPECT_EQ(raw, p1.get());
    308       EXPECT_EQ(nullptr, p2.get());
    309 
    310       // p2 goes out of scope.
    311     }
    312     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
    313     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
    314 
    315     // p1 goes out of scope.
    316   }
    317   EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
    318   EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
    319 }
    320 
    321 TEST(RefCountedUnitTest, MoveAssignmentSameInstance2) {
    322   ScopedRefPtrCountBase::reset_count();
    323 
    324   {
    325     ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
    326     scoped_refptr<ScopedRefPtrCountBase> p1(raw);
    327     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
    328     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
    329 
    330     {
    331       scoped_refptr<ScopedRefPtrCountBase> p2(p1);
    332       EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
    333       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
    334 
    335       p2 = std::move(p1);
    336       EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
    337       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
    338       EXPECT_EQ(nullptr, p1.get());
    339       EXPECT_EQ(raw, p2.get());
    340 
    341       // p2 goes out of scope.
    342     }
    343     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
    344     EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
    345 
    346     // p1 goes out of scope.
    347   }
    348   EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
    349   EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
    350 }
    351 
    352 TEST(RefCountedUnitTest, MoveAssignmentDifferentInstances) {
    353   ScopedRefPtrCountBase::reset_count();
    354 
    355   {
    356     ScopedRefPtrCountBase *raw1 = new ScopedRefPtrCountBase();
    357     scoped_refptr<ScopedRefPtrCountBase> p1(raw1);
    358     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
    359     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
    360 
    361     {
    362       ScopedRefPtrCountBase *raw2 = new ScopedRefPtrCountBase();
    363       scoped_refptr<ScopedRefPtrCountBase> p2(raw2);
    364       EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
    365       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
    366 
    367       p1 = std::move(p2);
    368       EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
    369       EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
    370       EXPECT_EQ(raw2, p1.get());
    371       EXPECT_EQ(nullptr, p2.get());
    372 
    373       // p2 goes out of scope.
    374     }
    375     EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
    376     EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
    377 
    378     // p1 goes out of scope.
    379   }
    380   EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
    381   EXPECT_EQ(2, ScopedRefPtrCountBase::destructor_count());
    382 }
    383 
    384 TEST(RefCountedUnitTest, MoveAssignmentDerived) {
    385   ScopedRefPtrCountBase::reset_count();
    386   ScopedRefPtrCountDerived::reset_count();
    387 
    388   {
    389     ScopedRefPtrCountBase *raw1 = new ScopedRefPtrCountBase();
    390     scoped_refptr<ScopedRefPtrCountBase> p1(raw1);
    391     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
    392     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
    393     EXPECT_EQ(0, ScopedRefPtrCountDerived::constructor_count());
    394     EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
    395 
    396     {
    397       ScopedRefPtrCountDerived *raw2 = new ScopedRefPtrCountDerived();
    398       scoped_refptr<ScopedRefPtrCountDerived> p2(raw2);
    399       EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
    400       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
    401       EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
    402       EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
    403 
    404       p1 = std::move(p2);
    405       EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
    406       EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
    407       EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
    408       EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
    409       EXPECT_EQ(raw2, p1.get());
    410       EXPECT_EQ(nullptr, p2.get());
    411 
    412       // p2 goes out of scope.
    413     }
    414     EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
    415     EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
    416     EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
    417     EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
    418 
    419     // p1 goes out of scope.
    420   }
    421   EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
    422   EXPECT_EQ(2, ScopedRefPtrCountBase::destructor_count());
    423   EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
    424   EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count());
    425 }
    426 
    427 TEST(RefCountedUnitTest, MoveConstructor) {
    428   ScopedRefPtrCountBase::reset_count();
    429 
    430   {
    431     ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
    432     scoped_refptr<ScopedRefPtrCountBase> p1(raw);
    433     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
    434     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
    435 
    436     {
    437       scoped_refptr<ScopedRefPtrCountBase> p2(std::move(p1));
    438       EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
    439       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
    440       EXPECT_EQ(nullptr, p1.get());
    441       EXPECT_EQ(raw, p2.get());
    442 
    443       // p2 goes out of scope.
    444     }
    445     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
    446     EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
    447 
    448     // p1 goes out of scope.
    449   }
    450   EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
    451   EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
    452 }
    453 
    454 TEST(RefCountedUnitTest, MoveConstructorDerived) {
    455   ScopedRefPtrCountBase::reset_count();
    456   ScopedRefPtrCountDerived::reset_count();
    457 
    458   {
    459     ScopedRefPtrCountDerived *raw1 = new ScopedRefPtrCountDerived();
    460     scoped_refptr<ScopedRefPtrCountDerived> p1(raw1);
    461     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
    462     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
    463     EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
    464     EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
    465 
    466     {
    467       scoped_refptr<ScopedRefPtrCountBase> p2(std::move(p1));
    468       EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
    469       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
    470       EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
    471       EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
    472       EXPECT_EQ(nullptr, p1.get());
    473       EXPECT_EQ(raw1, p2.get());
    474 
    475       // p2 goes out of scope.
    476     }
    477     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
    478     EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
    479     EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
    480     EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count());
    481 
    482     // p1 goes out of scope.
    483   }
    484   EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
    485   EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
    486   EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
    487   EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count());
    488 }
    489 
    490 TEST(RefCountedUnitTest, TestOverloadResolutionCopy) {
    491   scoped_refptr<Derived> derived(new Derived);
    492   scoped_refptr<SelfAssign> expected(derived);
    493   EXPECT_EQ(expected, Overloaded(derived));
    494 
    495   scoped_refptr<Other> other(new Other);
    496   EXPECT_EQ(other, Overloaded(other));
    497 }
    498 
    499 TEST(RefCountedUnitTest, TestOverloadResolutionMove) {
    500   scoped_refptr<Derived> derived(new Derived);
    501   scoped_refptr<SelfAssign> expected(derived);
    502   EXPECT_EQ(expected, Overloaded(std::move(derived)));
    503 
    504   scoped_refptr<Other> other(new Other);
    505   scoped_refptr<Other> other2(other);
    506   EXPECT_EQ(other2, Overloaded(std::move(other)));
    507 }
    508