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 |