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_retain_ptr.h" 6 7 #include <utility> 8 9 #include "testing/fx_string_testhelpers.h" 10 #include "testing/gtest/include/gtest/gtest.h" 11 12 namespace { 13 14 class PseudoRetainable { 15 public: 16 PseudoRetainable() : retain_count_(0), release_count_(0) {} 17 void Retain() { ++retain_count_; } 18 void Release() { ++release_count_; } 19 int retain_count() const { return retain_count_; } 20 int release_count() const { return release_count_; } 21 22 private: 23 int retain_count_; 24 int release_count_; 25 }; 26 27 } // namespace 28 29 TEST(fxcrt, RetainPtrNull) { 30 CFX_RetainPtr<PseudoRetainable> ptr; 31 EXPECT_EQ(nullptr, ptr.Get()); 32 } 33 34 TEST(fxcrt, RetainPtrNormal) { 35 PseudoRetainable obj; 36 { 37 CFX_RetainPtr<PseudoRetainable> ptr(&obj); 38 EXPECT_EQ(&obj, ptr.Get()); 39 EXPECT_EQ(1, obj.retain_count()); 40 EXPECT_EQ(0, obj.release_count()); 41 } 42 EXPECT_EQ(1, obj.retain_count()); 43 EXPECT_EQ(1, obj.release_count()); 44 } 45 46 TEST(fxcrt, RetainPtrCopyCtor) { 47 PseudoRetainable obj; 48 { 49 CFX_RetainPtr<PseudoRetainable> ptr1(&obj); 50 { 51 CFX_RetainPtr<PseudoRetainable> ptr2(ptr1); 52 EXPECT_EQ(2, obj.retain_count()); 53 EXPECT_EQ(0, obj.release_count()); 54 } 55 EXPECT_EQ(2, obj.retain_count()); 56 EXPECT_EQ(1, obj.release_count()); 57 } 58 EXPECT_EQ(2, obj.retain_count()); 59 EXPECT_EQ(2, obj.release_count()); 60 } 61 62 TEST(fxcrt, RetainPtrMoveCtor) { 63 PseudoRetainable obj; 64 { 65 CFX_RetainPtr<PseudoRetainable> ptr1(&obj); 66 { 67 CFX_RetainPtr<PseudoRetainable> ptr2(std::move(ptr1)); 68 EXPECT_EQ(1, obj.retain_count()); 69 EXPECT_EQ(0, obj.release_count()); 70 } 71 EXPECT_EQ(1, obj.retain_count()); 72 EXPECT_EQ(1, obj.release_count()); 73 } 74 EXPECT_EQ(1, obj.retain_count()); 75 EXPECT_EQ(1, obj.release_count()); 76 } 77 78 TEST(fxcrt, RetainPtrResetNull) { 79 PseudoRetainable obj; 80 { 81 CFX_RetainPtr<PseudoRetainable> ptr(&obj); 82 ptr.Reset(); 83 EXPECT_EQ(1, obj.retain_count()); 84 EXPECT_EQ(1, obj.release_count()); 85 } 86 EXPECT_EQ(1, obj.retain_count()); 87 EXPECT_EQ(1, obj.release_count()); 88 } 89 90 TEST(fxcrt, RetainPtrReset) { 91 PseudoRetainable obj1; 92 PseudoRetainable obj2; 93 { 94 CFX_RetainPtr<PseudoRetainable> ptr(&obj1); 95 ptr.Reset(&obj2); 96 EXPECT_EQ(1, obj1.retain_count()); 97 EXPECT_EQ(1, obj1.release_count()); 98 EXPECT_EQ(1, obj2.retain_count()); 99 EXPECT_EQ(0, obj2.release_count()); 100 } 101 EXPECT_EQ(1, obj1.retain_count()); 102 EXPECT_EQ(1, obj1.release_count()); 103 EXPECT_EQ(1, obj2.retain_count()); 104 EXPECT_EQ(1, obj2.release_count()); 105 } 106 107 TEST(fxcrt, RetainPtrSwap) { 108 PseudoRetainable obj1; 109 PseudoRetainable obj2; 110 { 111 CFX_RetainPtr<PseudoRetainable> ptr1(&obj1); 112 { 113 CFX_RetainPtr<PseudoRetainable> ptr2(&obj2); 114 ptr1.Swap(ptr2); 115 EXPECT_EQ(1, obj1.retain_count()); 116 EXPECT_EQ(0, obj1.release_count()); 117 EXPECT_EQ(1, obj2.retain_count()); 118 EXPECT_EQ(0, obj2.release_count()); 119 } 120 EXPECT_EQ(1, obj1.retain_count()); 121 EXPECT_EQ(1, obj1.release_count()); 122 EXPECT_EQ(1, obj2.retain_count()); 123 EXPECT_EQ(0, obj2.release_count()); 124 } 125 EXPECT_EQ(1, obj1.retain_count()); 126 EXPECT_EQ(1, obj1.release_count()); 127 EXPECT_EQ(1, obj2.retain_count()); 128 EXPECT_EQ(1, obj2.release_count()); 129 } 130 131 TEST(fxcrt, RetainPtrLeak) { 132 PseudoRetainable obj; 133 PseudoRetainable* leak; 134 { 135 CFX_RetainPtr<PseudoRetainable> ptr(&obj); 136 leak = ptr.Leak(); 137 EXPECT_EQ(1, obj.retain_count()); 138 EXPECT_EQ(0, obj.release_count()); 139 } 140 EXPECT_EQ(1, obj.retain_count()); 141 EXPECT_EQ(0, obj.release_count()); 142 { 143 CFX_RetainPtr<PseudoRetainable> ptr; 144 ptr.Unleak(leak); 145 EXPECT_EQ(1, obj.retain_count()); 146 EXPECT_EQ(0, obj.release_count()); 147 } 148 EXPECT_EQ(1, obj.retain_count()); 149 EXPECT_EQ(1, obj.release_count()); 150 } 151 152 TEST(fxcrt, RetainPtrSwapNull) { 153 PseudoRetainable obj1; 154 { 155 CFX_RetainPtr<PseudoRetainable> ptr1(&obj1); 156 { 157 CFX_RetainPtr<PseudoRetainable> ptr2; 158 ptr1.Swap(ptr2); 159 EXPECT_FALSE(ptr1); 160 EXPECT_TRUE(ptr2); 161 EXPECT_EQ(1, obj1.retain_count()); 162 EXPECT_EQ(0, obj1.release_count()); 163 } 164 EXPECT_EQ(1, obj1.retain_count()); 165 EXPECT_EQ(1, obj1.release_count()); 166 } 167 EXPECT_EQ(1, obj1.retain_count()); 168 EXPECT_EQ(1, obj1.release_count()); 169 } 170 171 TEST(fxcrt, RetainPtrAssign) { 172 PseudoRetainable obj; 173 { 174 CFX_RetainPtr<PseudoRetainable> ptr(&obj); 175 { 176 CFX_RetainPtr<PseudoRetainable> ptr2; 177 ptr2 = ptr; 178 EXPECT_EQ(2, obj.retain_count()); 179 EXPECT_EQ(0, obj.release_count()); 180 } 181 EXPECT_EQ(2, obj.retain_count()); 182 EXPECT_EQ(1, obj.release_count()); 183 } 184 EXPECT_EQ(2, obj.retain_count()); 185 EXPECT_EQ(2, obj.release_count()); 186 } 187 188 TEST(fxcrt, RetainPtrEquals) { 189 PseudoRetainable obj1; 190 PseudoRetainable obj2; 191 CFX_RetainPtr<PseudoRetainable> null_ptr1; 192 CFX_RetainPtr<PseudoRetainable> obj1_ptr1(&obj1); 193 CFX_RetainPtr<PseudoRetainable> obj2_ptr1(&obj2); 194 { 195 CFX_RetainPtr<PseudoRetainable> null_ptr2; 196 EXPECT_TRUE(null_ptr1 == null_ptr2); 197 198 CFX_RetainPtr<PseudoRetainable> obj1_ptr2(&obj1); 199 EXPECT_TRUE(obj1_ptr1 == obj1_ptr2); 200 201 CFX_RetainPtr<PseudoRetainable> obj2_ptr2(&obj2); 202 EXPECT_TRUE(obj2_ptr1 == obj2_ptr2); 203 } 204 EXPECT_FALSE(null_ptr1 == obj1_ptr1); 205 EXPECT_FALSE(null_ptr1 == obj2_ptr1); 206 EXPECT_FALSE(obj1_ptr1 == obj2_ptr1); 207 } 208 209 TEST(fxcrt, RetainPtrNotEquals) { 210 PseudoRetainable obj1; 211 PseudoRetainable obj2; 212 CFX_RetainPtr<PseudoRetainable> null_ptr1; 213 CFX_RetainPtr<PseudoRetainable> obj1_ptr1(&obj1); 214 CFX_RetainPtr<PseudoRetainable> obj2_ptr1(&obj2); 215 { 216 CFX_RetainPtr<PseudoRetainable> null_ptr2; 217 CFX_RetainPtr<PseudoRetainable> obj1_ptr2(&obj1); 218 CFX_RetainPtr<PseudoRetainable> obj2_ptr2(&obj2); 219 EXPECT_FALSE(null_ptr1 != null_ptr2); 220 EXPECT_FALSE(obj1_ptr1 != obj1_ptr2); 221 EXPECT_FALSE(obj2_ptr1 != obj2_ptr2); 222 } 223 EXPECT_TRUE(null_ptr1 != obj1_ptr1); 224 EXPECT_TRUE(null_ptr1 != obj2_ptr1); 225 EXPECT_TRUE(obj1_ptr1 != obj2_ptr1); 226 } 227 228 TEST(fxcrt, RetainPtrLessThan) { 229 PseudoRetainable objs[2]; 230 CFX_RetainPtr<PseudoRetainable> obj1_ptr(&objs[0]); 231 CFX_RetainPtr<PseudoRetainable> obj2_ptr(&objs[1]); 232 EXPECT_TRUE(obj1_ptr < obj2_ptr); 233 EXPECT_FALSE(obj2_ptr < obj1_ptr); 234 } 235 236 TEST(fxcrt, RetainPtrBool) { 237 PseudoRetainable obj1; 238 CFX_RetainPtr<PseudoRetainable> null_ptr; 239 CFX_RetainPtr<PseudoRetainable> obj1_ptr(&obj1); 240 bool null_bool = !!null_ptr; 241 bool obj1_bool = !!obj1_ptr; 242 EXPECT_FALSE(null_bool); 243 EXPECT_TRUE(obj1_bool); 244 } 245 246 TEST(fxcrt, RetainPtrMakeRetained) { 247 auto ptr = pdfium::MakeRetain<CFX_Retainable>(); 248 EXPECT_TRUE(ptr->HasOneRef()); 249 { 250 CFX_RetainPtr<CFX_Retainable> other = ptr; 251 EXPECT_FALSE(ptr->HasOneRef()); 252 } 253 EXPECT_TRUE(ptr->HasOneRef()); 254 } 255