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/callback.h" | |
5 #include "base/memory/scoped_ptr.h" | 6 #include "base/memory/scoped_ptr.h" |
6 #include "base/message_loop/message_loop.h" | 7 #include "base/message_loop/message_loop.h" |
8 #include "base/synchronization/waitable_event.h" | |
9 #include "base/test/sequenced_worker_pool_owner.h" | |
7 #include "base/test/test_simple_task_runner.h" | 10 #include "base/test/test_simple_task_runner.h" |
8 #include "base/timer/timer.h" | 11 #include "base/timer/timer.h" |
9 #include "testing/gtest/include/gtest/gtest.h" | 12 #include "testing/gtest/include/gtest/gtest.h" |
10 | 13 |
14 using base::SequencedTaskRunner; | |
11 using base::TimeDelta; | 15 using base::TimeDelta; |
12 using base::SingleThreadTaskRunner; | |
13 | 16 |
14 namespace { | 17 namespace { |
15 | 18 |
16 // The message loops on which each timer should be tested. | 19 // The message loops on which each timer should be tested. |
17 const base::MessageLoop::Type testing_message_loops[] = { | 20 const base::MessageLoop::Type testing_message_loops[] = { |
18 base::MessageLoop::TYPE_DEFAULT, | 21 base::MessageLoop::TYPE_DEFAULT, |
19 base::MessageLoop::TYPE_IO, | 22 base::MessageLoop::TYPE_IO, |
20 #if !defined(OS_IOS) // iOS does not allow direct running of the UI loop. | 23 #if !defined(OS_IOS) // iOS does not allow direct running of the UI loop. |
21 base::MessageLoop::TYPE_UI, | 24 base::MessageLoop::TYPE_UI, |
22 #endif | 25 #endif |
23 }; | 26 }; |
24 | 27 |
25 const int kNumTestingMessageLoops = arraysize(testing_message_loops); | 28 const int kNumTestingMessageLoops = arraysize(testing_message_loops); |
26 | 29 |
27 class OneShotTimerTester { | 30 class OneShotTimerTester { |
28 public: | 31 public: |
29 explicit OneShotTimerTester(bool* did_run, unsigned milliseconds = 10) | 32 explicit OneShotTimerTester(bool* did_run, unsigned milliseconds = 10) |
30 : did_run_(did_run), | 33 : did_run_(did_run), |
31 delay_ms_(milliseconds), | 34 delay_ms_(milliseconds), |
32 quit_message_loop_(true) { | 35 quit_message_loop_(true) { |
33 } | 36 } |
34 | 37 |
35 void Start() { | 38 void Start() { |
36 timer_.Start(FROM_HERE, TimeDelta::FromMilliseconds(delay_ms_), this, | 39 timer_.Start(FROM_HERE, TimeDelta::FromMilliseconds(delay_ms_), this, |
37 &OneShotTimerTester::Run); | 40 &OneShotTimerTester::Run); |
38 } | 41 } |
39 | 42 |
40 void SetTaskRunner(scoped_refptr<SingleThreadTaskRunner> task_runner) { | 43 void SetTaskRunner(scoped_refptr<SequencedTaskRunner> task_runner) { |
41 quit_message_loop_ = false; | 44 quit_message_loop_ = false; |
42 timer_.SetTaskRunner(task_runner); | 45 timer_.SetTaskRunner(task_runner); |
43 } | 46 } |
44 | 47 |
45 private: | 48 private: |
46 void Run() { | 49 void Run() { |
47 *did_run_ = true; | 50 *did_run_ = true; |
48 if (quit_message_loop_) { | 51 if (quit_message_loop_) { |
49 base::MessageLoop::current()->QuitWhenIdle(); | 52 base::MessageLoop::current()->QuitWhenIdle(); |
50 } | 53 } |
(...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
521 timer.Start(FROM_HERE, TimeDelta::FromMilliseconds(10), | 524 timer.Start(FROM_HERE, TimeDelta::FromMilliseconds(10), |
522 base::Bind(&SetCallbackHappened1)); | 525 base::Bind(&SetCallbackHappened1)); |
523 timer.Reset(); | 526 timer.Reset(); |
524 // Since Reset happened before task ran, the user_task must not be cleared: | 527 // Since Reset happened before task ran, the user_task must not be cleared: |
525 ASSERT_FALSE(timer.user_task().is_null()); | 528 ASSERT_FALSE(timer.user_task().is_null()); |
526 base::MessageLoop::current()->Run(); | 529 base::MessageLoop::current()->Run(); |
527 EXPECT_TRUE(g_callback_happened1); | 530 EXPECT_TRUE(g_callback_happened1); |
528 } | 531 } |
529 } | 532 } |
530 | 533 |
534 const size_t kNumWorkerThreads = 3; | |
535 | |
536 // Fixture for tests requiring a worker pool. Includes a WaitableEvent so | |
537 // that cases may Wait() on one thread and Signal() (explicitly, or implicitly | |
538 // via helper methods) on another. | |
539 class TimerSequenceTest : public testing::Test { | |
540 public: | |
541 TimerSequenceTest() | |
542 : event_(false /*manual_reset*/, true /*initially_signaled*/) {} | |
gab
2015/12/03 22:26:08
Add space padding in /* comment */
jsbell
2015/12/05 01:15:39
Done.
| |
543 | |
544 void SetUp() override { ResetPool(); } | |
545 | |
546 void TearDown() override { pool()->Shutdown(); } | |
547 | |
548 // Block until Signal() is called on another thread. | |
549 void Wait() { event_.Wait(); } | |
550 | |
551 void Signal() { event_.Signal(); } | |
552 | |
553 // Explicitly create the timer. Not done in the constructor so that test | |
554 // cases demonstrate creation on a specific thread. | |
555 void CreateTimer() { timer_.reset(new base::OneShotTimer); } | |
556 | |
557 // Start the timer; when the timer fires it will Signal(), so Wait() can | |
558 // be called on another thread to await this. | |
559 void StartTimerWillSignal() { | |
560 timer_->Start(FROM_HERE, TimeDelta::FromMilliseconds(1), this, | |
561 &TimerSequenceTest::Signal); | |
562 } | |
563 | |
564 // Delete the timer then Signal() so that this can be posted as a task | |
565 // to another thread and the poster can Wait(). | |
566 void DeleteTimerAndSignal() { | |
567 timer_.reset(); | |
568 Signal(); | |
569 } | |
570 | |
571 protected: | |
572 const scoped_refptr<base::SequencedWorkerPool>& pool() { | |
573 return pool_owner_->pool(); | |
574 } | |
575 | |
576 // Destroys the SequencedWorkerPool instance, blocking until it is fully shut | |
577 // down, and creates a new instance. | |
578 void ResetPool() { | |
579 pool_owner_.reset( | |
580 new base::SequencedWorkerPoolOwner(kNumWorkerThreads, "test")); | |
581 } | |
582 | |
583 scoped_ptr<base::OneShotTimer> timer_; | |
584 | |
585 private: | |
586 base::WaitableEvent event_; | |
587 | |
588 base::MessageLoop message_loop_; | |
589 scoped_ptr<base::SequencedWorkerPoolOwner> pool_owner_; | |
590 }; | |
gab
2015/12/03 22:26:08
DISALLOW_COPY_AND_ASSIGN
jsbell
2015/12/05 01:15:39
Done.
| |
591 | |
592 TEST_F(TimerSequenceTest, OneShotTimerTaskOnPoolThread) { | |
593 scoped_refptr<base::SequencedTaskRunner> task_runner = | |
594 pool()->GetSequencedTaskRunner(pool()->GetSequenceToken()); | |
595 | |
596 // Timer is created on this thread. | |
597 CreateTimer(); | |
598 | |
599 // Task will execute on a pool thread. | |
600 timer_->SetTaskRunner(task_runner.get()); | |
601 StartTimerWillSignal(); | |
602 Wait(); | |
603 | |
604 // Timer will be destroyed on this thread. | |
605 timer_.reset(); | |
606 } | |
607 | |
608 TEST_F(TimerSequenceTest, OneShotTimerUsedOnPoolThread) { | |
609 scoped_refptr<base::SequencedTaskRunner> task_runner = | |
610 pool()->GetSequencedTaskRunner(pool()->GetSequenceToken()); | |
611 | |
612 // Timer is created on this thread. | |
613 CreateTimer(); | |
614 | |
615 // Task will execute on a pool thread. | |
616 task_runner->PostTask(FROM_HERE, | |
617 base::Bind(&TimerSequenceTest::StartTimerWillSignal, | |
618 base::Unretained(this))); | |
619 Wait(); | |
620 | |
621 // Timer must be destroyed on pool thread, too. | |
622 task_runner->PostTask(FROM_HERE, | |
623 base::Bind(&TimerSequenceTest::DeleteTimerAndSignal, | |
624 base::Unretained(this))); | |
625 Wait(); | |
626 } | |
627 | |
gab
2015/12/03 22:26:09
Feels a test that would:
1) Create a |timer| from
jsbell
2015/12/05 01:15:39
Those sound great - done and done. Any others?
| |
531 } // namespace | 628 } // namespace |
OLD | NEW |