blob: a2e3393f557f56b984023a75f2444a8cde9aa05b [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/cast/test/fake_single_thread_task_runner.h"
#include "base/logging.h"
#include "base/time/tick_clock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace media {
namespace cast {
namespace test {
FakeSingleThreadTaskRunner::FakeSingleThreadTaskRunner(
base::SimpleTestTickClock* clock)
: clock_(clock),
fail_on_next_task_(false) {}
FakeSingleThreadTaskRunner::~FakeSingleThreadTaskRunner() {}
bool FakeSingleThreadTaskRunner::PostDelayedTask(
const tracked_objects::Location& from_here,
const base::Closure& task,
base::TimeDelta delay) {
if (fail_on_next_task_) {
LOG(FATAL) << "Infinite task-add loop detected.";
}
CHECK(delay >= base::TimeDelta());
EXPECT_GE(delay, base::TimeDelta());
PostedTask posed_task(from_here,
task,
clock_->NowTicks(),
delay,
base::TestPendingTask::NESTABLE);
tasks_.insert(std::make_pair(posed_task.GetTimeToRun(), posed_task));
return false;
}
bool FakeSingleThreadTaskRunner::RunsTasksOnCurrentThread() const {
return true;
}
void FakeSingleThreadTaskRunner::RunTasks() {
while (true) {
// Run all tasks equal or older than current time.
std::multimap<base::TimeTicks, PostedTask>::iterator it = tasks_.begin();
if (it == tasks_.end())
return; // No more tasks.
PostedTask task = it->second;
if (clock_->NowTicks() < task.GetTimeToRun())
return;
tasks_.erase(it);
task.task.Run();
}
}
void FakeSingleThreadTaskRunner::Sleep(base::TimeDelta t) {
base::TimeTicks run_until = clock_->NowTicks() + t;
while (1) {
// If we run more than 100000 iterations, we've probably
// hit some sort of case where a new task is posted every
// time that we invoke a task, and we can't make progress
// anymore. If that happens, set fail_on_next_task_ to true
// and throw an error when the next task is posted.
for (int i = 0; i < 100000; i++) {
// Run all tasks equal or older than current time.
std::multimap<base::TimeTicks, PostedTask>::iterator it = tasks_.begin();
if (it == tasks_.end()) {
clock_->Advance(run_until - clock_->NowTicks());
return;
}
PostedTask task = it->second;
if (run_until < task.GetTimeToRun()) {
clock_->Advance(run_until - clock_->NowTicks());
return;
}
clock_->Advance(task.GetTimeToRun() - clock_->NowTicks());
tasks_.erase(it);
task.task.Run();
}
// Instead of failing immediately, we fail when the next task is
// added so that the backtrace will include the task that was added.
fail_on_next_task_ = true;
}
}
bool FakeSingleThreadTaskRunner::PostNonNestableDelayedTask(
const tracked_objects::Location& from_here,
const base::Closure& task,
base::TimeDelta delay) {
NOTIMPLEMENTED();
return false;
}
} // namespace test
} // namespace cast
} // namespace media