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