blob: f2d60cf9d13c01c69b2a982f67afe68d5ace4b97 [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 "components/scheduler/child/scheduler_helper.h"
#include "base/callback.h"
#include "base/test/simple_test_tick_clock.h"
#include "cc/test/ordered_simple_task_runner.h"
#include "components/scheduler/base/task_queue.h"
#include "components/scheduler/base/test_time_source.h"
#include "components/scheduler/child/scheduler_tqm_delegate_for_test.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using testing::_;
using testing::AnyNumber;
using testing::Invoke;
using testing::Return;
namespace scheduler {
namespace {
void AppendToVectorTestTask(std::vector<std::string>* vector,
std::string value) {
vector->push_back(value);
}
void AppendToVectorReentrantTask(base::SingleThreadTaskRunner* task_runner,
std::vector<int>* vector,
int* reentrant_count,
int max_reentrant_count) {
vector->push_back((*reentrant_count)++);
if (*reentrant_count < max_reentrant_count) {
task_runner->PostTask(
FROM_HERE,
base::Bind(AppendToVectorReentrantTask, base::Unretained(task_runner),
vector, reentrant_count, max_reentrant_count));
}
}
}; // namespace
class SchedulerHelperTest : public testing::Test {
public:
SchedulerHelperTest()
: clock_(new base::SimpleTestTickClock()),
mock_task_runner_(new cc::OrderedSimpleTaskRunner(clock_.get(), false)),
main_task_runner_(SchedulerTqmDelegateForTest::Create(
mock_task_runner_,
make_scoped_ptr(new TestTimeSource(clock_.get())))),
scheduler_helper_(new SchedulerHelper(
main_task_runner_,
"test.scheduler",
TRACE_DISABLED_BY_DEFAULT("test.scheduler"),
TRACE_DISABLED_BY_DEFAULT("test.scheduler.dbg"))),
default_task_runner_(scheduler_helper_->DefaultTaskRunner()) {
clock_->Advance(base::TimeDelta::FromMicroseconds(5000));
}
~SchedulerHelperTest() override {}
void TearDown() override {
// Check that all tests stop posting tasks.
mock_task_runner_->SetAutoAdvanceNowToPendingTasks(true);
while (mock_task_runner_->RunUntilIdle()) {
}
}
void RunUntilIdle() { mock_task_runner_->RunUntilIdle(); }
template <typename E>
static void CallForEachEnumValue(E first,
E last,
const char* (*function)(E)) {
for (E val = first; val < last;
val = static_cast<E>(static_cast<int>(val) + 1)) {
(*function)(val);
}
}
protected:
scoped_ptr<base::SimpleTestTickClock> clock_;
scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_;
scoped_refptr<SchedulerTqmDelegateForTest> main_task_runner_;
scoped_ptr<SchedulerHelper> scheduler_helper_;
scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
DISALLOW_COPY_AND_ASSIGN(SchedulerHelperTest);
};
TEST_F(SchedulerHelperTest, TestPostDefaultTask) {
std::vector<std::string> run_order;
default_task_runner_->PostTask(
FROM_HERE, base::Bind(&AppendToVectorTestTask, &run_order, "D1"));
default_task_runner_->PostTask(
FROM_HERE, base::Bind(&AppendToVectorTestTask, &run_order, "D2"));
default_task_runner_->PostTask(
FROM_HERE, base::Bind(&AppendToVectorTestTask, &run_order, "D3"));
default_task_runner_->PostTask(
FROM_HERE, base::Bind(&AppendToVectorTestTask, &run_order, "D4"));
RunUntilIdle();
EXPECT_THAT(run_order,
testing::ElementsAre(std::string("D1"), std::string("D2"),
std::string("D3"), std::string("D4")));
}
TEST_F(SchedulerHelperTest, TestRentrantTask) {
int count = 0;
std::vector<int> run_order;
default_task_runner_->PostTask(
FROM_HERE, base::Bind(AppendToVectorReentrantTask, default_task_runner_,
&run_order, &count, 5));
RunUntilIdle();
EXPECT_THAT(run_order, testing::ElementsAre(0, 1, 2, 3, 4));
}
TEST_F(SchedulerHelperTest, IsShutdown) {
EXPECT_FALSE(scheduler_helper_->IsShutdown());
scheduler_helper_->Shutdown();
EXPECT_TRUE(scheduler_helper_->IsShutdown());
}
TEST_F(SchedulerHelperTest, DefaultTaskRunnerRegistration) {
EXPECT_EQ(main_task_runner_->default_task_runner(),
scheduler_helper_->DefaultTaskRunner());
scheduler_helper_->Shutdown();
EXPECT_EQ(nullptr, main_task_runner_->default_task_runner());
}
namespace {
class MockTaskObserver : public base::MessageLoop::TaskObserver {
public:
MOCK_METHOD1(DidProcessTask, void(const base::PendingTask& task));
MOCK_METHOD1(WillProcessTask, void(const base::PendingTask& task));
};
void NopTask() {}
} // namespace
TEST_F(SchedulerHelperTest, ObserversNotifiedFor_DefaultTaskRunner) {
MockTaskObserver observer;
scheduler_helper_->AddTaskObserver(&observer);
scheduler_helper_->DefaultTaskRunner()->PostTask(FROM_HERE,
base::Bind(&NopTask));
EXPECT_CALL(observer, WillProcessTask(_)).Times(1);
EXPECT_CALL(observer, DidProcessTask(_)).Times(1);
RunUntilIdle();
}
TEST_F(SchedulerHelperTest, ObserversNotNotifiedFor_ControlTaskRunner) {
MockTaskObserver observer;
scheduler_helper_->AddTaskObserver(&observer);
scheduler_helper_->ControlTaskRunner()->PostTask(FROM_HERE,
base::Bind(&NopTask));
EXPECT_CALL(observer, WillProcessTask(_)).Times(0);
EXPECT_CALL(observer, DidProcessTask(_)).Times(0);
RunUntilIdle();
}
TEST_F(SchedulerHelperTest,
ObserversNotNotifiedFor_ControlAfterWakeUpTaskRunner) {
MockTaskObserver observer;
scheduler_helper_->AddTaskObserver(&observer);
scheduler_helper_->ControlAfterWakeUpTaskRunner()->PostTask(
FROM_HERE, base::Bind(&NopTask));
EXPECT_CALL(observer, WillProcessTask(_)).Times(0);
EXPECT_CALL(observer, DidProcessTask(_)).Times(0);
scheduler_helper_->ControlAfterWakeUpTaskRunner()->PumpQueue();
RunUntilIdle();
}
namespace {
class MockObserver : public SchedulerHelper::Observer {
public:
MOCK_METHOD1(OnUnregisterTaskQueue,
void(const scoped_refptr<TaskQueue>& queue));
};
} // namespace
TEST_F(SchedulerHelperTest, OnUnregisterTaskQueue) {
MockObserver observer;
scheduler_helper_->SetObserver(&observer);
scoped_refptr<TaskQueue> task_queue =
scheduler_helper_->NewTaskQueue(TaskQueue::Spec("test_queue"));
EXPECT_CALL(observer, OnUnregisterTaskQueue(_)).Times(1);
task_queue->UnregisterTaskQueue();
scheduler_helper_->SetObserver(nullptr);
}
} // namespace scheduler