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 <type_traits> 8 #include <utility> 9 10 #include "base/test/gtest_util.h" 11 #include "testing/gtest/include/gtest/gtest.h" 12 13 namespace { 14 15 class SelfAssign : public base::RefCounted<SelfAssign> { 16 protected: 17 virtual ~SelfAssign() = default; 18 19 private: 20 friend class base::RefCounted<SelfAssign>; 21 }; 22 23 class Derived : public SelfAssign { 24 protected: 25 ~Derived() override = default; 26 27 private: 28 friend class base::RefCounted<Derived>; 29 }; 30 31 class CheckDerivedMemberAccess : public scoped_refptr<SelfAssign> { 32 public: 33 CheckDerivedMemberAccess() { 34 // This shouldn't compile if we don't have access to the member variable. 35 SelfAssign** pptr = &ptr_; 36 EXPECT_EQ(*pptr, ptr_); 37 } 38 }; 39 40 class ScopedRefPtrToSelf : public base::RefCounted<ScopedRefPtrToSelf> { 41 public: 42 ScopedRefPtrToSelf() : self_ptr_(this) {} 43 44 static bool was_destroyed() { return was_destroyed_; } 45 46 static void reset_was_destroyed() { was_destroyed_ = false; } 47 48 scoped_refptr<ScopedRefPtrToSelf> self_ptr_; 49 50 private: 51 friend class base::RefCounted<ScopedRefPtrToSelf>; 52 ~ScopedRefPtrToSelf() { was_destroyed_ = true; } 53 54 static bool was_destroyed_; 55 }; 56 57 bool ScopedRefPtrToSelf::was_destroyed_ = false; 58 59 class ScopedRefPtrCountBase : public base::RefCounted<ScopedRefPtrCountBase> { 60 public: 61 ScopedRefPtrCountBase() { ++constructor_count_; } 62 63 static int constructor_count() { return constructor_count_; } 64 65 static int destructor_count() { return destructor_count_; } 66 67 static void reset_count() { 68 constructor_count_ = 0; 69 destructor_count_ = 0; 70 } 71 72 protected: 73 virtual ~ScopedRefPtrCountBase() { ++destructor_count_; } 74 75 private: 76 friend class base::RefCounted<ScopedRefPtrCountBase>; 77 78 static int constructor_count_; 79 static int destructor_count_; 80 }; 81 82 int ScopedRefPtrCountBase::constructor_count_ = 0; 83 int ScopedRefPtrCountBase::destructor_count_ = 0; 84 85 class ScopedRefPtrCountDerived : public ScopedRefPtrCountBase { 86 public: 87 ScopedRefPtrCountDerived() { ++constructor_count_; } 88 89 static int constructor_count() { return constructor_count_; } 90 91 static int destructor_count() { return destructor_count_; } 92 93 static void reset_count() { 94 constructor_count_ = 0; 95 destructor_count_ = 0; 96 } 97 98 protected: 99 ~ScopedRefPtrCountDerived() override { ++destructor_count_; } 100 101 private: 102 friend class base::RefCounted<ScopedRefPtrCountDerived>; 103 104 static int constructor_count_; 105 static int destructor_count_; 106 }; 107 108 int ScopedRefPtrCountDerived::constructor_count_ = 0; 109 int ScopedRefPtrCountDerived::destructor_count_ = 0; 110 111 class Other : public base::RefCounted<Other> { 112 private: 113 friend class base::RefCounted<Other>; 114 115 ~Other() = default; 116 }; 117 118 class HasPrivateDestructorWithDeleter; 119 120 struct Deleter { 121 static void Destruct(const HasPrivateDestructorWithDeleter* x); 122 }; 123 124 class HasPrivateDestructorWithDeleter 125 : public base::RefCounted<HasPrivateDestructorWithDeleter, Deleter> { 126 public: 127 HasPrivateDestructorWithDeleter() = default; 128 129 private: 130 friend struct Deleter; 131 ~HasPrivateDestructorWithDeleter() = default; 132 }; 133 134 void Deleter::Destruct(const HasPrivateDestructorWithDeleter* x) { 135 delete x; 136 } 137 138 scoped_refptr<Other> Overloaded(scoped_refptr<Other> other) { 139 return other; 140 } 141 142 scoped_refptr<SelfAssign> Overloaded(scoped_refptr<SelfAssign> self_assign) { 143 return self_assign; 144 } 145 146 class InitialRefCountIsOne : public base::RefCounted<InitialRefCountIsOne> { 147 public: 148 REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE(); 149 150 InitialRefCountIsOne() = default; 151 152 private: 153 friend class base::RefCounted<InitialRefCountIsOne>; 154 ~InitialRefCountIsOne() = default; 155 }; 156 157 // Checks that the scoped_refptr is null before the reference counted object is 158 // destroyed. 159 class CheckRefptrNull : public base::RefCounted<CheckRefptrNull> { 160 public: 161 // Set the last scoped_refptr that will have a reference to this object. 162 void set_scoped_refptr(scoped_refptr<CheckRefptrNull>* ptr) { ptr_ = ptr; } 163 164 protected: 165 virtual ~CheckRefptrNull() { 166 EXPECT_NE(ptr_, nullptr); 167 EXPECT_EQ(ptr_->get(), nullptr); 168 } 169 170 private: 171 friend class base::RefCounted<CheckRefptrNull>; 172 173 scoped_refptr<CheckRefptrNull>* ptr_ = nullptr; 174 }; 175 176 } // end namespace 177 178 TEST(RefCountedUnitTest, TestSelfAssignment) { 179 SelfAssign* p = new SelfAssign; 180 scoped_refptr<SelfAssign> var(p); 181 var = *&var; // The *& defeats Clang's -Wself-assign warning. 182 EXPECT_EQ(var.get(), p); 183 var = std::move(var); 184 EXPECT_EQ(var.get(), p); 185 var.swap(var); 186 EXPECT_EQ(var.get(), p); 187 swap(var, var); 188 EXPECT_EQ(var.get(), p); 189 } 190 191 TEST(RefCountedUnitTest, ScopedRefPtrMemberAccess) { 192 CheckDerivedMemberAccess check; 193 } 194 195 TEST(RefCountedUnitTest, ScopedRefPtrToSelfPointerAssignment) { 196 ScopedRefPtrToSelf::reset_was_destroyed(); 197 198 ScopedRefPtrToSelf* check = new ScopedRefPtrToSelf(); 199 EXPECT_FALSE(ScopedRefPtrToSelf::was_destroyed()); 200 check->self_ptr_ = nullptr; 201 EXPECT_TRUE(ScopedRefPtrToSelf::was_destroyed()); 202 } 203 204 TEST(RefCountedUnitTest, ScopedRefPtrToSelfMoveAssignment) { 205 ScopedRefPtrToSelf::reset_was_destroyed(); 206 207 ScopedRefPtrToSelf* check = new ScopedRefPtrToSelf(); 208 EXPECT_FALSE(ScopedRefPtrToSelf::was_destroyed()); 209 // Releasing |check->self_ptr_| will delete |check|. 210 // The move assignment operator must assign |check->self_ptr_| first then 211 // release |check->self_ptr_|. 212 check->self_ptr_ = scoped_refptr<ScopedRefPtrToSelf>(); 213 EXPECT_TRUE(ScopedRefPtrToSelf::was_destroyed()); 214 } 215 216 TEST(RefCountedUnitTest, BooleanTesting) { 217 scoped_refptr<SelfAssign> ptr_to_an_instance = new SelfAssign; 218 EXPECT_TRUE(ptr_to_an_instance); 219 EXPECT_FALSE(!ptr_to_an_instance); 220 221 if (ptr_to_an_instance) { 222 } else { 223 ADD_FAILURE() << "Pointer to an instance should result in true."; 224 } 225 226 if (!ptr_to_an_instance) { // check for operator!(). 227 ADD_FAILURE() << "Pointer to an instance should result in !x being false."; 228 } 229 230 scoped_refptr<SelfAssign> null_ptr; 231 EXPECT_FALSE(null_ptr); 232 EXPECT_TRUE(!null_ptr); 233 234 if (null_ptr) { 235 ADD_FAILURE() << "Null pointer should result in false."; 236 } 237 238 if (!null_ptr) { // check for operator!(). 239 } else { 240 ADD_FAILURE() << "Null pointer should result in !x being true."; 241 } 242 } 243 244 TEST(RefCountedUnitTest, Equality) { 245 scoped_refptr<SelfAssign> p1(new SelfAssign); 246 scoped_refptr<SelfAssign> p2(new SelfAssign); 247 248 EXPECT_EQ(p1, p1); 249 EXPECT_EQ(p2, p2); 250 251 EXPECT_NE(p1, p2); 252 EXPECT_NE(p2, p1); 253 } 254 255 TEST(RefCountedUnitTest, NullptrEquality) { 256 scoped_refptr<SelfAssign> ptr_to_an_instance(new SelfAssign); 257 scoped_refptr<SelfAssign> ptr_to_nullptr; 258 259 EXPECT_NE(nullptr, ptr_to_an_instance); 260 EXPECT_NE(ptr_to_an_instance, nullptr); 261 EXPECT_EQ(nullptr, ptr_to_nullptr); 262 EXPECT_EQ(ptr_to_nullptr, nullptr); 263 } 264 265 TEST(RefCountedUnitTest, ConvertibleEquality) { 266 scoped_refptr<Derived> p1(new Derived); 267 scoped_refptr<SelfAssign> p2; 268 269 EXPECT_NE(p1, p2); 270 EXPECT_NE(p2, p1); 271 272 p2 = p1; 273 274 EXPECT_EQ(p1, p2); 275 EXPECT_EQ(p2, p1); 276 } 277 278 TEST(RefCountedUnitTest, MoveAssignment1) { 279 ScopedRefPtrCountBase::reset_count(); 280 281 { 282 ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase(); 283 scoped_refptr<ScopedRefPtrCountBase> p1(raw); 284 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 285 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 286 287 { 288 scoped_refptr<ScopedRefPtrCountBase> p2; 289 290 p2 = std::move(p1); 291 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 292 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 293 EXPECT_EQ(nullptr, p1.get()); 294 EXPECT_EQ(raw, p2.get()); 295 296 // p2 goes out of scope. 297 } 298 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 299 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count()); 300 301 // p1 goes out of scope. 302 } 303 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 304 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count()); 305 } 306 307 TEST(RefCountedUnitTest, MoveAssignment2) { 308 ScopedRefPtrCountBase::reset_count(); 309 310 { 311 ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase(); 312 scoped_refptr<ScopedRefPtrCountBase> p1; 313 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 314 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 315 316 { 317 scoped_refptr<ScopedRefPtrCountBase> p2(raw); 318 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 319 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 320 321 p1 = std::move(p2); 322 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 323 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 324 EXPECT_EQ(raw, p1.get()); 325 EXPECT_EQ(nullptr, p2.get()); 326 327 // p2 goes out of scope. 328 } 329 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 330 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 331 332 // p1 goes out of scope. 333 } 334 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 335 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count()); 336 } 337 338 TEST(RefCountedUnitTest, MoveAssignmentSameInstance1) { 339 ScopedRefPtrCountBase::reset_count(); 340 341 { 342 ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase(); 343 scoped_refptr<ScopedRefPtrCountBase> p1(raw); 344 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 345 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 346 347 { 348 scoped_refptr<ScopedRefPtrCountBase> p2(p1); 349 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 350 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 351 352 p1 = std::move(p2); 353 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 354 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 355 EXPECT_EQ(raw, p1.get()); 356 EXPECT_EQ(nullptr, p2.get()); 357 358 // p2 goes out of scope. 359 } 360 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 361 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 362 363 // p1 goes out of scope. 364 } 365 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 366 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count()); 367 } 368 369 TEST(RefCountedUnitTest, MoveAssignmentSameInstance2) { 370 ScopedRefPtrCountBase::reset_count(); 371 372 { 373 ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase(); 374 scoped_refptr<ScopedRefPtrCountBase> p1(raw); 375 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 376 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 377 378 { 379 scoped_refptr<ScopedRefPtrCountBase> p2(p1); 380 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 381 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 382 383 p2 = std::move(p1); 384 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 385 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 386 EXPECT_EQ(nullptr, p1.get()); 387 EXPECT_EQ(raw, p2.get()); 388 389 // p2 goes out of scope. 390 } 391 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 392 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count()); 393 394 // p1 goes out of scope. 395 } 396 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 397 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count()); 398 } 399 400 TEST(RefCountedUnitTest, MoveAssignmentDifferentInstances) { 401 ScopedRefPtrCountBase::reset_count(); 402 403 { 404 ScopedRefPtrCountBase *raw1 = new ScopedRefPtrCountBase(); 405 scoped_refptr<ScopedRefPtrCountBase> p1(raw1); 406 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 407 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 408 409 { 410 ScopedRefPtrCountBase *raw2 = new ScopedRefPtrCountBase(); 411 scoped_refptr<ScopedRefPtrCountBase> p2(raw2); 412 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count()); 413 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 414 415 p1 = std::move(p2); 416 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count()); 417 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count()); 418 EXPECT_EQ(raw2, p1.get()); 419 EXPECT_EQ(nullptr, p2.get()); 420 421 // p2 goes out of scope. 422 } 423 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count()); 424 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count()); 425 426 // p1 goes out of scope. 427 } 428 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count()); 429 EXPECT_EQ(2, ScopedRefPtrCountBase::destructor_count()); 430 } 431 432 TEST(RefCountedUnitTest, MoveAssignmentSelfMove) { 433 ScopedRefPtrCountBase::reset_count(); 434 435 { 436 ScopedRefPtrCountBase* raw = new ScopedRefPtrCountBase; 437 scoped_refptr<ScopedRefPtrCountBase> p1(raw); 438 scoped_refptr<ScopedRefPtrCountBase>& p1_ref = p1; 439 440 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 441 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 442 443 p1 = std::move(p1_ref); 444 445 // |p1| is "valid but unspecified", so don't bother inspecting its 446 // contents, just ensure that we don't crash. 447 } 448 449 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 450 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count()); 451 } 452 453 TEST(RefCountedUnitTest, MoveAssignmentDerived) { 454 ScopedRefPtrCountBase::reset_count(); 455 ScopedRefPtrCountDerived::reset_count(); 456 457 { 458 ScopedRefPtrCountBase *raw1 = new ScopedRefPtrCountBase(); 459 scoped_refptr<ScopedRefPtrCountBase> p1(raw1); 460 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 461 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 462 EXPECT_EQ(0, ScopedRefPtrCountDerived::constructor_count()); 463 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count()); 464 465 { 466 ScopedRefPtrCountDerived *raw2 = new ScopedRefPtrCountDerived(); 467 scoped_refptr<ScopedRefPtrCountDerived> p2(raw2); 468 EXPECT_EQ(2, 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 473 p1 = std::move(p2); 474 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count()); 475 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count()); 476 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count()); 477 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count()); 478 EXPECT_EQ(raw2, p1.get()); 479 EXPECT_EQ(nullptr, p2.get()); 480 481 // p2 goes out of scope. 482 } 483 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count()); 484 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count()); 485 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count()); 486 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count()); 487 488 // p1 goes out of scope. 489 } 490 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count()); 491 EXPECT_EQ(2, ScopedRefPtrCountBase::destructor_count()); 492 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count()); 493 EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count()); 494 } 495 496 TEST(RefCountedUnitTest, MoveConstructor) { 497 ScopedRefPtrCountBase::reset_count(); 498 499 { 500 ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase(); 501 scoped_refptr<ScopedRefPtrCountBase> p1(raw); 502 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 503 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 504 505 { 506 scoped_refptr<ScopedRefPtrCountBase> p2(std::move(p1)); 507 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 508 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 509 EXPECT_EQ(nullptr, p1.get()); 510 EXPECT_EQ(raw, p2.get()); 511 512 // p2 goes out of scope. 513 } 514 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 515 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count()); 516 517 // p1 goes out of scope. 518 } 519 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 520 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count()); 521 } 522 523 TEST(RefCountedUnitTest, MoveConstructorDerived) { 524 ScopedRefPtrCountBase::reset_count(); 525 ScopedRefPtrCountDerived::reset_count(); 526 527 { 528 ScopedRefPtrCountDerived *raw1 = new ScopedRefPtrCountDerived(); 529 scoped_refptr<ScopedRefPtrCountDerived> p1(raw1); 530 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 531 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 532 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count()); 533 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count()); 534 535 { 536 scoped_refptr<ScopedRefPtrCountBase> p2(std::move(p1)); 537 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 538 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); 539 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count()); 540 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count()); 541 EXPECT_EQ(nullptr, p1.get()); 542 EXPECT_EQ(raw1, p2.get()); 543 544 // p2 goes out of scope. 545 } 546 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 547 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count()); 548 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count()); 549 EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count()); 550 551 // p1 goes out of scope. 552 } 553 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); 554 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count()); 555 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count()); 556 EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count()); 557 } 558 559 TEST(RefCountedUnitTest, TestOverloadResolutionCopy) { 560 const scoped_refptr<Derived> derived(new Derived); 561 const scoped_refptr<SelfAssign> expected(derived); 562 EXPECT_EQ(expected, Overloaded(derived)); 563 564 const scoped_refptr<Other> other(new Other); 565 EXPECT_EQ(other, Overloaded(other)); 566 } 567 568 TEST(RefCountedUnitTest, TestOverloadResolutionMove) { 569 scoped_refptr<Derived> derived(new Derived); 570 const scoped_refptr<SelfAssign> expected(derived); 571 EXPECT_EQ(expected, Overloaded(std::move(derived))); 572 573 scoped_refptr<Other> other(new Other); 574 const scoped_refptr<Other> other2(other); 575 EXPECT_EQ(other2, Overloaded(std::move(other))); 576 } 577 578 TEST(RefCountedUnitTest, TestMakeRefCounted) { 579 scoped_refptr<Derived> derived = new Derived; 580 EXPECT_TRUE(derived->HasOneRef()); 581 derived.reset(); 582 583 scoped_refptr<Derived> derived2 = base::MakeRefCounted<Derived>(); 584 EXPECT_TRUE(derived2->HasOneRef()); 585 derived2.reset(); 586 } 587 588 TEST(RefCountedUnitTest, TestInitialRefCountIsOne) { 589 scoped_refptr<InitialRefCountIsOne> obj = 590 base::MakeRefCounted<InitialRefCountIsOne>(); 591 EXPECT_TRUE(obj->HasOneRef()); 592 obj.reset(); 593 594 scoped_refptr<InitialRefCountIsOne> obj2 = 595 base::AdoptRef(new InitialRefCountIsOne); 596 EXPECT_TRUE(obj2->HasOneRef()); 597 obj2.reset(); 598 599 scoped_refptr<Other> obj3 = base::MakeRefCounted<Other>(); 600 EXPECT_TRUE(obj3->HasOneRef()); 601 obj3.reset(); 602 } 603 604 TEST(RefCountedUnitTest, TestPrivateDestructorWithDeleter) { 605 // Ensure that RefCounted doesn't need the access to the pointee dtor when 606 // a custom deleter is given. 607 scoped_refptr<HasPrivateDestructorWithDeleter> obj = 608 base::MakeRefCounted<HasPrivateDestructorWithDeleter>(); 609 } 610 611 TEST(RefCountedUnitTest, TestReset) { 612 ScopedRefPtrCountBase::reset_count(); 613 614 // Create ScopedRefPtrCountBase that is referenced by |obj1| and |obj2|. 615 scoped_refptr<ScopedRefPtrCountBase> obj1 = 616 base::MakeRefCounted<ScopedRefPtrCountBase>(); 617 scoped_refptr<ScopedRefPtrCountBase> obj2 = obj1; 618 EXPECT_NE(obj1.get(), nullptr); 619 EXPECT_NE(obj2.get(), nullptr); 620 EXPECT_EQ(ScopedRefPtrCountBase::constructor_count(), 1); 621 EXPECT_EQ(ScopedRefPtrCountBase::destructor_count(), 0); 622 623 // Check that calling reset() on |obj1| resets it. |obj2| still has a 624 // reference to the ScopedRefPtrCountBase so it shouldn't be reset. 625 obj1.reset(); 626 EXPECT_EQ(obj1.get(), nullptr); 627 EXPECT_EQ(ScopedRefPtrCountBase::constructor_count(), 1); 628 EXPECT_EQ(ScopedRefPtrCountBase::destructor_count(), 0); 629 630 // Check that calling reset() on |obj2| resets it and causes the deletion of 631 // the ScopedRefPtrCountBase. 632 obj2.reset(); 633 EXPECT_EQ(obj2.get(), nullptr); 634 EXPECT_EQ(ScopedRefPtrCountBase::constructor_count(), 1); 635 EXPECT_EQ(ScopedRefPtrCountBase::destructor_count(), 1); 636 } 637 638 TEST(RefCountedUnitTest, TestResetAlreadyNull) { 639 // Check that calling reset() on a null scoped_refptr does nothing. 640 scoped_refptr<ScopedRefPtrCountBase> obj; 641 obj.reset(); 642 // |obj| should still be null after calling reset(). 643 EXPECT_EQ(obj.get(), nullptr); 644 } 645 646 TEST(RefCountedUnitTest, CheckScopedRefptrNullBeforeObjectDestruction) { 647 scoped_refptr<CheckRefptrNull> obj = base::MakeRefCounted<CheckRefptrNull>(); 648 obj->set_scoped_refptr(&obj); 649 650 // Check that when reset() is called the scoped_refptr internal pointer is set 651 // to null before the reference counted object is destroyed. This check is 652 // done by the CheckRefptrNull destructor. 653 obj.reset(); 654 EXPECT_EQ(obj.get(), nullptr); 655 } 656 657 TEST(RefCountedDeathTest, TestAdoptRef) { 658 // Check that WrapRefCounted() DCHECKs if passed a type that defines 659 // REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE. 660 EXPECT_DCHECK_DEATH(base::WrapRefCounted(new InitialRefCountIsOne)); 661 662 // Check that AdoptRef() DCHECKs if passed a nullptr. 663 InitialRefCountIsOne* ptr = nullptr; 664 EXPECT_DCHECK_DEATH(base::AdoptRef(ptr)); 665 666 // Check that AdoptRef() DCHECKs if passed an object that doesn't need to be 667 // adopted. 668 scoped_refptr<InitialRefCountIsOne> obj = 669 base::MakeRefCounted<InitialRefCountIsOne>(); 670 EXPECT_DCHECK_DEATH(base::AdoptRef(obj.get())); 671 } 672