Home | History | Annotate | Download | only in fxcrt
      1 // Copyright 2016 PDFium 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 "core/fxcrt/retain_ptr.h"
      6 
      7 #include <utility>
      8 #include <vector>
      9 
     10 #include "testing/gtest/include/gtest/gtest.h"
     11 
     12 namespace fxcrt {
     13 namespace {
     14 
     15 class PseudoRetainable {
     16  public:
     17   PseudoRetainable() : retain_count_(0), release_count_(0) {}
     18   void Retain() { ++retain_count_; }
     19   void Release() { ++release_count_; }
     20   int retain_count() const { return retain_count_; }
     21   int release_count() const { return release_count_; }
     22 
     23  private:
     24   int retain_count_;
     25   int release_count_;
     26 };
     27 
     28 }  // namespace
     29 
     30 TEST(RetainPtr, Null) {
     31   RetainPtr<PseudoRetainable> ptr;
     32   EXPECT_EQ(nullptr, ptr.Get());
     33 }
     34 
     35 TEST(RetainPtr, Normal) {
     36   PseudoRetainable obj;
     37   {
     38     RetainPtr<PseudoRetainable> ptr(&obj);
     39     EXPECT_EQ(&obj, ptr.Get());
     40     EXPECT_EQ(1, obj.retain_count());
     41     EXPECT_EQ(0, obj.release_count());
     42   }
     43   EXPECT_EQ(1, obj.retain_count());
     44   EXPECT_EQ(1, obj.release_count());
     45 }
     46 
     47 TEST(RetainPtr, CopyCtor) {
     48   PseudoRetainable obj;
     49   {
     50     RetainPtr<PseudoRetainable> ptr1(&obj);
     51     {
     52       RetainPtr<PseudoRetainable> ptr2(ptr1);
     53       EXPECT_EQ(2, obj.retain_count());
     54       EXPECT_EQ(0, obj.release_count());
     55     }
     56     EXPECT_EQ(2, obj.retain_count());
     57     EXPECT_EQ(1, obj.release_count());
     58   }
     59   EXPECT_EQ(2, obj.retain_count());
     60   EXPECT_EQ(2, obj.release_count());
     61 }
     62 
     63 TEST(RetainPtr, MoveCtor) {
     64   PseudoRetainable obj;
     65   {
     66     RetainPtr<PseudoRetainable> ptr1(&obj);
     67     {
     68       RetainPtr<PseudoRetainable> ptr2(std::move(ptr1));
     69       EXPECT_EQ(nullptr, ptr1.Get());
     70       EXPECT_EQ(&obj, ptr2.Get());
     71       EXPECT_EQ(1, obj.retain_count());
     72       EXPECT_EQ(0, obj.release_count());
     73     }
     74     EXPECT_EQ(1, obj.retain_count());
     75     EXPECT_EQ(1, obj.release_count());
     76   }
     77   EXPECT_EQ(1, obj.retain_count());
     78   EXPECT_EQ(1, obj.release_count());
     79 }
     80 
     81 TEST(RetainPtr, ResetNull) {
     82   PseudoRetainable obj;
     83   {
     84     RetainPtr<PseudoRetainable> ptr(&obj);
     85     ptr.Reset();
     86     EXPECT_EQ(1, obj.retain_count());
     87     EXPECT_EQ(1, obj.release_count());
     88   }
     89   EXPECT_EQ(1, obj.retain_count());
     90   EXPECT_EQ(1, obj.release_count());
     91 }
     92 
     93 TEST(RetainPtr, Reset) {
     94   PseudoRetainable obj1;
     95   PseudoRetainable obj2;
     96   {
     97     RetainPtr<PseudoRetainable> ptr(&obj1);
     98     ptr.Reset(&obj2);
     99     EXPECT_EQ(1, obj1.retain_count());
    100     EXPECT_EQ(1, obj1.release_count());
    101     EXPECT_EQ(1, obj2.retain_count());
    102     EXPECT_EQ(0, obj2.release_count());
    103   }
    104   EXPECT_EQ(1, obj1.retain_count());
    105   EXPECT_EQ(1, obj1.release_count());
    106   EXPECT_EQ(1, obj2.retain_count());
    107   EXPECT_EQ(1, obj2.release_count());
    108 }
    109 
    110 TEST(RetainPtr, Swap) {
    111   PseudoRetainable obj1;
    112   PseudoRetainable obj2;
    113   {
    114     RetainPtr<PseudoRetainable> ptr1(&obj1);
    115     {
    116       RetainPtr<PseudoRetainable> ptr2(&obj2);
    117       ptr1.Swap(ptr2);
    118       EXPECT_EQ(1, obj1.retain_count());
    119       EXPECT_EQ(0, obj1.release_count());
    120       EXPECT_EQ(1, obj2.retain_count());
    121       EXPECT_EQ(0, obj2.release_count());
    122     }
    123     EXPECT_EQ(1, obj1.retain_count());
    124     EXPECT_EQ(1, obj1.release_count());
    125     EXPECT_EQ(1, obj2.retain_count());
    126     EXPECT_EQ(0, obj2.release_count());
    127   }
    128   EXPECT_EQ(1, obj1.retain_count());
    129   EXPECT_EQ(1, obj1.release_count());
    130   EXPECT_EQ(1, obj2.retain_count());
    131   EXPECT_EQ(1, obj2.release_count());
    132 }
    133 
    134 TEST(RetainPtr, Leak) {
    135   PseudoRetainable obj;
    136   PseudoRetainable* leak;
    137   {
    138     RetainPtr<PseudoRetainable> ptr(&obj);
    139     leak = ptr.Leak();
    140     EXPECT_EQ(1, obj.retain_count());
    141     EXPECT_EQ(0, obj.release_count());
    142   }
    143   EXPECT_EQ(1, obj.retain_count());
    144   EXPECT_EQ(0, obj.release_count());
    145   {
    146     RetainPtr<PseudoRetainable> ptr;
    147     ptr.Unleak(leak);
    148     EXPECT_EQ(1, obj.retain_count());
    149     EXPECT_EQ(0, obj.release_count());
    150   }
    151   EXPECT_EQ(1, obj.retain_count());
    152   EXPECT_EQ(1, obj.release_count());
    153 }
    154 
    155 TEST(RetainPtr, SwapNull) {
    156   PseudoRetainable obj1;
    157   {
    158     RetainPtr<PseudoRetainable> ptr1(&obj1);
    159     {
    160       RetainPtr<PseudoRetainable> ptr2;
    161       ptr1.Swap(ptr2);
    162       EXPECT_FALSE(ptr1);
    163       EXPECT_TRUE(ptr2);
    164       EXPECT_EQ(1, obj1.retain_count());
    165       EXPECT_EQ(0, obj1.release_count());
    166     }
    167     EXPECT_EQ(1, obj1.retain_count());
    168     EXPECT_EQ(1, obj1.release_count());
    169   }
    170   EXPECT_EQ(1, obj1.retain_count());
    171   EXPECT_EQ(1, obj1.release_count());
    172 }
    173 
    174 TEST(RetainPtr, Assign) {
    175   PseudoRetainable obj;
    176   {
    177     RetainPtr<PseudoRetainable> ptr(&obj);
    178     {
    179       RetainPtr<PseudoRetainable> ptr2;
    180       ptr2 = ptr;
    181       EXPECT_EQ(2, obj.retain_count());
    182       EXPECT_EQ(0, obj.release_count());
    183     }
    184     EXPECT_EQ(2, obj.retain_count());
    185     EXPECT_EQ(1, obj.release_count());
    186   }
    187   EXPECT_EQ(2, obj.retain_count());
    188   EXPECT_EQ(2, obj.release_count());
    189 }
    190 
    191 TEST(RetainPtr, MoveAssign) {
    192   PseudoRetainable obj;
    193   {
    194     RetainPtr<PseudoRetainable> ptr1(&obj);
    195     {
    196       RetainPtr<PseudoRetainable> ptr2;
    197       EXPECT_EQ(&obj, ptr1.Get());
    198       EXPECT_EQ(nullptr, ptr2.Get());
    199       ptr2 = std::move(ptr1);
    200       EXPECT_EQ(nullptr, ptr1.Get());
    201       EXPECT_EQ(&obj, ptr2.Get());
    202       EXPECT_EQ(1, obj.retain_count());
    203       EXPECT_EQ(0, obj.release_count());
    204     }
    205     EXPECT_EQ(1, obj.retain_count());
    206     EXPECT_EQ(1, obj.release_count());
    207   }
    208   EXPECT_EQ(1, obj.retain_count());
    209   EXPECT_EQ(1, obj.release_count());
    210 }
    211 
    212 TEST(RetainPtr, Equals) {
    213   PseudoRetainable obj1;
    214   PseudoRetainable obj2;
    215   RetainPtr<PseudoRetainable> null_ptr1;
    216   RetainPtr<PseudoRetainable> obj1_ptr1(&obj1);
    217   RetainPtr<PseudoRetainable> obj2_ptr1(&obj2);
    218   {
    219     RetainPtr<PseudoRetainable> null_ptr2;
    220     EXPECT_TRUE(null_ptr1 == null_ptr2);
    221 
    222     RetainPtr<PseudoRetainable> obj1_ptr2(&obj1);
    223     EXPECT_TRUE(obj1_ptr1 == obj1_ptr2);
    224 
    225     RetainPtr<PseudoRetainable> obj2_ptr2(&obj2);
    226     EXPECT_TRUE(obj2_ptr1 == obj2_ptr2);
    227   }
    228   EXPECT_FALSE(null_ptr1 == obj1_ptr1);
    229   EXPECT_FALSE(null_ptr1 == obj2_ptr1);
    230   EXPECT_FALSE(obj1_ptr1 == obj2_ptr1);
    231 }
    232 
    233 TEST(RetainPtr, NotEquals) {
    234   PseudoRetainable obj1;
    235   PseudoRetainable obj2;
    236   RetainPtr<PseudoRetainable> null_ptr1;
    237   RetainPtr<PseudoRetainable> obj1_ptr1(&obj1);
    238   RetainPtr<PseudoRetainable> obj2_ptr1(&obj2);
    239   {
    240     RetainPtr<PseudoRetainable> null_ptr2;
    241     RetainPtr<PseudoRetainable> obj1_ptr2(&obj1);
    242     RetainPtr<PseudoRetainable> obj2_ptr2(&obj2);
    243     EXPECT_FALSE(null_ptr1 != null_ptr2);
    244     EXPECT_FALSE(obj1_ptr1 != obj1_ptr2);
    245     EXPECT_FALSE(obj2_ptr1 != obj2_ptr2);
    246   }
    247   EXPECT_TRUE(null_ptr1 != obj1_ptr1);
    248   EXPECT_TRUE(null_ptr1 != obj2_ptr1);
    249   EXPECT_TRUE(obj1_ptr1 != obj2_ptr1);
    250 }
    251 
    252 TEST(RetainPtr, LessThan) {
    253   PseudoRetainable objs[2];
    254   RetainPtr<PseudoRetainable> obj1_ptr(&objs[0]);
    255   RetainPtr<PseudoRetainable> obj2_ptr(&objs[1]);
    256   EXPECT_TRUE(obj1_ptr < obj2_ptr);
    257   EXPECT_FALSE(obj2_ptr < obj1_ptr);
    258 }
    259 
    260 TEST(RetainPtr, Bool) {
    261   PseudoRetainable obj1;
    262   RetainPtr<PseudoRetainable> null_ptr;
    263   RetainPtr<PseudoRetainable> obj1_ptr(&obj1);
    264   bool null_bool = !!null_ptr;
    265   bool obj1_bool = !!obj1_ptr;
    266   EXPECT_FALSE(null_bool);
    267   EXPECT_TRUE(obj1_bool);
    268 }
    269 
    270 TEST(RetainPtr, MakeRetained) {
    271   auto ptr = pdfium::MakeRetain<Retainable>();
    272   EXPECT_TRUE(ptr->HasOneRef());
    273   {
    274     RetainPtr<Retainable> other = ptr;
    275     EXPECT_FALSE(ptr->HasOneRef());
    276   }
    277   EXPECT_TRUE(ptr->HasOneRef());
    278 }
    279 
    280 TEST(RetainPtr, VectorMove) {
    281   // Proves move ctor is selected by std::vector over copy/delete, this
    282   // may require the ctor to be marked "noexcept".
    283   PseudoRetainable obj;
    284   {
    285     RetainPtr<PseudoRetainable> ptr(&obj);
    286     std::vector<RetainPtr<PseudoRetainable>> vec1;
    287     vec1.push_back(std::move(ptr));
    288     EXPECT_EQ(1, obj.retain_count());
    289     EXPECT_EQ(0, obj.release_count());
    290 
    291     std::vector<RetainPtr<PseudoRetainable>> vec2 = std::move(vec1);
    292     EXPECT_EQ(1, obj.retain_count());
    293     EXPECT_EQ(0, obj.release_count());
    294 
    295     vec2.resize(4096);
    296     EXPECT_EQ(1, obj.retain_count());
    297     EXPECT_EQ(0, obj.release_count());
    298   }
    299   EXPECT_EQ(1, obj.retain_count());
    300   EXPECT_EQ(1, obj.release_count());
    301 }
    302 
    303 }  // namespace fxcrt
    304