• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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