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 11namespace media { 12namespace cast { 13namespace test { 14 15FakeSingleThreadTaskRunner::FakeSingleThreadTaskRunner( 16 base::SimpleTestTickClock* clock) 17 : clock_(clock), 18 fail_on_next_task_(false) {} 19 20FakeSingleThreadTaskRunner::~FakeSingleThreadTaskRunner() {} 21 22bool 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 41bool FakeSingleThreadTaskRunner::RunsTasksOnCurrentThread() const { 42 return true; 43} 44 45void 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 61void 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 93bool 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