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/scoped_ptr.h" 6 7 #include <stddef.h> 8 9 #include <sstream> 10 11 #include <gtest/gtest.h> 12 13 #include "base/bind.h" 14 #include "base/callback.h" 15 #include "base/macros.h" 16 #include "build/build_config.h" 17 18 namespace { 19 20 // Used to test depth subtyping. 21 class ConDecLoggerParent { 22 public: 23 virtual ~ConDecLoggerParent() {} 24 25 virtual void SetPtr(int* ptr) = 0; 26 27 virtual int SomeMeth(int x) const = 0; 28 }; 29 30 class ConDecLogger : public ConDecLoggerParent { 31 public: 32 ConDecLogger() : ptr_(NULL) { } 33 explicit ConDecLogger(int* ptr) { SetPtr(ptr); } 34 ~ConDecLogger() override { --*ptr_; } 35 36 void SetPtr(int* ptr) override { 37 ptr_ = ptr; 38 ++*ptr_; 39 } 40 41 int SomeMeth(int x) const override { return x; } 42 43 private: 44 int* ptr_; 45 46 DISALLOW_COPY_AND_ASSIGN(ConDecLogger); 47 }; 48 49 struct CountingDeleter { 50 explicit CountingDeleter(int* count) : count_(count) {} 51 inline void operator()(double* ptr) const { 52 (*count_)++; 53 } 54 int* count_; 55 }; 56 57 // Used to test assignment of convertible deleters. 58 struct CountingDeleterChild : public CountingDeleter { 59 explicit CountingDeleterChild(int* count) : CountingDeleter(count) {} 60 }; 61 62 class OverloadedNewAndDelete { 63 public: 64 void* operator new(size_t size) { 65 g_new_count++; 66 return malloc(size); 67 } 68 69 void operator delete(void* ptr) { 70 g_delete_count++; 71 free(ptr); 72 } 73 74 static void ResetCounters() { 75 g_new_count = 0; 76 g_delete_count = 0; 77 } 78 79 static int new_count() { return g_new_count; } 80 static int delete_count() { return g_delete_count; } 81 82 private: 83 static int g_new_count; 84 static int g_delete_count; 85 }; 86 87 int OverloadedNewAndDelete::g_new_count = 0; 88 int OverloadedNewAndDelete::g_delete_count = 0; 89 90 scoped_ptr<ConDecLogger> PassThru(scoped_ptr<ConDecLogger> logger) { 91 return logger; 92 } 93 94 void GrabAndDrop(scoped_ptr<ConDecLogger> logger) { 95 } 96 97 // Do not delete this function! It's existence is to test that you can 98 // return a temporarily constructed version of the scoper. 99 scoped_ptr<ConDecLogger> TestReturnOfType(int* constructed) { 100 return scoped_ptr<ConDecLogger>(new ConDecLogger(constructed)); 101 } 102 103 } // namespace 104 105 TEST(ScopedPtrTest, ScopedPtr) { 106 int constructed = 0; 107 108 // Ensure size of scoped_ptr<> doesn't increase unexpectedly. 109 static_assert(sizeof(int*) >= sizeof(scoped_ptr<int>), 110 "scoped_ptr shouldn't be larger than the raw pointer"); 111 112 { 113 scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed)); 114 EXPECT_EQ(1, constructed); 115 EXPECT_TRUE(scoper.get()); 116 117 EXPECT_EQ(10, scoper->SomeMeth(10)); 118 EXPECT_EQ(10, scoper.get()->SomeMeth(10)); 119 EXPECT_EQ(10, (*scoper).SomeMeth(10)); 120 } 121 EXPECT_EQ(0, constructed); 122 123 // Test reset() and release() 124 { 125 scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed)); 126 EXPECT_EQ(1, constructed); 127 EXPECT_TRUE(scoper.get()); 128 129 scoper.reset(new ConDecLogger(&constructed)); 130 EXPECT_EQ(1, constructed); 131 EXPECT_TRUE(scoper.get()); 132 133 scoper.reset(); 134 EXPECT_EQ(0, constructed); 135 EXPECT_FALSE(scoper.get()); 136 137 scoper.reset(new ConDecLogger(&constructed)); 138 EXPECT_EQ(1, constructed); 139 EXPECT_TRUE(scoper.get()); 140 141 ConDecLogger* take = scoper.release(); 142 EXPECT_EQ(1, constructed); 143 EXPECT_FALSE(scoper.get()); 144 delete take; 145 EXPECT_EQ(0, constructed); 146 147 scoper.reset(new ConDecLogger(&constructed)); 148 EXPECT_EQ(1, constructed); 149 EXPECT_TRUE(scoper.get()); 150 } 151 EXPECT_EQ(0, constructed); 152 153 // Test swap(). 154 { 155 scoped_ptr<ConDecLogger> scoper1; 156 scoped_ptr<ConDecLogger> scoper2; 157 EXPECT_TRUE(scoper1.get() == scoper2.get()); 158 EXPECT_FALSE(scoper1.get() != scoper2.get()); 159 160 ConDecLogger* logger = new ConDecLogger(&constructed); 161 scoper1.reset(logger); 162 EXPECT_EQ(logger, scoper1.get()); 163 EXPECT_FALSE(scoper2.get()); 164 EXPECT_FALSE(scoper1.get() == scoper2.get()); 165 EXPECT_TRUE(scoper1.get() != scoper2.get()); 166 167 scoper2.swap(scoper1); 168 EXPECT_EQ(logger, scoper2.get()); 169 EXPECT_FALSE(scoper1.get()); 170 EXPECT_FALSE(scoper1.get() == scoper2.get()); 171 EXPECT_TRUE(scoper1.get() != scoper2.get()); 172 } 173 EXPECT_EQ(0, constructed); 174 } 175 176 TEST(ScopedPtrTest, ScopedPtrDepthSubtyping) { 177 int constructed = 0; 178 179 // Test construction from a scoped_ptr to a derived class. 180 { 181 scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed)); 182 EXPECT_EQ(1, constructed); 183 EXPECT_TRUE(scoper.get()); 184 185 scoped_ptr<ConDecLoggerParent> scoper_parent(std::move(scoper)); 186 EXPECT_EQ(1, constructed); 187 EXPECT_TRUE(scoper_parent.get()); 188 EXPECT_FALSE(scoper.get()); 189 190 EXPECT_EQ(10, scoper_parent->SomeMeth(10)); 191 EXPECT_EQ(10, scoper_parent.get()->SomeMeth(10)); 192 EXPECT_EQ(10, (*scoper_parent).SomeMeth(10)); 193 } 194 EXPECT_EQ(0, constructed); 195 196 // Test assignment from a scoped_ptr to a derived class. 197 { 198 scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed)); 199 EXPECT_EQ(1, constructed); 200 EXPECT_TRUE(scoper.get()); 201 202 scoped_ptr<ConDecLoggerParent> scoper_parent; 203 scoper_parent = std::move(scoper); 204 EXPECT_EQ(1, constructed); 205 EXPECT_TRUE(scoper_parent.get()); 206 EXPECT_FALSE(scoper.get()); 207 } 208 EXPECT_EQ(0, constructed); 209 210 // Test construction of a scoped_ptr with an additional const annotation. 211 { 212 scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed)); 213 EXPECT_EQ(1, constructed); 214 EXPECT_TRUE(scoper.get()); 215 216 scoped_ptr<const ConDecLogger> scoper_const(std::move(scoper)); 217 EXPECT_EQ(1, constructed); 218 EXPECT_TRUE(scoper_const.get()); 219 EXPECT_FALSE(scoper.get()); 220 221 EXPECT_EQ(10, scoper_const->SomeMeth(10)); 222 EXPECT_EQ(10, scoper_const.get()->SomeMeth(10)); 223 EXPECT_EQ(10, (*scoper_const).SomeMeth(10)); 224 } 225 EXPECT_EQ(0, constructed); 226 227 // Test assignment to a scoped_ptr with an additional const annotation. 228 { 229 scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed)); 230 EXPECT_EQ(1, constructed); 231 EXPECT_TRUE(scoper.get()); 232 233 scoped_ptr<const ConDecLogger> scoper_const; 234 scoper_const = std::move(scoper); 235 EXPECT_EQ(1, constructed); 236 EXPECT_TRUE(scoper_const.get()); 237 EXPECT_FALSE(scoper.get()); 238 } 239 EXPECT_EQ(0, constructed); 240 241 // Test assignment to a scoped_ptr deleter of parent type. 242 { 243 // Custom deleters never touch these value. 244 double dummy_value, dummy_value2; 245 int deletes = 0; 246 int alternate_deletes = 0; 247 scoped_ptr<double, CountingDeleter> scoper(&dummy_value, 248 CountingDeleter(&deletes)); 249 scoped_ptr<double, CountingDeleterChild> scoper_child( 250 &dummy_value2, CountingDeleterChild(&alternate_deletes)); 251 252 EXPECT_TRUE(scoper); 253 EXPECT_TRUE(scoper_child); 254 EXPECT_EQ(0, deletes); 255 EXPECT_EQ(0, alternate_deletes); 256 257 // Test this compiles and correctly overwrites the deleter state. 258 scoper = std::move(scoper_child); 259 EXPECT_TRUE(scoper); 260 EXPECT_FALSE(scoper_child); 261 EXPECT_EQ(1, deletes); 262 EXPECT_EQ(0, alternate_deletes); 263 264 scoper.reset(); 265 EXPECT_FALSE(scoper); 266 EXPECT_FALSE(scoper_child); 267 EXPECT_EQ(1, deletes); 268 EXPECT_EQ(1, alternate_deletes); 269 270 scoper_child.reset(&dummy_value); 271 EXPECT_TRUE(scoper_child); 272 EXPECT_EQ(1, deletes); 273 EXPECT_EQ(1, alternate_deletes); 274 scoped_ptr<double, CountingDeleter> scoper_construct( 275 std::move(scoper_child)); 276 EXPECT_TRUE(scoper_construct); 277 EXPECT_FALSE(scoper_child); 278 EXPECT_EQ(1, deletes); 279 EXPECT_EQ(1, alternate_deletes); 280 281 scoper_construct.reset(); 282 EXPECT_EQ(1, deletes); 283 EXPECT_EQ(2, alternate_deletes); 284 } 285 } 286 287 TEST(ScopedPtrTest, ScopedPtrWithArray) { 288 static const int kNumLoggers = 12; 289 290 int constructed = 0; 291 292 { 293 scoped_ptr<ConDecLogger[]> scoper(new ConDecLogger[kNumLoggers]); 294 EXPECT_TRUE(scoper); 295 EXPECT_EQ(&scoper[0], scoper.get()); 296 for (int i = 0; i < kNumLoggers; ++i) { 297 scoper[i].SetPtr(&constructed); 298 } 299 EXPECT_EQ(12, constructed); 300 301 EXPECT_EQ(10, scoper.get()->SomeMeth(10)); 302 EXPECT_EQ(10, scoper[2].SomeMeth(10)); 303 } 304 EXPECT_EQ(0, constructed); 305 306 // Test reset() and release() 307 { 308 scoped_ptr<ConDecLogger[]> scoper; 309 EXPECT_FALSE(scoper.get()); 310 EXPECT_FALSE(scoper.release()); 311 EXPECT_FALSE(scoper.get()); 312 scoper.reset(); 313 EXPECT_FALSE(scoper.get()); 314 315 scoper.reset(new ConDecLogger[kNumLoggers]); 316 for (int i = 0; i < kNumLoggers; ++i) { 317 scoper[i].SetPtr(&constructed); 318 } 319 EXPECT_EQ(12, constructed); 320 scoper.reset(); 321 EXPECT_EQ(0, constructed); 322 323 scoper.reset(new ConDecLogger[kNumLoggers]); 324 for (int i = 0; i < kNumLoggers; ++i) { 325 scoper[i].SetPtr(&constructed); 326 } 327 EXPECT_EQ(12, constructed); 328 ConDecLogger* ptr = scoper.release(); 329 EXPECT_EQ(12, constructed); 330 delete[] ptr; 331 EXPECT_EQ(0, constructed); 332 } 333 EXPECT_EQ(0, constructed); 334 335 // Test swap() and type-safe Boolean. 336 { 337 scoped_ptr<ConDecLogger[]> scoper1; 338 scoped_ptr<ConDecLogger[]> scoper2; 339 EXPECT_TRUE(scoper1.get() == scoper2.get()); 340 EXPECT_FALSE(scoper1.get() != scoper2.get()); 341 342 ConDecLogger* loggers = new ConDecLogger[kNumLoggers]; 343 for (int i = 0; i < kNumLoggers; ++i) { 344 loggers[i].SetPtr(&constructed); 345 } 346 scoper1.reset(loggers); 347 EXPECT_TRUE(scoper1); 348 EXPECT_EQ(loggers, scoper1.get()); 349 EXPECT_FALSE(scoper2); 350 EXPECT_FALSE(scoper2.get()); 351 EXPECT_FALSE(scoper1.get() == scoper2.get()); 352 EXPECT_TRUE(scoper1.get() != scoper2.get()); 353 354 scoper2.swap(scoper1); 355 EXPECT_EQ(loggers, scoper2.get()); 356 EXPECT_FALSE(scoper1.get()); 357 EXPECT_FALSE(scoper1.get() == scoper2.get()); 358 EXPECT_TRUE(scoper1.get() != scoper2.get()); 359 } 360 EXPECT_EQ(0, constructed); 361 362 { 363 ConDecLogger* loggers = new ConDecLogger[kNumLoggers]; 364 scoped_ptr<ConDecLogger[]> scoper(loggers); 365 EXPECT_TRUE(scoper); 366 for (int i = 0; i < kNumLoggers; ++i) { 367 scoper[i].SetPtr(&constructed); 368 } 369 EXPECT_EQ(kNumLoggers, constructed); 370 371 // Test moving with constructor; 372 scoped_ptr<ConDecLogger[]> scoper2(std::move(scoper)); 373 EXPECT_EQ(kNumLoggers, constructed); 374 375 // Test moving with assignment; 376 scoped_ptr<ConDecLogger[]> scoper3; 377 scoper3 = std::move(scoper2); 378 EXPECT_EQ(kNumLoggers, constructed); 379 EXPECT_FALSE(scoper); 380 EXPECT_FALSE(scoper2); 381 EXPECT_TRUE(scoper3); 382 } 383 EXPECT_EQ(0, constructed); 384 } 385 386 TEST(ScopedPtrTest, MoveBehavior) { 387 int constructed = 0; 388 { 389 ConDecLogger* logger = new ConDecLogger(&constructed); 390 scoped_ptr<ConDecLogger> scoper(logger); 391 EXPECT_EQ(1, constructed); 392 393 // Test moving with constructor; 394 scoped_ptr<ConDecLogger> scoper2(std::move(scoper)); 395 EXPECT_EQ(1, constructed); 396 397 // Test moving with assignment; 398 scoped_ptr<ConDecLogger> scoper3; 399 scoper3 = std::move(scoper2); 400 EXPECT_EQ(1, constructed); 401 EXPECT_FALSE(scoper.get()); 402 EXPECT_FALSE(scoper2.get()); 403 EXPECT_TRUE(scoper3.get()); 404 } 405 406 #if !defined(OS_ANDROID) && !defined(OS_LINUX) 407 // Test uncaught Pass() does not have side effects, because Pass() 408 // is implemented by std::move(). 409 // TODO(danakj): Remove this test case when we remove Pass(). 410 { 411 ConDecLogger* logger = new ConDecLogger(&constructed); 412 scoped_ptr<ConDecLogger> scoper(logger); 413 EXPECT_EQ(1, constructed); 414 415 // Should auto-destruct logger by end of scope. 416 scoped_ptr<ConDecLogger>&& rvalue = scoper.Pass(); 417 // The Pass() function mimics std::move(), which does not have side-effects. 418 EXPECT_TRUE(scoper.get()); 419 EXPECT_TRUE(rvalue); 420 } 421 EXPECT_EQ(0, constructed); 422 #endif 423 424 // Test that passing to function which does nothing does not leak. 425 { 426 ConDecLogger* logger = new ConDecLogger(&constructed); 427 scoped_ptr<ConDecLogger> scoper(logger); 428 EXPECT_EQ(1, constructed); 429 430 // Should auto-destruct logger by end of scope. 431 GrabAndDrop(std::move(scoper)); 432 EXPECT_FALSE(scoper.get()); 433 } 434 EXPECT_EQ(0, constructed); 435 } 436 437 TEST(ScopedPtrTest, ReturnTypeBehavior) { 438 int constructed = 0; 439 440 // Test that we can return a scoped_ptr. 441 { 442 ConDecLogger* logger = new ConDecLogger(&constructed); 443 scoped_ptr<ConDecLogger> scoper(logger); 444 EXPECT_EQ(1, constructed); 445 446 PassThru(std::move(scoper)); 447 EXPECT_FALSE(scoper.get()); 448 } 449 EXPECT_EQ(0, constructed); 450 451 // Test uncaught return type not leak. 452 { 453 ConDecLogger* logger = new ConDecLogger(&constructed); 454 scoped_ptr<ConDecLogger> scoper(logger); 455 EXPECT_EQ(1, constructed); 456 457 // Should auto-destruct logger by end of scope. 458 PassThru(std::move(scoper)); 459 EXPECT_FALSE(scoper.get()); 460 } 461 EXPECT_EQ(0, constructed); 462 463 // Call TestReturnOfType() so the compiler doesn't warn for an unused 464 // function. 465 { 466 TestReturnOfType(&constructed); 467 } 468 EXPECT_EQ(0, constructed); 469 } 470 471 TEST(ScopedPtrTest, CustomDeleter) { 472 double dummy_value; // Custom deleter never touches this value. 473 int deletes = 0; 474 int alternate_deletes = 0; 475 476 // Normal delete support. 477 { 478 deletes = 0; 479 scoped_ptr<double, CountingDeleter> scoper(&dummy_value, 480 CountingDeleter(&deletes)); 481 EXPECT_EQ(0, deletes); 482 EXPECT_TRUE(scoper.get()); 483 } 484 EXPECT_EQ(1, deletes); 485 486 // Test reset() and release(). 487 deletes = 0; 488 { 489 scoped_ptr<double, CountingDeleter> scoper(NULL, 490 CountingDeleter(&deletes)); 491 EXPECT_FALSE(scoper.get()); 492 EXPECT_FALSE(scoper.release()); 493 EXPECT_FALSE(scoper.get()); 494 scoper.reset(); 495 EXPECT_FALSE(scoper.get()); 496 EXPECT_EQ(0, deletes); 497 498 scoper.reset(&dummy_value); 499 scoper.reset(); 500 EXPECT_EQ(1, deletes); 501 502 scoper.reset(&dummy_value); 503 EXPECT_EQ(&dummy_value, scoper.release()); 504 } 505 EXPECT_EQ(1, deletes); 506 507 // Test get_deleter(). 508 deletes = 0; 509 alternate_deletes = 0; 510 { 511 scoped_ptr<double, CountingDeleter> scoper(&dummy_value, 512 CountingDeleter(&deletes)); 513 // Call deleter manually. 514 EXPECT_EQ(0, deletes); 515 scoper.get_deleter()(&dummy_value); 516 EXPECT_EQ(1, deletes); 517 518 // Deleter is still there after reset. 519 scoper.reset(); 520 EXPECT_EQ(2, deletes); 521 scoper.get_deleter()(&dummy_value); 522 EXPECT_EQ(3, deletes); 523 524 // Deleter can be assigned into (matches C++11 unique_ptr<> spec). 525 scoper.get_deleter() = CountingDeleter(&alternate_deletes); 526 scoper.reset(&dummy_value); 527 EXPECT_EQ(0, alternate_deletes); 528 529 } 530 EXPECT_EQ(3, deletes); 531 EXPECT_EQ(1, alternate_deletes); 532 533 // Test operator= deleter support. 534 deletes = 0; 535 alternate_deletes = 0; 536 { 537 double dummy_value2; 538 scoped_ptr<double, CountingDeleter> scoper(&dummy_value, 539 CountingDeleter(&deletes)); 540 scoped_ptr<double, CountingDeleter> scoper2( 541 &dummy_value2, 542 CountingDeleter(&alternate_deletes)); 543 EXPECT_EQ(0, deletes); 544 EXPECT_EQ(0, alternate_deletes); 545 546 // Pass the second deleter through a constructor and an operator=. Then 547 // reinitialize the empty scopers to ensure that each one is deleting 548 // properly. 549 scoped_ptr<double, CountingDeleter> scoper3(std::move(scoper2)); 550 scoper = std::move(scoper3); 551 EXPECT_EQ(1, deletes); 552 553 scoper2.reset(&dummy_value2); 554 scoper3.reset(&dummy_value2); 555 EXPECT_EQ(0, alternate_deletes); 556 557 } 558 EXPECT_EQ(1, deletes); 559 EXPECT_EQ(3, alternate_deletes); 560 561 // Test swap(), and type-safe Boolean. 562 { 563 scoped_ptr<double, CountingDeleter> scoper1(NULL, 564 CountingDeleter(&deletes)); 565 scoped_ptr<double, CountingDeleter> scoper2(NULL, 566 CountingDeleter(&deletes)); 567 EXPECT_TRUE(scoper1.get() == scoper2.get()); 568 EXPECT_FALSE(scoper1.get() != scoper2.get()); 569 570 scoper1.reset(&dummy_value); 571 EXPECT_TRUE(scoper1); 572 EXPECT_EQ(&dummy_value, scoper1.get()); 573 EXPECT_FALSE(scoper2); 574 EXPECT_FALSE(scoper2.get()); 575 EXPECT_FALSE(scoper1.get() == scoper2.get()); 576 EXPECT_TRUE(scoper1.get() != scoper2.get()); 577 578 scoper2.swap(scoper1); 579 EXPECT_EQ(&dummy_value, scoper2.get()); 580 EXPECT_FALSE(scoper1.get()); 581 EXPECT_FALSE(scoper1.get() == scoper2.get()); 582 EXPECT_TRUE(scoper1.get() != scoper2.get()); 583 } 584 } 585 586 // Sanity check test for overloaded new and delete operators. Does not do full 587 // coverage of reset/release/move operations as that is redundant with the 588 // above. 589 TEST(ScopedPtrTest, OverloadedNewAndDelete) { 590 { 591 OverloadedNewAndDelete::ResetCounters(); 592 scoped_ptr<OverloadedNewAndDelete> scoper(new OverloadedNewAndDelete()); 593 EXPECT_TRUE(scoper.get()); 594 595 scoped_ptr<OverloadedNewAndDelete> scoper2(std::move(scoper)); 596 } 597 EXPECT_EQ(1, OverloadedNewAndDelete::delete_count()); 598 EXPECT_EQ(1, OverloadedNewAndDelete::new_count()); 599 } 600 601 scoped_ptr<int> NullIntReturn() { 602 return nullptr; 603 } 604 605 TEST(ScopedPtrTest, Nullptr) { 606 scoped_ptr<int> scoper1(nullptr); 607 scoped_ptr<int> scoper2(new int); 608 scoper2 = nullptr; 609 scoped_ptr<int> scoper3(NullIntReturn()); 610 scoped_ptr<int> scoper4 = NullIntReturn(); 611 EXPECT_EQ(nullptr, scoper1.get()); 612 EXPECT_EQ(nullptr, scoper2.get()); 613 EXPECT_EQ(nullptr, scoper3.get()); 614 EXPECT_EQ(nullptr, scoper4.get()); 615 } 616 617 scoped_ptr<int[]> NullIntArrayReturn() { 618 return nullptr; 619 } 620 621 TEST(ScopedPtrTest, NullptrArray) { 622 scoped_ptr<int[]> scoper1(nullptr); 623 scoped_ptr<int[]> scoper2(new int[3]); 624 scoper2 = nullptr; 625 scoped_ptr<int[]> scoper3(NullIntArrayReturn()); 626 scoped_ptr<int[]> scoper4 = NullIntArrayReturn(); 627 EXPECT_EQ(nullptr, scoper1.get()); 628 EXPECT_EQ(nullptr, scoper2.get()); 629 EXPECT_EQ(nullptr, scoper3.get()); 630 EXPECT_EQ(nullptr, scoper4.get()); 631 } 632 633 class Super {}; 634 class Sub : public Super {}; 635 636 scoped_ptr<Sub> SubClassReturn() { 637 return make_scoped_ptr(new Sub); 638 } 639 640 TEST(ScopedPtrTest, Conversion) { 641 scoped_ptr<Sub> sub1(new Sub); 642 scoped_ptr<Sub> sub2(new Sub); 643 644 // Upcast with move works. 645 scoped_ptr<Super> super1 = std::move(sub1); 646 super1 = std::move(sub2); 647 648 // Upcast with an rvalue works. 649 scoped_ptr<Super> super2 = SubClassReturn(); 650 super2 = SubClassReturn(); 651 } 652 653 // Logging a scoped_ptr<T> to an ostream shouldn't convert it to a boolean 654 // value first. 655 TEST(ScopedPtrTest, LoggingDoesntConvertToBoolean) { 656 scoped_ptr<int> x(new int); 657 std::stringstream s1; 658 s1 << x; 659 660 std::stringstream s2; 661 s2 << x.get(); 662 663 EXPECT_EQ(s2.str(), s1.str()); 664 } 665 666 TEST(ScopedPtrTest, ReferenceCycle) { 667 struct StructB; 668 struct StructA { 669 scoped_ptr<StructB> b; 670 }; 671 672 struct StructB { 673 scoped_ptr<StructA> a; 674 }; 675 676 // Create a reference cycle. 677 StructA* a = new StructA; 678 a->b.reset(new StructB); 679 a->b->a.reset(a); 680 681 // Break the cycle by calling reset(). This will cause |a| (and hence, |a->b|) 682 // to be deleted before the call to reset() returns. This tests that the 683 // implementation of scoped_ptr::reset() doesn't access |this| after it 684 // deletes the underlying pointer. This behaviour is consistent with the 685 // definition of unique_ptr::reset in C++11. 686 a->b.reset(); 687 688 // Go again, but this time, break the cycle by invoking |a|'s destructor. This 689 // tests that the implementation of ~scoped_ptr doesn't infinitely recurse 690 // into the destructors of |a| and |a->b|. Note, deleting |a| instead will 691 // cause |a| to be double-free'd because |a->b| owns |a| and deletes it via 692 // its destructor. 693 a = new StructA; 694 a->b.reset(new StructB); 695 a->b->a.reset(a); 696 a->~StructA(); 697 } 698 699 TEST(ScopedPtrTest, Operators) { 700 struct Parent {}; 701 struct Child : public Parent {}; 702 703 scoped_ptr<Parent> p(new Parent); 704 scoped_ptr<Parent> p2(new Parent); 705 scoped_ptr<Child> c(new Child); 706 scoped_ptr<Parent> pnull; 707 708 // Operator==. 709 EXPECT_TRUE(p == p); 710 EXPECT_FALSE(p == c); 711 EXPECT_FALSE(p == p2); 712 EXPECT_FALSE(p == pnull); 713 714 EXPECT_FALSE(p == nullptr); 715 EXPECT_FALSE(nullptr == p); 716 EXPECT_TRUE(pnull == nullptr); 717 EXPECT_TRUE(nullptr == pnull); 718 719 // Operator!=. 720 EXPECT_FALSE(p != p); 721 EXPECT_TRUE(p != c); 722 EXPECT_TRUE(p != p2); 723 EXPECT_TRUE(p != pnull); 724 725 EXPECT_TRUE(p != nullptr); 726 EXPECT_TRUE(nullptr != p); 727 EXPECT_FALSE(pnull != nullptr); 728 EXPECT_FALSE(nullptr != pnull); 729 730 // Compare two scoped_ptr<T>. 731 EXPECT_EQ(p.get() < p2.get(), p < p2); 732 EXPECT_EQ(p.get() <= p2.get(), p <= p2); 733 EXPECT_EQ(p.get() > p2.get(), p > p2); 734 EXPECT_EQ(p.get() >= p2.get(), p >= p2); 735 EXPECT_EQ(p2.get() < p.get(), p2 < p); 736 EXPECT_EQ(p2.get() <= p.get(), p2 <= p); 737 EXPECT_EQ(p2.get() > p.get(), p2 > p); 738 EXPECT_EQ(p2.get() >= p.get(), p2 >= p); 739 740 // And convertible scoped_ptr<T> and scoped_ptr<U>. 741 EXPECT_EQ(p.get() < c.get(), p < c); 742 EXPECT_EQ(p.get() <= c.get(), p <= c); 743 EXPECT_EQ(p.get() > c.get(), p > c); 744 EXPECT_EQ(p.get() >= c.get(), p >= c); 745 EXPECT_EQ(c.get() < p.get(), c < p); 746 EXPECT_EQ(c.get() <= p.get(), c <= p); 747 EXPECT_EQ(c.get() > p.get(), c > p); 748 EXPECT_EQ(c.get() >= p.get(), c >= p); 749 750 // Compare to nullptr. 751 EXPECT_TRUE(p > nullptr); 752 EXPECT_FALSE(nullptr > p); 753 EXPECT_FALSE(pnull > nullptr); 754 EXPECT_FALSE(nullptr > pnull); 755 756 EXPECT_TRUE(p >= nullptr); 757 EXPECT_FALSE(nullptr >= p); 758 EXPECT_TRUE(pnull >= nullptr); 759 EXPECT_TRUE(nullptr >= pnull); 760 761 EXPECT_FALSE(p < nullptr); 762 EXPECT_TRUE(nullptr < p); 763 EXPECT_FALSE(pnull < nullptr); 764 EXPECT_FALSE(nullptr < pnull); 765 766 EXPECT_FALSE(p <= nullptr); 767 EXPECT_TRUE(nullptr <= p); 768 EXPECT_TRUE(pnull <= nullptr); 769 EXPECT_TRUE(nullptr <= pnull); 770 }; 771 772 TEST(ScopedPtrTest, ArrayOperators) { 773 struct Parent {}; 774 struct Child : public Parent {}; 775 776 scoped_ptr<Parent[]> p(new Parent[1]); 777 scoped_ptr<Parent[]> p2(new Parent[1]); 778 scoped_ptr<Child[]> c(new Child[1]); 779 scoped_ptr<Parent[]> pnull; 780 781 // Operator==. 782 EXPECT_TRUE(p == p); 783 EXPECT_FALSE(p == c); 784 EXPECT_FALSE(p == p2); 785 EXPECT_FALSE(p == pnull); 786 787 EXPECT_FALSE(p == nullptr); 788 EXPECT_FALSE(nullptr == p); 789 EXPECT_TRUE(pnull == nullptr); 790 EXPECT_TRUE(nullptr == pnull); 791 792 // Operator!=. 793 EXPECT_FALSE(p != p); 794 EXPECT_TRUE(p != c); 795 EXPECT_TRUE(p != p2); 796 EXPECT_TRUE(p != pnull); 797 798 EXPECT_TRUE(p != nullptr); 799 EXPECT_TRUE(nullptr != p); 800 EXPECT_FALSE(pnull != nullptr); 801 EXPECT_FALSE(nullptr != pnull); 802 803 // Compare two scoped_ptr<T>. 804 EXPECT_EQ(p.get() < p2.get(), p < p2); 805 EXPECT_EQ(p.get() <= p2.get(), p <= p2); 806 EXPECT_EQ(p.get() > p2.get(), p > p2); 807 EXPECT_EQ(p.get() >= p2.get(), p >= p2); 808 EXPECT_EQ(p2.get() < p.get(), p2 < p); 809 EXPECT_EQ(p2.get() <= p.get(), p2 <= p); 810 EXPECT_EQ(p2.get() > p.get(), p2 > p); 811 EXPECT_EQ(p2.get() >= p.get(), p2 >= p); 812 813 // And convertible scoped_ptr<T> and scoped_ptr<U>. 814 EXPECT_EQ(p.get() < c.get(), p < c); 815 EXPECT_EQ(p.get() <= c.get(), p <= c); 816 EXPECT_EQ(p.get() > c.get(), p > c); 817 EXPECT_EQ(p.get() >= c.get(), p >= c); 818 EXPECT_EQ(c.get() < p.get(), c < p); 819 EXPECT_EQ(c.get() <= p.get(), c <= p); 820 EXPECT_EQ(c.get() > p.get(), c > p); 821 EXPECT_EQ(c.get() >= p.get(), c >= p); 822 823 // Compare to nullptr. 824 EXPECT_TRUE(p > nullptr); 825 EXPECT_FALSE(nullptr > p); 826 EXPECT_FALSE(pnull > nullptr); 827 EXPECT_FALSE(nullptr > pnull); 828 829 EXPECT_TRUE(p >= nullptr); 830 EXPECT_FALSE(nullptr >= p); 831 EXPECT_TRUE(pnull >= nullptr); 832 EXPECT_TRUE(nullptr >= pnull); 833 834 EXPECT_FALSE(p < nullptr); 835 EXPECT_TRUE(nullptr < p); 836 EXPECT_FALSE(pnull < nullptr); 837 EXPECT_FALSE(nullptr < pnull); 838 839 EXPECT_FALSE(p <= nullptr); 840 EXPECT_TRUE(nullptr <= p); 841 EXPECT_TRUE(pnull <= nullptr); 842 EXPECT_TRUE(nullptr <= pnull); 843 } 844