1 // Copyright (c) 2012 The Chromium 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 "base/memory/ref_counted.h" 6 7 #include "base/test/opaque_ref_counted.h" 8 #include "testing/gtest/include/gtest/gtest.h" 9 10 namespace { 11 12 class SelfAssign : public base::RefCounted<SelfAssign> { 13 protected: 14 virtual ~SelfAssign() {} 15 16 private: 17 friend class base::RefCounted<SelfAssign>; 18 }; 19 20 class Derived : public SelfAssign { 21 protected: 22 ~Derived() override {} 23 24 private: 25 friend class base::RefCounted<Derived>; 26 }; 27 28 class CheckDerivedMemberAccess : public scoped_refptr<SelfAssign> { 29 public: 30 CheckDerivedMemberAccess() { 31 // This shouldn't compile if we don't have access to the member variable. 32 SelfAssign** pptr = &ptr_; 33 EXPECT_EQ(*pptr, ptr_); 34 } 35 }; 36 37 class ScopedRefPtrToSelf : public base::RefCounted<ScopedRefPtrToSelf> { 38 public: 39 ScopedRefPtrToSelf() : self_ptr_(this) {} 40 41 static bool was_destroyed() { return was_destroyed_; } 42 43 static void reset_was_destroyed() { was_destroyed_ = false; } 44 45 scoped_refptr<ScopedRefPtrToSelf> self_ptr_; 46 47 private: 48 friend class base::RefCounted<ScopedRefPtrToSelf>; 49 ~ScopedRefPtrToSelf() { was_destroyed_ = true; } 50 51 static bool was_destroyed_; 52 }; 53 54 bool ScopedRefPtrToSelf::was_destroyed_ = false; 55 56 class ScopedRefPtrCountBase : public base::RefCounted<ScopedRefPtrCountBase> { 57 public: 58 ScopedRefPtrCountBase() { ++constructor_count_; } 59 60 static int constructor_count() { return constructor_count_; } 61 62 static int destructor_count() { return destructor_count_; } 63 64 static void reset_count() { 65 constructor_count_ = 0; 66 destructor_count_ = 0; 67 } 68 69 protected: 70 virtual ~ScopedRefPtrCountBase() { ++destructor_count_; } 71 72 private: 73 friend class base::RefCounted<ScopedRefPtrCountBase>; 74 75 static int constructor_count_; 76 static int destructor_count_; 77 }; 78 79 int ScopedRefPtrCountBase::constructor_count_ = 0; 80 int ScopedRefPtrCountBase::destructor_count_ = 0; 81 82 class ScopedRefPtrCountDerived : public ScopedRefPtrCountBase { 83 public: 84 ScopedRefPtrCountDerived() { ++constructor_count_; } 85 86 static int constructor_count() { return constructor_count_; } 87 88 static int destructor_count() { return destructor_count_; } 89 90 static void reset_count() { 91 constructor_count_ = 0; 92 destructor_count_ = 0; 93 } 94 95 protected: 96 ~ScopedRefPtrCountDerived() override { ++destructor_count_; } 97 98 private: 99 friend class base::RefCounted<ScopedRefPtrCountDerived>; 100 101 static int constructor_count_; 102 static int destructor_count_; 103 }; 104 105 int ScopedRefPtrCountDerived::constructor_count_ = 0; 106 int ScopedRefPtrCountDerived::destructor_count_ = 0; 107 108 class Other : public base::RefCounted<Other> { 109 private: 110 friend class base::RefCounted<Other>; 111 112 ~Other() {} 113 }; 114 115 scoped_refptr<Other> Overloaded(scoped_refptr<Other> other) { 116 return other; 117 } 118 119 scoped_refptr<SelfAssign> Overloaded(scoped_refptr<SelfAssign> self_assign) { 120 return self_assign; 121 } 122 123 124 } // end namespace 125 126 TEST(RefCountedUnitTest, TestSelfAssignment) { 127 SelfAssign* p = new SelfAssign; 128 scoped_refptr<SelfAssign> var(p); 129 var = var; 130 EXPECT_EQ(var.get(), p); 131 } 132 133 TEST(RefCountedUnitTest, ScopedRefPtrMemberAccess) { 134 CheckDerivedMemberAccess check; 135 } 136 137 TEST(RefCountedUnitTest, ScopedRefPtrToSelfPointerAssignment) { 138 ScopedRefPtrToSelf::reset_was_destroyed(); 139 140 ScopedRefPtrToSelf* check = new ScopedRefPtrToSelf(); 141 EXPECT_FALSE(ScopedRefPtrToSelf::was_destroyed()); 142 check->self_ptr_ = nullptr; 143 EXPECT_TRUE(ScopedRefPtrToSelf::was_destroyed()); 144 } 145 146 TEST(RefCountedUnitTest, ScopedRefPtrToSelfMoveAssignment) { 147 ScopedRefPtrToSelf::reset_was_destroyed(); 148 149 ScopedRefPtrToSelf* check = new ScopedRefPtrToSelf(); 150 EXPECT_FALSE(ScopedRefPtrToSelf::was_destroyed()); 151 // Releasing |check->self_ptr_| will delete |check|. 152 // The move assignment operator must assign |check->self_ptr_| first then 153 // release |check->self_ptr_|. 154 check->self_ptr_ = scoped_refptr<ScopedRefPtrToSelf>(); 155 EXPECT_TRUE(ScopedRefPtrToSelf::was_destroyed()); 156 } 157 158 TEST(RefCountedUnitTest, ScopedRefPtrToOpaque) { 159 scoped_refptr<base::OpaqueRefCounted> p = base::MakeOpaqueRefCounted(); 160 base::TestOpaqueRefCounted(p); 161 162 scoped_refptr<base::OpaqueRefCounted> q; 163 q = p; 164 base::TestOpaqueRefCounted(p); 165 base::TestOpaqueRefCounted(q); 166 } 167 168 TEST(RefCountedUnitTest, BooleanTesting) { 169 scoped_refptr<SelfAssign> ptr_to_an_instance = new SelfAssign; 170 EXPECT_TRUE(ptr_to_an_instance); 171 EXPECT_FALSE(!ptr_to_an_instance); 172 173 if (ptr_to_an_instance) { 174 } else { 175 ADD_FAILURE() << "Pointer to an instance should result in true."; 176 } 177 178 if (!ptr_to_an_instance) { // check for operator!(). 179 ADD_FAILURE() << "Pointer to an instance should result in !x being false."; 180 } 181 182 scoped_refptr<SelfAssign> null_ptr; 183 EXPECT_FALSE(null_ptr); 184 EXPECT_TRUE(!null_ptr); 185 186 if (null_ptr) { 187 ADD_FAILURE() << "Null pointer should result in false."; 188 } 189 190 if (!null_ptr) { // check for operator!(). 191 } else { 192 ADD_FAILURE() << "Null pointer should result in !x being true."; 193 } 194 } 195 196 TEST(RefCountedUnitTest, Equality) { 197 scoped_refptr<SelfAssign> p1(new SelfAssign); 198 scoped_refptr<SelfAssign> p2(new SelfAssign); 199 200 EXPECT_EQ(p1, p1); 201 EXPECT_EQ(p2, p2); 202 203 EXPECT_NE(p1, p2); 204 EXPECT_NE(p2, p1); 205 } 206 207 TEST(RefCountedUnitTest, NullptrEquality) { 208 scoped_refptr<SelfAssign> ptr_to_an_instance(new SelfAssign); 209 scoped_refptr<SelfAssign> ptr_to_nullptr; 210 211 EXPECT_NE(nullptr, ptr_to_an_instance); 212 EXPECT_NE(ptr_to_an_instance, nullptr); 213 EXPECT_EQ(nullptr, ptr_to_nullptr); 214 EXPECT_EQ(ptr_to_nullptr, nullptr); 215 } 216 217 TEST(RefCountedUnitTest, ConvertibleEquality) { 218 scoped_refptr<Derived> p1(new Derived); 219 scoped_refptr<SelfAssign> p2; 220 221 EXPECT_NE(p1, p2); 222 EXPECT_NE(p2, p1); 223 224 p2 = p1; 225 226 EXPECT_EQ(p1, p2); 227 EXPECT_EQ(p2, p1); 228 } 229 230 TEST(RefCountedUnitTest, MoveAssignment1) { 231 ScopedRefPtrCountBase::reset_count(); 232 233 { 234 ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase(); 235 scoped_refptr<ScopedRefPtrCountBase> p1(raw); 236 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 237 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 238 239 { 240 scoped_refptr<ScopedRefPtrCountBase> p2; 241 242 p2 = std::move(p1); 243 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 244 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 245 EXPECT_EQ(nullptr, p1.get()); 246 EXPECT_EQ(raw, p2.get()); 247 248 // p2 goes out of scope. 249 } 250 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 251 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count()); 252 253 // p1 goes out of scope. 254 } 255 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 256 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count()); 257 } 258 259 TEST(RefCountedUnitTest, MoveAssignment2) { 260 ScopedRefPtrCountBase::reset_count(); 261 262 { 263 ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase(); 264 scoped_refptr<ScopedRefPtrCountBase> p1; 265 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 266 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 267 268 { 269 scoped_refptr<ScopedRefPtrCountBase> p2(raw); 270 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 271 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 272 273 p1 = std::move(p2); 274 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 275 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 276 EXPECT_EQ(raw, p1.get()); 277 EXPECT_EQ(nullptr, p2.get()); 278 279 // p2 goes out of scope. 280 } 281 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 282 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 283 284 // p1 goes out of scope. 285 } 286 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 287 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count()); 288 } 289 290 TEST(RefCountedUnitTest, MoveAssignmentSameInstance1) { 291 ScopedRefPtrCountBase::reset_count(); 292 293 { 294 ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase(); 295 scoped_refptr<ScopedRefPtrCountBase> p1(raw); 296 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 297 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 298 299 { 300 scoped_refptr<ScopedRefPtrCountBase> p2(p1); 301 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 302 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 303 304 p1 = std::move(p2); 305 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 306 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 307 EXPECT_EQ(raw, p1.get()); 308 EXPECT_EQ(nullptr, p2.get()); 309 310 // p2 goes out of scope. 311 } 312 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 313 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 314 315 // p1 goes out of scope. 316 } 317 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 318 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count()); 319 } 320 321 TEST(RefCountedUnitTest, MoveAssignmentSameInstance2) { 322 ScopedRefPtrCountBase::reset_count(); 323 324 { 325 ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase(); 326 scoped_refptr<ScopedRefPtrCountBase> p1(raw); 327 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 328 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 329 330 { 331 scoped_refptr<ScopedRefPtrCountBase> p2(p1); 332 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 333 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 334 335 p2 = std::move(p1); 336 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 337 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 338 EXPECT_EQ(nullptr, p1.get()); 339 EXPECT_EQ(raw, p2.get()); 340 341 // p2 goes out of scope. 342 } 343 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 344 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count()); 345 346 // p1 goes out of scope. 347 } 348 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 349 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count()); 350 } 351 352 TEST(RefCountedUnitTest, MoveAssignmentDifferentInstances) { 353 ScopedRefPtrCountBase::reset_count(); 354 355 { 356 ScopedRefPtrCountBase *raw1 = new ScopedRefPtrCountBase(); 357 scoped_refptr<ScopedRefPtrCountBase> p1(raw1); 358 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 359 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 360 361 { 362 ScopedRefPtrCountBase *raw2 = new ScopedRefPtrCountBase(); 363 scoped_refptr<ScopedRefPtrCountBase> p2(raw2); 364 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count()); 365 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 366 367 p1 = std::move(p2); 368 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count()); 369 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count()); 370 EXPECT_EQ(raw2, p1.get()); 371 EXPECT_EQ(nullptr, p2.get()); 372 373 // p2 goes out of scope. 374 } 375 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count()); 376 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count()); 377 378 // p1 goes out of scope. 379 } 380 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count()); 381 EXPECT_EQ(2, ScopedRefPtrCountBase::destructor_count()); 382 } 383 384 TEST(RefCountedUnitTest, MoveAssignmentDerived) { 385 ScopedRefPtrCountBase::reset_count(); 386 ScopedRefPtrCountDerived::reset_count(); 387 388 { 389 ScopedRefPtrCountBase *raw1 = new ScopedRefPtrCountBase(); 390 scoped_refptr<ScopedRefPtrCountBase> p1(raw1); 391 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 392 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 393 EXPECT_EQ(0, ScopedRefPtrCountDerived::constructor_count()); 394 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count()); 395 396 { 397 ScopedRefPtrCountDerived *raw2 = new ScopedRefPtrCountDerived(); 398 scoped_refptr<ScopedRefPtrCountDerived> p2(raw2); 399 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count()); 400 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 401 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count()); 402 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count()); 403 404 p1 = std::move(p2); 405 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count()); 406 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count()); 407 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count()); 408 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count()); 409 EXPECT_EQ(raw2, p1.get()); 410 EXPECT_EQ(nullptr, p2.get()); 411 412 // p2 goes out of scope. 413 } 414 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count()); 415 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count()); 416 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count()); 417 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count()); 418 419 // p1 goes out of scope. 420 } 421 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count()); 422 EXPECT_EQ(2, ScopedRefPtrCountBase::destructor_count()); 423 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count()); 424 EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count()); 425 } 426 427 TEST(RefCountedUnitTest, MoveConstructor) { 428 ScopedRefPtrCountBase::reset_count(); 429 430 { 431 ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase(); 432 scoped_refptr<ScopedRefPtrCountBase> p1(raw); 433 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 434 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 435 436 { 437 scoped_refptr<ScopedRefPtrCountBase> p2(std::move(p1)); 438 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 439 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 440 EXPECT_EQ(nullptr, p1.get()); 441 EXPECT_EQ(raw, p2.get()); 442 443 // p2 goes out of scope. 444 } 445 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 446 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count()); 447 448 // p1 goes out of scope. 449 } 450 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 451 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count()); 452 } 453 454 TEST(RefCountedUnitTest, MoveConstructorDerived) { 455 ScopedRefPtrCountBase::reset_count(); 456 ScopedRefPtrCountDerived::reset_count(); 457 458 { 459 ScopedRefPtrCountDerived *raw1 = new ScopedRefPtrCountDerived(); 460 scoped_refptr<ScopedRefPtrCountDerived> p1(raw1); 461 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 462 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 463 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count()); 464 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count()); 465 466 { 467 scoped_refptr<ScopedRefPtrCountBase> p2(std::move(p1)); 468 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 469 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 470 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count()); 471 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count()); 472 EXPECT_EQ(nullptr, p1.get()); 473 EXPECT_EQ(raw1, p2.get()); 474 475 // p2 goes out of scope. 476 } 477 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 478 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count()); 479 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count()); 480 EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count()); 481 482 // p1 goes out of scope. 483 } 484 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 485 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count()); 486 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count()); 487 EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count()); 488 } 489 490 TEST(RefCountedUnitTest, TestOverloadResolutionCopy) { 491 scoped_refptr<Derived> derived(new Derived); 492 scoped_refptr<SelfAssign> expected(derived); 493 EXPECT_EQ(expected, Overloaded(derived)); 494 495 scoped_refptr<Other> other(new Other); 496 EXPECT_EQ(other, Overloaded(other)); 497 } 498 499 TEST(RefCountedUnitTest, TestOverloadResolutionMove) { 500 scoped_refptr<Derived> derived(new Derived); 501 scoped_refptr<SelfAssign> expected(derived); 502 EXPECT_EQ(expected, Overloaded(std::move(derived))); 503 504 scoped_refptr<Other> other(new Other); 505 scoped_refptr<Other> other2(other); 506 EXPECT_EQ(other2, Overloaded(std::move(other))); 507 } 508