Chromium Code Reviews| 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/timer/timer.h" | 5 #include "base/timer/timer.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <memory> | 9 #include <memory> |
| 10 | 10 |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/bind_helpers.h" | 12 #include "base/bind_helpers.h" |
| 13 #include "base/callback.h" | 13 #include "base/callback.h" |
| 14 #include "base/macros.h" | 14 #include "base/macros.h" |
| 15 #include "base/memory/ptr_util.h" | 15 #include "base/memory/ptr_util.h" |
| 16 #include "base/memory/ref_counted.h" | |
| 16 #include "base/message_loop/message_loop.h" | 17 #include "base/message_loop/message_loop.h" |
| 17 #include "base/run_loop.h" | 18 #include "base/run_loop.h" |
| 18 #include "base/sequenced_task_runner.h" | 19 #include "base/sequenced_task_runner.h" |
| 19 #include "base/single_thread_task_runner.h" | 20 #include "base/single_thread_task_runner.h" |
| 20 #include "base/synchronization/waitable_event.h" | 21 #include "base/synchronization/waitable_event.h" |
| 21 #include "base/test/sequenced_worker_pool_owner.h" | 22 #include "base/test/sequenced_worker_pool_owner.h" |
| 22 #include "base/test/test_mock_time_task_runner.h" | 23 #include "base/test/test_mock_time_task_runner.h" |
| 23 #include "base/threading/platform_thread.h" | 24 #include "base/threading/platform_thread.h" |
| 24 #include "base/threading/sequenced_task_runner_handle.h" | 25 #include "base/threading/sequenced_task_runner_handle.h" |
| 25 #include "base/threading/thread.h" | 26 #include "base/threading/thread.h" |
| (...skipping 523 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 549 { | 550 { |
| 550 MessageLoop loop; | 551 MessageLoop loop; |
| 551 a.Start(); | 552 a.Start(); |
| 552 b.Start(); | 553 b.Start(); |
| 553 } // MessageLoop destructs by falling out of scope. | 554 } // MessageLoop destructs by falling out of scope. |
| 554 } // OneShotTimers destruct. SHOULD NOT CRASH, of course. | 555 } // OneShotTimers destruct. SHOULD NOT CRASH, of course. |
| 555 | 556 |
| 556 EXPECT_FALSE(did_run.IsSignaled()); | 557 EXPECT_FALSE(did_run.IsSignaled()); |
| 557 } | 558 } |
| 558 | 559 |
| 560 // Ref counted class which owns a Timer. The class passes a reference to itself | |
| 561 // via the |user_task| parameter in Timer::Start(). |Timer::user_task_| might | |
| 562 // end up holding the last reference to the class. | |
| 563 class OneShotSelfOwningTimerTester | |
| 564 : public RefCounted<OneShotSelfOwningTimerTester> { | |
| 565 public: | |
| 566 explicit OneShotSelfOwningTimerTester(bool* did_run) : did_run_(did_run) {} | |
| 567 | |
| 568 void StartTimer() { | |
| 569 timer_.Start(FROM_HERE, TimeDelta::FromMilliseconds(10), | |
| 570 base::Bind(&OneShotSelfOwningTimerTester::Run, this)); | |
| 571 } | |
| 572 | |
| 573 private: | |
| 574 friend class RefCounted<OneShotSelfOwningTimerTester>; | |
| 575 ~OneShotSelfOwningTimerTester() {} | |
|
gab
2017/01/12 19:42:54
= default;
| |
| 576 | |
| 577 void Run() { | |
| 578 if (did_run_) | |
|
gab
2017/01/12 19:42:54
Instead of using |did_run_| simply
ADD_FAILURE()
| |
| 579 *did_run_ = true; | |
| 580 } | |
| 581 | |
| 582 OneShotTimer timer_; | |
| 583 bool* did_run_; | |
| 584 | |
| 585 DISALLOW_COPY_AND_ASSIGN(OneShotSelfOwningTimerTester); | |
| 586 }; | |
| 587 | |
| 588 TEST(TimerTest, MessageLoopShutdownSelfOwningTimer) { | |
| 589 // This test verifies that shutdown of the message loop does not cause crashes | |
| 590 // if there is a pending timer not yet fired and |Timer::user_task_| owns the | |
| 591 // timer. The test may only trigger exceptions if debug heap checking is | |
| 592 // enabled. | |
| 593 | |
| 594 bool did_run = false; | |
| 595 { | |
| 596 MessageLoop loop; | |
| 597 { | |
|
gab
2017/01/12 19:42:54
Instead of using a nested scope and racily dependi
| |
| 598 scoped_refptr<OneShotSelfOwningTimerTester> tester = | |
| 599 new OneShotSelfOwningTimerTester(&did_run); | |
| 600 tester->StartTimer(); | |
| 601 } // |Timer::user_task_| owns sole reference to |tester|. | |
| 602 } // MessageLoop destructs by falling out of scope. SHOULD NOT CRASH. | |
|
gab
2017/01/12 19:42:54
Since the goal in this test is to hit ~Timer() bef
| |
| 603 | |
| 604 EXPECT_FALSE(did_run); | |
| 605 } | |
| 606 | |
| 559 void TimerTestCallback() { | 607 void TimerTestCallback() { |
| 560 } | 608 } |
| 561 | 609 |
| 562 TEST(TimerTest, NonRepeatIsRunning) { | 610 TEST(TimerTest, NonRepeatIsRunning) { |
| 563 { | 611 { |
| 564 MessageLoop loop; | 612 MessageLoop loop; |
| 565 Timer timer(false, false); | 613 Timer timer(false, false); |
| 566 EXPECT_FALSE(timer.IsRunning()); | 614 EXPECT_FALSE(timer.IsRunning()); |
| 567 timer.Start(FROM_HERE, TimeDelta::FromDays(1), Bind(&TimerTestCallback)); | 615 timer.Start(FROM_HERE, TimeDelta::FromDays(1), Bind(&TimerTestCallback)); |
| 568 EXPECT_TRUE(timer.IsRunning()); | 616 EXPECT_TRUE(timer.IsRunning()); |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 670 Bind(&SetCallbackHappened1)); | 718 Bind(&SetCallbackHappened1)); |
| 671 timer.Reset(); | 719 timer.Reset(); |
| 672 // Since Reset happened before task ran, the user_task must not be cleared: | 720 // Since Reset happened before task ran, the user_task must not be cleared: |
| 673 ASSERT_FALSE(timer.user_task().is_null()); | 721 ASSERT_FALSE(timer.user_task().is_null()); |
| 674 RunLoop().Run(); | 722 RunLoop().Run(); |
| 675 EXPECT_TRUE(g_callback_happened1); | 723 EXPECT_TRUE(g_callback_happened1); |
| 676 } | 724 } |
| 677 } | 725 } |
| 678 | 726 |
| 679 } // namespace base | 727 } // namespace base |
| OLD | NEW |