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/cfx_weak_ptr.h" 6 7#include <memory> 8#include <utility> 9 10#include "core/fxcrt/fx_memory.h" 11#include "testing/fx_string_testhelpers.h" 12#include "testing/gtest/include/gtest/gtest.h" 13 14namespace { 15 16class PseudoDeletable; 17using WeakPtr = CFX_WeakPtr<PseudoDeletable, ReleaseDeleter<PseudoDeletable>>; 18using UniquePtr = 19 std::unique_ptr<PseudoDeletable, ReleaseDeleter<PseudoDeletable>>; 20 21class PseudoDeletable { 22 public: 23 PseudoDeletable() : delete_count_(0) {} 24 void Release() { 25 ++delete_count_; 26 next_.Reset(); 27 } 28 void SetNext(const WeakPtr& next) { next_ = next; } 29 int delete_count() const { return delete_count_; } 30 31 private: 32 int delete_count_; 33 WeakPtr next_; 34}; 35 36} // namespace 37 38TEST(fxcrt, WeakPtrNull) { 39 WeakPtr ptr1; 40 EXPECT_FALSE(ptr1); 41 42 WeakPtr ptr2; 43 EXPECT_TRUE(ptr1 == ptr2); 44 EXPECT_FALSE(ptr1 != ptr2); 45 46 WeakPtr ptr3(ptr1); 47 EXPECT_TRUE(ptr1 == ptr3); 48 EXPECT_FALSE(ptr1 != ptr3); 49 50 WeakPtr ptr4 = ptr1; 51 EXPECT_TRUE(ptr1 == ptr4); 52 EXPECT_FALSE(ptr1 != ptr4); 53} 54 55TEST(fxcrt, WeakPtrNonNull) { 56 PseudoDeletable thing; 57 EXPECT_EQ(0, thing.delete_count()); 58 { 59 UniquePtr unique(&thing); 60 WeakPtr ptr1(std::move(unique)); 61 EXPECT_TRUE(ptr1); 62 EXPECT_EQ(&thing, ptr1.Get()); 63 64 WeakPtr ptr2; 65 EXPECT_FALSE(ptr1 == ptr2); 66 EXPECT_TRUE(ptr1 != ptr2); 67 { 68 WeakPtr ptr3(ptr1); 69 EXPECT_TRUE(ptr1 == ptr3); 70 EXPECT_FALSE(ptr1 != ptr3); 71 EXPECT_EQ(&thing, ptr3.Get()); 72 { 73 WeakPtr 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 84TEST(fxcrt, WeakPtrResetNull) { 85 PseudoDeletable thing; 86 { 87 UniquePtr unique(&thing); 88 WeakPtr ptr1(std::move(unique)); 89 WeakPtr 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 102TEST(fxcrt, WeakPtrResetNonNull) { 103 PseudoDeletable thing1; 104 PseudoDeletable thing2; 105 { 106 UniquePtr unique1(&thing1); 107 WeakPtr ptr1(std::move(unique1)); 108 WeakPtr ptr2 = ptr1; 109 UniquePtr 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 124TEST(fxcrt, WeakPtrDeleteObject) { 125 PseudoDeletable thing; 126 { 127 UniquePtr unique(&thing); 128 WeakPtr ptr1(std::move(unique)); 129 WeakPtr 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 142TEST(fxcrt, WeakPtrCyclic) { 143 PseudoDeletable thing1; 144 PseudoDeletable thing2; 145 { 146 UniquePtr unique1(&thing1); 147 UniquePtr unique2(&thing2); 148 WeakPtr ptr1(std::move(unique1)); 149 WeakPtr 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 158TEST(fxcrt, WeakPtrCyclicDeleteObject) { 159 PseudoDeletable thing1; 160 PseudoDeletable thing2; 161 { 162 UniquePtr unique1(&thing1); 163 UniquePtr unique2(&thing2); 164 WeakPtr ptr1(std::move(unique1)); 165 WeakPtr 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