Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3064)

Unified Diff: content/renderer/scheduler/renderer_scheduler_unittest.cc

Issue 664963002: content: Add RendererScheduler. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix bug in calculating remaining_compositor_priority_time Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/renderer/scheduler/renderer_scheduler_unittest.cc
diff --git a/content/renderer/scheduler/renderer_scheduler_unittest.cc b/content/renderer/scheduler/renderer_scheduler_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..8114ff5956f68e1ca11e5c2d3cf74a36c0d0da17
--- /dev/null
+++ b/content/renderer/scheduler/renderer_scheduler_unittest.cc
@@ -0,0 +1,290 @@
+// 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 "content/renderer/scheduler/renderer_scheduler.h"
+
+#include "base/callback.h"
+#include "base/test/simple_test_tick_clock.h"
+#include "base/test/test_simple_task_runner.h"
+#include "cc/output/begin_frame_args.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+class DelaySupportingTestSimpleTaskRunner : public base::TestSimpleTaskRunner {
Sami 2014/10/24 10:46:13 I wonder if we could just reuse cc/test/ordered_si
rmcilroy 2014/10/24 14:58:29 I'll look into whether this is possible.
+ public:
+ DelaySupportingTestSimpleTaskRunner(base::SimpleTestTickClock* clock)
+ : clock_(clock) { }
+
+ virtual bool PostDelayedTask(
+ const tracked_objects::Location& from_here,
+ const base::Closure& task,
+ base::TimeDelta delay) override {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ pending_tasks_.push_back(
+ base::TestPendingTask(from_here, task, clock_->NowTicks(), delay,
+ base::TestPendingTask::NESTABLE));
+ return true;
+ }
+
+ virtual bool PostNonNestableDelayedTask(
+ const tracked_objects::Location& from_here,
+ const base::Closure& task,
+ base::TimeDelta delay) override {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ pending_tasks_.push_back(
+ base::TestPendingTask(from_here, task, clock_->NowTicks(), delay,
+ base::TestPendingTask::NON_NESTABLE));
+ return true;
+ }
+
+ void RunPendingTasksIfNotDelayed() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ // Swap with a local variable to avoid re-entrancy problems.
+ std::deque<base::TestPendingTask> tasks_to_run;
+ tasks_to_run.swap(pending_tasks_);
+ for (std::deque<base::TestPendingTask>::iterator it = tasks_to_run.begin();
+ it != tasks_to_run.end(); ++it) {
+ if (it->GetTimeToRun() <= clock_->NowTicks()) {
+ it->task.Run();
+ } else {
+ pending_tasks_.push_front(*it);
+ }
+ }
+ }
+
+ void RunUntilTasksAreAllDelayed() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ while (!pending_tasks_.empty() &&
+ pending_tasks_.front().GetTimeToRun() <= clock_->NowTicks()) {
+ RunPendingTasksIfNotDelayed();
+ }
+ }
+
+ protected:
+ virtual ~DelaySupportingTestSimpleTaskRunner() { }
+
+ private:
+ base::SimpleTestTickClock* clock_;
+};
+
+class RendererSchedulerForTest : public RendererScheduler {
+ public:
+ RendererSchedulerForTest(
+ scoped_refptr<base::TestSimpleTaskRunner> task_runner,
+ base::SimpleTestTickClock* clock)
+ : RendererScheduler(task_runner),
+ clock_(clock) { }
+ virtual ~RendererSchedulerForTest() { }
+
+ protected:
+ virtual base::TimeTicks Now() const override {
+ return clock_->NowTicks();
+ }
+
+ private:
+ base::SimpleTestTickClock* clock_;
+};
+
+class RendererSchedulerTest : public testing::Test {
+ public:
+ RendererSchedulerTest()
+ : clock_(new base::SimpleTestTickClock()),
+ mock_task_runner_(new DelaySupportingTestSimpleTaskRunner(clock_.get())),
+ scheduler_(new RendererSchedulerForTest(mock_task_runner_, clock_.get())),
+ default_task_runner_(scheduler_->DefaultTaskRunner()),
+ compositor_task_runner_(scheduler_->CompositorTaskRunner()),
+ idle_task_runner_(scheduler_->IdleTaskRunner()) { }
+ virtual ~RendererSchedulerTest() { }
+
+ void RunUntilIdle() {
+ mock_task_runner_->RunUntilTasksAreAllDelayed();
+ }
+
+ void EnableIdleTasks() {
+ scheduler_->WillBeginFrame(
+ cc::BeginFrameArgs::Create(clock_->NowTicks(),
+ base::TimeTicks(),
+ base::TimeDelta::FromMilliseconds(1000)));
+ clock_->Advance(base::TimeDelta::FromMilliseconds(800));
+ scheduler_->DidCommitFrameToCompositor();
+ }
+
+ protected:
+ virtual void SetUp() override {
+ // Ensure clock is non-zero.
+ clock_->Advance(base::TimeDelta::FromMilliseconds(5000));
+ }
+
+ scoped_ptr<base::SimpleTestTickClock> clock_;
+ scoped_refptr<DelaySupportingTestSimpleTaskRunner> mock_task_runner_;
+
+ scoped_ptr<RendererScheduler> scheduler_;
+ scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
+ scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_;
+ scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(RendererSchedulerTest);
+};
+
+void OrderedTestTask(int value, int* result) {
+ *result = (*result << 4) | value;
+}
+
+void UnorderedTestTask(int value, int* result) {
+ *result += value;
+}
+
+void AppendToVectorTestTask(
+ std::vector<std::string>* vector, std::string value) {
+ vector->push_back(value);
+}
+
+void AppendToVectorIdleTestTask(
+ std::vector<std::string>* vector,
+ std::string value,
+ base::TimeTicks deadline) {
+ AppendToVectorTestTask(vector, value);
+}
+
+void IdleTestTask(
+ bool* task_run,
+ base::TimeTicks expected_deadline,
+ base::TimeTicks deadline) {
+ EXPECT_FALSE(*task_run);
+ EXPECT_EQ(expected_deadline, deadline);
+ *task_run = true;
+}
+
+void RepostingIdleTestTask(
+ scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner,
+ int* run_count,
+ base::TimeTicks deadline) {
+ if (*run_count == 0)
+ idle_task_runner->PostIdleTask(FROM_HERE,
+ base::Bind(&RepostingIdleTestTask, idle_task_runner, run_count));
+ (*run_count)++;
+}
+
+TEST_F(RendererSchedulerTest, TestPostDefaultTask) {
+ int result = 0;
+ default_task_runner_->PostTask(FROM_HERE,
+ base::Bind(OrderedTestTask, 1, &result));
+ default_task_runner_->PostTask(FROM_HERE,
+ base::Bind(OrderedTestTask, 2, &result));
+ default_task_runner_->PostTask(FROM_HERE,
+ base::Bind(OrderedTestTask, 3, &result));
+ default_task_runner_->PostTask(FROM_HERE,
+ base::Bind(OrderedTestTask, 4, &result));
+ RunUntilIdle();
+ EXPECT_EQ(0x1234, result);
+}
+
+TEST_F(RendererSchedulerTest, TestPostDefaultAndCompositor) {
+ int result = 0;
+ default_task_runner_->PostTask(FROM_HERE,
+ base::Bind(&UnorderedTestTask, 1, &result));
+ compositor_task_runner_->PostTask(FROM_HERE,
+ base::Bind(&UnorderedTestTask, 2, &result));
+ RunUntilIdle();
+ EXPECT_EQ(3, result);
+}
+
+TEST_F(RendererSchedulerTest, TestPostIdleTask) {
+ bool task_run = false;
+ base::TimeTicks expected_deadline =
+ clock_->NowTicks() + base::TimeDelta::FromMilliseconds(2300);
+
+ clock_->Advance(base::TimeDelta::FromMilliseconds(100));
+ idle_task_runner_->PostIdleTask(FROM_HERE,
+ base::Bind(&IdleTestTask, &task_run, expected_deadline));
+
+ RunUntilIdle();
+ EXPECT_FALSE(task_run); // Shouldn't run yet as no WillBeginFrame.
+
+ scheduler_->WillBeginFrame(
+ cc::BeginFrameArgs::Create(clock_->NowTicks(),
+ base::TimeTicks(),
+ base::TimeDelta::FromMilliseconds(1000)));
+ RunUntilIdle();
+ EXPECT_FALSE(task_run); // Shouldn't run as no didCommitFrameToCompositor.
+
+ clock_->Advance(base::TimeDelta::FromMilliseconds(1200));
+ scheduler_->DidCommitFrameToCompositor();
+ RunUntilIdle();
+ EXPECT_FALSE(task_run); // We missed the deadline.
+
+ scheduler_->WillBeginFrame(
+ cc::BeginFrameArgs::Create(clock_->NowTicks(),
+ base::TimeTicks(),
+ base::TimeDelta::FromMilliseconds(1000)));
+ clock_->Advance(base::TimeDelta::FromMilliseconds(800));
+ scheduler_->DidCommitFrameToCompositor();
+ RunUntilIdle();
+ EXPECT_TRUE(task_run);
+}
+
+TEST_F(RendererSchedulerTest, TestRepostingIdleTask) {
+ int run_count = 0;
+
+ idle_task_runner_->PostIdleTask(FROM_HERE,
+ base::Bind(&RepostingIdleTestTask, idle_task_runner_, &run_count));
+ EnableIdleTasks();
+ RunUntilIdle();
+ EXPECT_EQ(1, run_count);
+
+ // Reposted tasks shouldn't run until next idle period.
+ RunUntilIdle();
+ EXPECT_EQ(1, run_count);
+
+ EnableIdleTasks();
+ RunUntilIdle();
+ EXPECT_EQ(2, run_count);
+}
+
+TEST_F(RendererSchedulerTest, TestDefaultPolicy) {
+ std::vector<std::string> order;
+
+ idle_task_runner_->PostIdleTask(FROM_HERE,
+ base::Bind(&AppendToVectorIdleTestTask, &order, std::string("I1")));
+ default_task_runner_->PostTask(FROM_HERE,
+ base::Bind(&AppendToVectorTestTask, &order, std::string("D1")));
+ compositor_task_runner_->PostTask(FROM_HERE,
+ base::Bind(&AppendToVectorTestTask, &order, std::string("C1")));
+ default_task_runner_->PostTask(FROM_HERE,
+ base::Bind(&AppendToVectorTestTask, &order, std::string("D2")));
+ compositor_task_runner_->PostTask(FROM_HERE,
+ base::Bind(&AppendToVectorTestTask, &order, std::string("C2")));
+
+ EnableIdleTasks();
+ RunUntilIdle();
+ EXPECT_THAT(order, testing::ElementsAre(
+ std::string("D1"), std::string("C1"), std::string("D2"),
+ std::string("C2"), std::string("I1")));
+}
+
+TEST_F(RendererSchedulerTest, TestCompositorPolicy) {
+ std::vector<std::string> order;
+
+ idle_task_runner_->PostIdleTask(FROM_HERE,
+ base::Bind(&AppendToVectorIdleTestTask, &order, std::string("I1")));
+ default_task_runner_->PostTask(FROM_HERE,
+ base::Bind(&AppendToVectorTestTask, &order, std::string("D1")));
+ compositor_task_runner_->PostTask(FROM_HERE,
+ base::Bind(&AppendToVectorTestTask, &order, std::string("C1")));
+ default_task_runner_->PostTask(FROM_HERE,
+ base::Bind(&AppendToVectorTestTask, &order, std::string("D2")));
+ compositor_task_runner_->PostTask(FROM_HERE,
+ base::Bind(&AppendToVectorTestTask, &order, std::string("C2")));
+
+ scheduler_->DidReceiveInputEvent();
+ EnableIdleTasks();
+ RunUntilIdle();
+ EXPECT_THAT(order, testing::ElementsAre(
+ std::string("C1"), std::string("C2"), std::string("D1"),
+ std::string("D2"), std::string("I1")));
+}
+
+} // namespace content

Powered by Google App Engine
This is Rietveld 408576698