1 // Copyright 2015 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.
5 #include "content/renderer/scheduler/webthread_impl_for_renderer_scheduler.h"
7 #include "base/run_loop.h"
8 #include "content/child/scheduler/scheduler_message_loop_delegate.h"
9 #include "content/renderer/scheduler/renderer_scheduler_impl.h"
10 #include "testing/gmock/include/gmock/gmock.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "third_party/WebKit/public/platform/WebTraceLocation.h"
17 const int kWorkBatchSize
= 2;
19 class MockTask
: public blink::WebThread::Task
{
21 MOCK_METHOD0(run
, void());
24 class MockTaskObserver
: public blink::WebThread::TaskObserver
{
26 MOCK_METHOD0(willProcessTask
, void());
27 MOCK_METHOD0(didProcessTask
, void());
31 class WebThreadImplForRendererSchedulerTest
: public testing::Test
{
33 WebThreadImplForRendererSchedulerTest()
34 : scheduler_(SchedulerMessageLoopDelegate::Create(&message_loop_
)),
35 default_task_runner_(scheduler_
.DefaultTaskRunner()),
36 thread_(&scheduler_
) {}
38 ~WebThreadImplForRendererSchedulerTest() override
{}
40 void SetWorkBatchSizeForTesting(size_t work_batch_size
) {
41 scheduler_
.SetWorkBatchSizeForTesting(work_batch_size
);
45 void EatDefaultTask(MockTaskObserver
* observer
) {
46 // The scheduler posts one extra DoWork() task automatically.
47 EXPECT_CALL(*observer
, willProcessTask());
48 EXPECT_CALL(*observer
, didProcessTask());
51 base::MessageLoop message_loop_
;
52 RendererSchedulerImpl scheduler_
;
53 scoped_refptr
<base::SingleThreadTaskRunner
> default_task_runner_
;
54 WebThreadImplForRendererScheduler thread_
;
56 DISALLOW_COPY_AND_ASSIGN(WebThreadImplForRendererSchedulerTest
);
59 TEST_F(WebThreadImplForRendererSchedulerTest
, TestTaskObserver
) {
60 MockTaskObserver observer
;
61 thread_
.addTaskObserver(&observer
);
62 scoped_ptr
<MockTask
> task(new MockTask());
65 testing::InSequence sequence
;
66 EXPECT_CALL(observer
, willProcessTask());
67 EXPECT_CALL(*task
, run());
68 EXPECT_CALL(observer
, didProcessTask());
70 EatDefaultTask(&observer
);
73 thread_
.postTask(blink::WebTraceLocation(), task
.release());
74 message_loop_
.RunUntilIdle();
75 thread_
.removeTaskObserver(&observer
);
78 TEST_F(WebThreadImplForRendererSchedulerTest
, TestWorkBatchWithOneTask
) {
79 MockTaskObserver observer
;
80 thread_
.addTaskObserver(&observer
);
81 scoped_ptr
<MockTask
> task(new MockTask());
83 scheduler_
.SetWorkBatchSizeForTesting(kWorkBatchSize
);
85 testing::InSequence sequence
;
86 EXPECT_CALL(observer
, willProcessTask());
87 EXPECT_CALL(*task
, run());
88 EXPECT_CALL(observer
, didProcessTask());
90 EatDefaultTask(&observer
);
93 thread_
.postTask(blink::WebTraceLocation(), task
.release());
94 message_loop_
.RunUntilIdle();
95 thread_
.removeTaskObserver(&observer
);
98 TEST_F(WebThreadImplForRendererSchedulerTest
, TestWorkBatchWithTwoTasks
) {
99 MockTaskObserver observer
;
100 thread_
.addTaskObserver(&observer
);
101 scoped_ptr
<MockTask
> task1(new MockTask());
102 scoped_ptr
<MockTask
> task2(new MockTask());
104 scheduler_
.SetWorkBatchSizeForTesting(kWorkBatchSize
);
106 testing::InSequence sequence
;
107 EXPECT_CALL(observer
, willProcessTask());
108 EXPECT_CALL(*task1
, run());
109 EXPECT_CALL(observer
, didProcessTask());
111 EXPECT_CALL(observer
, willProcessTask());
112 EXPECT_CALL(*task2
, run());
113 EXPECT_CALL(observer
, didProcessTask());
115 EatDefaultTask(&observer
);
118 thread_
.postTask(blink::WebTraceLocation(), task1
.release());
119 thread_
.postTask(blink::WebTraceLocation(), task2
.release());
120 message_loop_
.RunUntilIdle();
121 thread_
.removeTaskObserver(&observer
);
124 TEST_F(WebThreadImplForRendererSchedulerTest
, TestWorkBatchWithThreeTasks
) {
125 MockTaskObserver observer
;
126 thread_
.addTaskObserver(&observer
);
127 scoped_ptr
<MockTask
> task1(new MockTask());
128 scoped_ptr
<MockTask
> task2(new MockTask());
129 scoped_ptr
<MockTask
> task3(new MockTask());
131 scheduler_
.SetWorkBatchSizeForTesting(kWorkBatchSize
);
133 testing::InSequence sequence
;
134 EXPECT_CALL(observer
, willProcessTask());
135 EXPECT_CALL(*task1
, run());
136 EXPECT_CALL(observer
, didProcessTask());
138 EXPECT_CALL(observer
, willProcessTask());
139 EXPECT_CALL(*task2
, run());
140 EXPECT_CALL(observer
, didProcessTask());
142 EXPECT_CALL(observer
, willProcessTask());
143 EXPECT_CALL(*task3
, run());
144 EXPECT_CALL(observer
, didProcessTask());
146 EatDefaultTask(&observer
);
149 thread_
.postTask(blink::WebTraceLocation(), task1
.release());
150 thread_
.postTask(blink::WebTraceLocation(), task2
.release());
151 thread_
.postTask(blink::WebTraceLocation(), task3
.release());
152 message_loop_
.RunUntilIdle();
153 thread_
.removeTaskObserver(&observer
);
156 class ExitRunLoopTask
: public blink::WebThread::Task
{
158 ExitRunLoopTask(base::RunLoop
* run_loop
) : run_loop_(run_loop
) {}
160 virtual void run() { run_loop_
->Quit(); }
163 base::RunLoop
* run_loop_
;
166 void EnterRunLoop(base::MessageLoop
* message_loop
, blink::WebThread
* thread
) {
167 // Note: WebThreads do not support nested run loops, which is why we use a
168 // run loop directly.
169 base::RunLoop run_loop
;
170 thread
->postTask(blink::WebTraceLocation(), new ExitRunLoopTask(&run_loop
));
171 message_loop
->SetNestableTasksAllowed(true);
175 TEST_F(WebThreadImplForRendererSchedulerTest
, TestNestedRunLoop
) {
176 MockTaskObserver observer
;
177 thread_
.addTaskObserver(&observer
);
180 testing::InSequence sequence
;
182 // One callback for EnterRunLoop.
183 EXPECT_CALL(observer
, willProcessTask());
185 // A pair for ExitRunLoopTask.
186 EXPECT_CALL(observer
, willProcessTask());
187 EXPECT_CALL(observer
, didProcessTask());
189 // A final callback for EnterRunLoop.
190 EXPECT_CALL(observer
, didProcessTask());
192 EatDefaultTask(&observer
);
195 message_loop_
.PostTask(
196 FROM_HERE
, base::Bind(&EnterRunLoop
, base::Unretained(&message_loop_
),
197 base::Unretained(&thread_
)));
198 message_loop_
.RunUntilIdle();
199 thread_
.removeTaskObserver(&observer
);
202 } // namespace content