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/weak_ptr.h"
      6 
      7 #include <memory>
      8 #include <utility>
      9 
     10 #include "core/fxcrt/fx_memory.h"
     11 #include "testing/gtest/include/gtest/gtest.h"
     12 
     13 namespace fxcrt {
     14 namespace {
     15 
     16 class PseudoDeletable;
     17 using WeakTestPtr = WeakPtr<PseudoDeletable, ReleaseDeleter<PseudoDeletable>>;
     18 using UniqueTestPtr =
     19     std::unique_ptr<PseudoDeletable, ReleaseDeleter<PseudoDeletable>>;
     20 
     21 class PseudoDeletable {
     22  public:
     23   PseudoDeletable() : delete_count_(0) {}
     24   void Release() {
     25     ++delete_count_;
     26     next_.Reset();
     27   }
     28   void SetNext(const WeakTestPtr& next) { next_ = next; }
     29   int delete_count() const { return delete_count_; }
     30 
     31  private:
     32   int delete_count_;
     33   WeakTestPtr next_;
     34 };
     35 
     36 }  // namespace
     37 
     38 TEST(WeakPtr, Null) {
     39   WeakTestPtr ptr1;
     40   EXPECT_FALSE(ptr1);
     41 
     42   WeakTestPtr ptr2;
     43   EXPECT_TRUE(ptr1 == ptr2);
     44   EXPECT_FALSE(ptr1 != ptr2);
     45 
     46   WeakTestPtr ptr3(ptr1);
     47   EXPECT_TRUE(ptr1 == ptr3);
     48   EXPECT_FALSE(ptr1 != ptr3);
     49 
     50   WeakTestPtr ptr4 = ptr1;
     51   EXPECT_TRUE(ptr1 == ptr4);
     52   EXPECT_FALSE(ptr1 != ptr4);
     53 }
     54 
     55 TEST(WeakPtr, NonNull) {
     56   PseudoDeletable thing;
     57   EXPECT_EQ(0, thing.delete_count());
     58   {
     59     UniqueTestPtr unique(&thing);
     60     WeakTestPtr ptr1(std::move(unique));
     61     EXPECT_TRUE(ptr1);
     62     EXPECT_EQ(&thing, ptr1.Get());
     63 
     64     WeakTestPtr ptr2;
     65     EXPECT_FALSE(ptr1 == ptr2);
     66     EXPECT_TRUE(ptr1 != ptr2);
     67     {
     68       WeakTestPtr ptr3(ptr1);
     69       EXPECT_TRUE(ptr1 == ptr3);
     70       EXPECT_FALSE(ptr1 != ptr3);
     71       EXPECT_EQ(&thing, ptr3.Get());
     72       {
     73         WeakTestPtr ptr4 = ptr1;
     74         EXPECT_TRUE(ptr1 == ptr4);
     75         EXPECT_FALSE(ptr1 != ptr4);
     76         EXPECT_EQ(&thing, ptr4.Get());
     77       }
     78     }
     79     EXPECT_EQ(0, thing.delete_count());
     80   }
     81   EXPECT_EQ(1, thing.delete_count());
     82 }
     83 
     84 TEST(WeakPtr, ResetNull) {
     85   PseudoDeletable thing;
     86   {
     87     UniqueTestPtr unique(&thing);
     88     WeakTestPtr ptr1(std::move(unique));
     89     WeakTestPtr ptr2 = ptr1;
     90     ptr1.Reset();
     91     EXPECT_FALSE(ptr1);
     92     EXPECT_EQ(nullptr, ptr1.Get());
     93     EXPECT_TRUE(ptr2);
     94     EXPECT_EQ(&thing, ptr2.Get());
     95     EXPECT_FALSE(ptr1 == ptr2);
     96     EXPECT_TRUE(ptr1 != ptr2);
     97     EXPECT_EQ(0, thing.delete_count());
     98   }
     99   EXPECT_EQ(1, thing.delete_count());
    100 }
    101 
    102 TEST(WeakPtr, ResetNonNull) {
    103   PseudoDeletable thing1;
    104   PseudoDeletable thing2;
    105   {
    106     UniqueTestPtr unique1(&thing1);
    107     WeakTestPtr ptr1(std::move(unique1));
    108     WeakTestPtr ptr2 = ptr1;
    109     UniqueTestPtr unique2(&thing2);
    110     ptr2.Reset(std::move(unique2));
    111     EXPECT_TRUE(ptr1);
    112     EXPECT_EQ(&thing1, ptr1.Get());
    113     EXPECT_TRUE(ptr2);
    114     EXPECT_EQ(&thing2, ptr2.Get());
    115     EXPECT_FALSE(ptr1 == ptr2);
    116     EXPECT_TRUE(ptr1 != ptr2);
    117     EXPECT_EQ(0, thing1.delete_count());
    118     EXPECT_EQ(0, thing2.delete_count());
    119   }
    120   EXPECT_EQ(1, thing1.delete_count());
    121   EXPECT_EQ(1, thing2.delete_count());
    122 }
    123 
    124 TEST(WeakPtr, DeleteObject) {
    125   PseudoDeletable thing;
    126   {
    127     UniqueTestPtr unique(&thing);
    128     WeakTestPtr ptr1(std::move(unique));
    129     WeakTestPtr ptr2 = ptr1;
    130     ptr1.DeleteObject();
    131     EXPECT_FALSE(ptr1);
    132     EXPECT_EQ(nullptr, ptr1.Get());
    133     EXPECT_FALSE(ptr2);
    134     EXPECT_EQ(nullptr, ptr2.Get());
    135     EXPECT_FALSE(ptr1 == ptr2);
    136     EXPECT_TRUE(ptr1 != ptr2);
    137     EXPECT_EQ(1, thing.delete_count());
    138   }
    139   EXPECT_EQ(1, thing.delete_count());
    140 }
    141 
    142 TEST(WeakPtr, Cyclic) {
    143   PseudoDeletable thing1;
    144   PseudoDeletable thing2;
    145   {
    146     UniqueTestPtr unique1(&thing1);
    147     UniqueTestPtr unique2(&thing2);
    148     WeakTestPtr ptr1(std::move(unique1));
    149     WeakTestPtr ptr2(std::move(unique2));
    150     ptr1->SetNext(ptr2);
    151     ptr2->SetNext(ptr1);
    152   }
    153   // Leaks without explicit clear.
    154   EXPECT_EQ(0, thing1.delete_count());
    155   EXPECT_EQ(0, thing2.delete_count());
    156 }
    157 
    158 TEST(WeakPtr, CyclicDeleteObject) {
    159   PseudoDeletable thing1;
    160   PseudoDeletable thing2;
    161   {
    162     UniqueTestPtr unique1(&thing1);
    163     UniqueTestPtr unique2(&thing2);
    164     WeakTestPtr ptr1(std::move(unique1));
    165     WeakTestPtr ptr2(std::move(unique2));
    166     ptr1->SetNext(ptr2);
    167     ptr2->SetNext(ptr1);
    168     ptr1.DeleteObject();
    169     EXPECT_EQ(1, thing1.delete_count());
    170     EXPECT_EQ(0, thing2.delete_count());
    171   }
    172   EXPECT_EQ(1, thing1.delete_count());
    173   EXPECT_EQ(1, thing2.delete_count());
    174 }
    175 
    176 }  // namespace fxcrt
    177