| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/memory/weak_ptr.h" | 5 #include "base/memory/weak_ptr.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/debug/leak_annotations.h" | 11 #include "base/debug/leak_annotations.h" |
| 12 #include "base/location.h" | 12 #include "base/location.h" |
| 13 #include "base/single_thread_task_runner.h" | 13 #include "base/single_thread_task_runner.h" |
| 14 #include "base/synchronization/waitable_event.h" | 14 #include "base/synchronization/waitable_event.h" |
| 15 #include "base/test/gtest_util.h" |
| 15 #include "base/threading/thread.h" | 16 #include "base/threading/thread.h" |
| 16 #include "testing/gtest/include/gtest/gtest.h" | 17 #include "testing/gtest/include/gtest/gtest.h" |
| 17 | 18 |
| 18 namespace base { | 19 namespace base { |
| 19 namespace { | 20 namespace { |
| 20 | 21 |
| 21 WeakPtr<int> PassThru(WeakPtr<int> ptr) { | 22 WeakPtr<int> PassThru(WeakPtr<int> ptr) { |
| 22 return ptr; | 23 return ptr; |
| 23 } | 24 } |
| 24 | 25 |
| (...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 556 // Main thread creates an arrow referencing the Target. | 557 // Main thread creates an arrow referencing the Target. |
| 557 Arrow* arrow = new Arrow(); | 558 Arrow* arrow = new Arrow(); |
| 558 arrow->target = target.AsWeakPtr(); | 559 arrow->target = target.AsWeakPtr(); |
| 559 | 560 |
| 560 // Background can delete arrow (as well as the WeakPtr inside). | 561 // Background can delete arrow (as well as the WeakPtr inside). |
| 561 BackgroundThread background; | 562 BackgroundThread background; |
| 562 background.Start(); | 563 background.Start(); |
| 563 background.DeleteArrow(arrow); | 564 background.DeleteArrow(arrow); |
| 564 } | 565 } |
| 565 | 566 |
| 566 #if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) && GTEST_HAS_DEATH_TEST | |
| 567 | |
| 568 TEST(WeakPtrDeathTest, WeakPtrCopyDoesNotChangeThreadBinding) { | 567 TEST(WeakPtrDeathTest, WeakPtrCopyDoesNotChangeThreadBinding) { |
| 569 // The default style "fast" does not support multi-threaded tests | 568 // The default style "fast" does not support multi-threaded tests |
| 570 // (introduces deadlock on Linux). | 569 // (introduces deadlock on Linux). |
| 571 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; | 570 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; |
| 572 | 571 |
| 573 BackgroundThread background; | 572 BackgroundThread background; |
| 574 background.Start(); | 573 background.Start(); |
| 575 | 574 |
| 576 // Main thread creates a Target object. | 575 // Main thread creates a Target object. |
| 577 Target target; | 576 Target target; |
| 578 // Main thread creates an arrow referencing the Target. | 577 // Main thread creates an arrow referencing the Target. |
| 579 Arrow arrow; | 578 Arrow arrow; |
| 580 arrow.target = target.AsWeakPtr(); | 579 arrow.target = target.AsWeakPtr(); |
| 581 | 580 |
| 582 // Background copies the WeakPtr. | 581 // Background copies the WeakPtr. |
| 583 Arrow* arrow_copy; | 582 Arrow* arrow_copy; |
| 584 background.CreateArrowFromArrow(&arrow_copy, &arrow); | 583 background.CreateArrowFromArrow(&arrow_copy, &arrow); |
| 585 | 584 |
| 586 // The copy is still bound to main thread so I can deref. | 585 // The copy is still bound to main thread so I can deref. |
| 587 EXPECT_EQ(arrow.target.get(), arrow_copy->target.get()); | 586 EXPECT_EQ(arrow.target.get(), arrow_copy->target.get()); |
| 588 | 587 |
| 589 // Although background thread created the copy, it can not deref the copied | 588 // Although background thread created the copy, it can not deref the copied |
| 590 // WeakPtr. | 589 // WeakPtr. |
| 591 ASSERT_DEATH(background.DeRef(arrow_copy), ""); | 590 ASSERT_DCHECK_DEATH(background.DeRef(arrow_copy), ""); |
| 592 | 591 |
| 593 background.DeleteArrow(arrow_copy); | 592 background.DeleteArrow(arrow_copy); |
| 594 } | 593 } |
| 595 | 594 |
| 596 TEST(WeakPtrDeathTest, NonOwnerThreadDereferencesWeakPtrAfterReference) { | 595 TEST(WeakPtrDeathTest, NonOwnerThreadDereferencesWeakPtrAfterReference) { |
| 597 // The default style "fast" does not support multi-threaded tests | 596 // The default style "fast" does not support multi-threaded tests |
| 598 // (introduces deadlock on Linux). | 597 // (introduces deadlock on Linux). |
| 599 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; | 598 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; |
| 600 | 599 |
| 601 // Main thread creates a Target object. | 600 // Main thread creates a Target object. |
| 602 Target target; | 601 Target target; |
| 603 | 602 |
| 604 // Main thread creates an arrow referencing the Target (so target's | 603 // Main thread creates an arrow referencing the Target (so target's |
| 605 // thread ownership can not be implicitly moved). | 604 // thread ownership can not be implicitly moved). |
| 606 Arrow arrow; | 605 Arrow arrow; |
| 607 arrow.target = target.AsWeakPtr(); | 606 arrow.target = target.AsWeakPtr(); |
| 608 arrow.target.get(); | 607 arrow.target.get(); |
| 609 | 608 |
| 610 // Background thread tries to deref target, which violates thread ownership. | 609 // Background thread tries to deref target, which violates thread ownership. |
| 611 BackgroundThread background; | 610 BackgroundThread background; |
| 612 background.Start(); | 611 background.Start(); |
| 613 ASSERT_DEATH(background.DeRef(&arrow), ""); | 612 ASSERT_DCHECK_DEATH(background.DeRef(&arrow), ""); |
| 614 } | 613 } |
| 615 | 614 |
| 616 TEST(WeakPtrDeathTest, NonOwnerThreadDeletesWeakPtrAfterReference) { | 615 TEST(WeakPtrDeathTest, NonOwnerThreadDeletesWeakPtrAfterReference) { |
| 617 // The default style "fast" does not support multi-threaded tests | 616 // The default style "fast" does not support multi-threaded tests |
| 618 // (introduces deadlock on Linux). | 617 // (introduces deadlock on Linux). |
| 619 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; | 618 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; |
| 620 | 619 |
| 621 std::unique_ptr<Target> target(new Target()); | 620 std::unique_ptr<Target> target(new Target()); |
| 622 | 621 |
| 623 // Main thread creates an arrow referencing the Target. | 622 // Main thread creates an arrow referencing the Target. |
| 624 Arrow arrow; | 623 Arrow arrow; |
| 625 arrow.target = target->AsWeakPtr(); | 624 arrow.target = target->AsWeakPtr(); |
| 626 | 625 |
| 627 // Background thread tries to deref target, binding it to the thread. | 626 // Background thread tries to deref target, binding it to the thread. |
| 628 BackgroundThread background; | 627 BackgroundThread background; |
| 629 background.Start(); | 628 background.Start(); |
| 630 background.DeRef(&arrow); | 629 background.DeRef(&arrow); |
| 631 | 630 |
| 632 // Main thread deletes Target, violating thread binding. | 631 // Main thread deletes Target, violating thread binding. |
| 633 ASSERT_DEATH(target.reset(), ""); | 632 ASSERT_DCHECK_DEATH(target.reset(), ""); |
| 634 | 633 |
| 635 // |target.reset()| died so |target| still holds the object, so we | 634 // |target.reset()| died so |target| still holds the object, so we |
| 636 // must pass it to the background thread to teardown. | 635 // must pass it to the background thread to teardown. |
| 637 background.DeleteTarget(target.release()); | 636 background.DeleteTarget(target.release()); |
| 638 } | 637 } |
| 639 | 638 |
| 640 TEST(WeakPtrDeathTest, NonOwnerThreadDeletesObjectAfterReference) { | 639 TEST(WeakPtrDeathTest, NonOwnerThreadDeletesObjectAfterReference) { |
| 641 // The default style "fast" does not support multi-threaded tests | 640 // The default style "fast" does not support multi-threaded tests |
| 642 // (introduces deadlock on Linux). | 641 // (introduces deadlock on Linux). |
| 643 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; | 642 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; |
| 644 | 643 |
| 645 std::unique_ptr<Target> target(new Target()); | 644 std::unique_ptr<Target> target(new Target()); |
| 646 | 645 |
| 647 // Main thread creates an arrow referencing the Target, and references it, so | 646 // Main thread creates an arrow referencing the Target, and references it, so |
| 648 // that it becomes bound to the thread. | 647 // that it becomes bound to the thread. |
| 649 Arrow arrow; | 648 Arrow arrow; |
| 650 arrow.target = target->AsWeakPtr(); | 649 arrow.target = target->AsWeakPtr(); |
| 651 arrow.target.get(); | 650 arrow.target.get(); |
| 652 | 651 |
| 653 // Background thread tries to delete target, volating thread binding. | 652 // Background thread tries to delete target, volating thread binding. |
| 654 BackgroundThread background; | 653 BackgroundThread background; |
| 655 background.Start(); | 654 background.Start(); |
| 656 ASSERT_DEATH(background.DeleteTarget(target.release()), ""); | 655 ASSERT_DCHECK_DEATH(background.DeleteTarget(target.release()), ""); |
| 657 } | 656 } |
| 658 | 657 |
| 659 TEST(WeakPtrDeathTest, NonOwnerThreadReferencesObjectAfterDeletion) { | 658 TEST(WeakPtrDeathTest, NonOwnerThreadReferencesObjectAfterDeletion) { |
| 660 // The default style "fast" does not support multi-threaded tests | 659 // The default style "fast" does not support multi-threaded tests |
| 661 // (introduces deadlock on Linux). | 660 // (introduces deadlock on Linux). |
| 662 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; | 661 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; |
| 663 | 662 |
| 664 std::unique_ptr<Target> target(new Target()); | 663 std::unique_ptr<Target> target(new Target()); |
| 665 | 664 |
| 666 // Main thread creates an arrow referencing the Target. | 665 // Main thread creates an arrow referencing the Target. |
| 667 Arrow arrow; | 666 Arrow arrow; |
| 668 arrow.target = target->AsWeakPtr(); | 667 arrow.target = target->AsWeakPtr(); |
| 669 | 668 |
| 670 // Background thread tries to delete target, binding the object to the thread. | 669 // Background thread tries to delete target, binding the object to the thread. |
| 671 BackgroundThread background; | 670 BackgroundThread background; |
| 672 background.Start(); | 671 background.Start(); |
| 673 background.DeleteTarget(target.release()); | 672 background.DeleteTarget(target.release()); |
| 674 | 673 |
| 675 // Main thread attempts to dereference the target, violating thread binding. | 674 // Main thread attempts to dereference the target, violating thread binding. |
| 676 ASSERT_DEATH(arrow.target.get(), ""); | 675 ASSERT_DCHECK_DEATH(arrow.target.get(), ""); |
| 677 } | 676 } |
| 678 | 677 |
| 679 #endif | |
| 680 | |
| 681 } // namespace base | 678 } // namespace base |
| OLD | NEW |