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