1 // Copyright 2014 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 "media/cast/test/fake_single_thread_task_runner.h"
6
7 #include "base/logging.h"
8 #include "base/time/tick_clock.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10
11 namespace media {
12 namespace cast {
13 namespace test {
14
FakeSingleThreadTaskRunner(base::SimpleTestTickClock * clock)15 FakeSingleThreadTaskRunner::FakeSingleThreadTaskRunner(
16 base::SimpleTestTickClock* clock)
17 : clock_(clock),
18 fail_on_next_task_(false) {}
19
~FakeSingleThreadTaskRunner()20 FakeSingleThreadTaskRunner::~FakeSingleThreadTaskRunner() {}
21
PostDelayedTask(const tracked_objects::Location & from_here,const base::Closure & task,base::TimeDelta delay)22 bool FakeSingleThreadTaskRunner::PostDelayedTask(
23 const tracked_objects::Location& from_here,
24 const base::Closure& task,
25 base::TimeDelta delay) {
26 if (fail_on_next_task_) {
27 LOG(FATAL) << "Infinite task-add loop detected.";
28 }
29 CHECK(delay >= base::TimeDelta());
30 EXPECT_GE(delay, base::TimeDelta());
31 PostedTask posed_task(from_here,
32 task,
33 clock_->NowTicks(),
34 delay,
35 base::TestPendingTask::NESTABLE);
36
37 tasks_.insert(std::make_pair(posed_task.GetTimeToRun(), posed_task));
38 return false;
39 }
40
RunsTasksOnCurrentThread() const41 bool FakeSingleThreadTaskRunner::RunsTasksOnCurrentThread() const {
42 return true;
43 }
44
RunTasks()45 void FakeSingleThreadTaskRunner::RunTasks() {
46 while (true) {
47 // Run all tasks equal or older than current time.
48 std::multimap<base::TimeTicks, PostedTask>::iterator it = tasks_.begin();
49 if (it == tasks_.end())
50 return; // No more tasks.
51
52 PostedTask task = it->second;
53 if (clock_->NowTicks() < task.GetTimeToRun())
54 return;
55
56 tasks_.erase(it);
57 task.task.Run();
58 }
59 }
60
Sleep(base::TimeDelta t)61 void FakeSingleThreadTaskRunner::Sleep(base::TimeDelta t) {
62 base::TimeTicks run_until = clock_->NowTicks() + t;
63 while (1) {
64 // If we run more than 100000 iterations, we've probably
65 // hit some sort of case where a new task is posted every
66 // time that we invoke a task, and we can't make progress
67 // anymore. If that happens, set fail_on_next_task_ to true
68 // and throw an error when the next task is posted.
69 for (int i = 0; i < 100000; i++) {
70 // Run all tasks equal or older than current time.
71 std::multimap<base::TimeTicks, PostedTask>::iterator it = tasks_.begin();
72 if (it == tasks_.end()) {
73 clock_->Advance(run_until - clock_->NowTicks());
74 return;
75 }
76
77 PostedTask task = it->second;
78 if (run_until < task.GetTimeToRun()) {
79 clock_->Advance(run_until - clock_->NowTicks());
80 return;
81 }
82
83 clock_->Advance(task.GetTimeToRun() - clock_->NowTicks());
84 tasks_.erase(it);
85 task.task.Run();
86 }
87 // Instead of failing immediately, we fail when the next task is
88 // added so that the backtrace will include the task that was added.
89 fail_on_next_task_ = true;
90 }
91 }
92
PostNonNestableDelayedTask(const tracked_objects::Location & from_here,const base::Closure & task,base::TimeDelta delay)93 bool FakeSingleThreadTaskRunner::PostNonNestableDelayedTask(
94 const tracked_objects::Location& from_here,
95 const base::Closure& task,
96 base::TimeDelta delay) {
97 NOTIMPLEMENTED();
98 return false;
99 }
100
101 } // namespace test
102 } // namespace cast
103 } // namespace media
104