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.
6 #include "core/dom/ScriptRunner.h"
8 #include "core/dom/Document.h"
9 #include "core/dom/Element.h"
10 #include "core/dom/ScriptLoader.h"
11 #include "platform/scheduler/CancellableTaskFactory.h"
12 #include "public/platform/Platform.h"
13 #include <gmock/gmock.h>
14 #include <gtest/gtest.h>
16 using ::testing::Invoke
;
17 using ::testing::ElementsAre
;
18 using ::testing::Return
;
22 class MockScriptLoader final
: public ScriptLoader
{
24 static PassOwnPtrWillBeRawPtr
<MockScriptLoader
> create(Element
* element
)
26 return adoptPtrWillBeNoop(new MockScriptLoader(element
));
28 ~MockScriptLoader() override
{ }
30 MOCK_METHOD0(execute
, void());
31 MOCK_CONST_METHOD0(isReady
, bool());
33 explicit MockScriptLoader(Element
* element
) : ScriptLoader(element
, false, false)
38 class MockWebThread
: public WebThread
{
40 explicit MockWebThread(WebScheduler
* webScheduler
) : m_webScheduler(webScheduler
) { }
41 ~MockWebThread() override
{ }
43 bool isCurrentThread() const override
49 PlatformThreadId
threadId() const override
55 WebTaskRunner
* taskRunner() override
61 void addTaskObserver(TaskObserver
*) override
{ ASSERT_NOT_REACHED(); }
62 void removeTaskObserver(TaskObserver
*) override
{ ASSERT_NOT_REACHED(); }
64 WebScheduler
* scheduler() const override
{ return m_webScheduler
; }
67 WebScheduler
* m_webScheduler
;
70 class MockWebTaskRunner
: public WebTaskRunner
{
72 explicit MockWebTaskRunner(Deque
<OwnPtr
<WebTaskRunner::Task
>>* tasks
) : m_tasks(tasks
) { }
73 ~MockWebTaskRunner() override
{ }
75 virtual void postTask(const WebTraceLocation
&, Task
* task
)
77 m_tasks
->append(adoptPtr(task
));
80 void postDelayedTask(const WebTraceLocation
&, Task
* task
, long long delayMs
) override
85 Deque
<OwnPtr
<WebTaskRunner::Task
>>* m_tasks
; // NOT OWNED
88 class MockPlatform
: public Platform
, private WebScheduler
{
91 : m_mockWebThread(this)
92 , m_mockWebTaskRunner(&m_tasks
)
93 , m_shouldYield(false)
94 , m_shouldYieldEveryOtherTime(false) { }
96 void cryptographicallyRandomValues(unsigned char* buffer
, size_t length
) override
{ }
98 WebThread
* currentThread() override
{ return &m_mockWebThread
; }
100 WebTaskRunner
* loadingTaskRunner() override
102 return &m_mockWebTaskRunner
;
105 WebTaskRunner
* timerTaskRunner() override
107 ASSERT_NOT_REACHED();
113 if (m_tasks
.isEmpty())
115 m_tasks
.takeFirst()->run();
120 while (!m_tasks
.isEmpty())
121 m_tasks
.takeFirst()->run();
124 bool shouldYieldForHighPriorityWork() override
126 if (m_shouldYieldEveryOtherTime
)
127 m_shouldYield
= !m_shouldYield
;
128 return m_shouldYield
;
131 void setShouldYield(bool shouldYield
)
133 m_shouldYield
= shouldYield
;
136 // NOTE if we yield 100% of the time, nothing will get run.
137 void setShouldYieldEveryOtherTime(bool shouldYieldEveryOtherTime
)
139 m_shouldYieldEveryOtherTime
= shouldYieldEveryOtherTime
;
143 MockWebThread m_mockWebThread
;
144 Deque
<OwnPtr
<WebTaskRunner::Task
>> m_tasks
;
145 MockWebTaskRunner m_mockWebTaskRunner
;
147 bool m_shouldYieldEveryOtherTime
;
150 class ScriptRunnerTest
: public testing::Test
{
152 void SetUp() override
154 m_document
= Document::create();
155 m_element
= m_document
->createElement("foo", ASSERT_NO_EXCEPTION
);
157 m_scriptRunner
= ScriptRunner::create(m_document
.get());
158 m_oldPlatform
= Platform::current();
160 // Force Platform::initialize to create a new one pointing at MockPlatform.
161 Platform::initialize(&m_platform
);
162 m_platform
.setShouldYield(false);
163 m_platform
.setShouldYieldEveryOtherTime(false);
166 void TearDown() override
168 m_scriptRunner
.release();
169 Platform::initialize(m_oldPlatform
);
172 RefPtrWillBePersistent
<Document
> m_document
;
173 RefPtrWillBePersistent
<Element
> m_element
;
174 OwnPtrWillBePersistent
<ScriptRunner
> m_scriptRunner
;
175 std::vector
<int> m_order
; // gmock matchers don't work nicely with WTF::Vector
176 MockPlatform m_platform
;
177 Platform
* m_oldPlatform
; // NOT OWNED
180 TEST_F(ScriptRunnerTest
, QueueSingleScript_Async
)
182 OwnPtrWillBeRawPtr
<MockScriptLoader
> scriptLoader
= MockScriptLoader::create(m_element
.get());
183 m_scriptRunner
->queueScriptForExecution(scriptLoader
.get(), ScriptRunner::ASYNC_EXECUTION
);
184 m_scriptRunner
->notifyScriptReady(scriptLoader
.get(), ScriptRunner::ASYNC_EXECUTION
);
186 EXPECT_CALL(*scriptLoader
, execute());
187 m_platform
.runAllTasks();
190 TEST_F(ScriptRunnerTest
, QueueSingleScript_InOrder
)
192 OwnPtrWillBeRawPtr
<MockScriptLoader
> scriptLoader
= MockScriptLoader::create(m_element
.get());
193 m_scriptRunner
->queueScriptForExecution(scriptLoader
.get(), ScriptRunner::IN_ORDER_EXECUTION
);
194 m_scriptRunner
->resume();
196 EXPECT_CALL(*scriptLoader
, isReady()).WillOnce(Return(true));
197 EXPECT_CALL(*scriptLoader
, execute());
198 m_platform
.runAllTasks();
201 TEST_F(ScriptRunnerTest
, QueueMultipleScripts_InOrder
)
203 OwnPtrWillBeRawPtr
<MockScriptLoader
> scriptLoader1
= MockScriptLoader::create(m_element
.get());
204 OwnPtrWillBeRawPtr
<MockScriptLoader
> scriptLoader2
= MockScriptLoader::create(m_element
.get());
205 OwnPtrWillBeRawPtr
<MockScriptLoader
> scriptLoader3
= MockScriptLoader::create(m_element
.get());
207 m_scriptRunner
->queueScriptForExecution(scriptLoader1
.get(), ScriptRunner::IN_ORDER_EXECUTION
);
208 m_scriptRunner
->queueScriptForExecution(scriptLoader2
.get(), ScriptRunner::IN_ORDER_EXECUTION
);
209 m_scriptRunner
->queueScriptForExecution(scriptLoader3
.get(), ScriptRunner::IN_ORDER_EXECUTION
);
211 EXPECT_CALL(*scriptLoader1
, execute()).WillOnce(Invoke([this] {
212 m_order
.push_back(1);
214 EXPECT_CALL(*scriptLoader2
, execute()).WillOnce(Invoke([this] {
215 m_order
.push_back(2);
217 EXPECT_CALL(*scriptLoader3
, execute()).WillOnce(Invoke([this] {
218 m_order
.push_back(3);
221 // Make the scripts become ready in reverse order.
222 bool isReady
[] = { false, false, false };
223 EXPECT_CALL(*scriptLoader1
, isReady()).WillRepeatedly(Invoke([&isReady
] {
226 EXPECT_CALL(*scriptLoader2
, isReady()).WillRepeatedly(Invoke([&isReady
] {
229 EXPECT_CALL(*scriptLoader3
, isReady()).WillRepeatedly(Invoke([&isReady
] {
233 for (int i
= 2; i
>= 0; i
--) {
235 m_scriptRunner
->resume();
236 m_platform
.runAllTasks();
239 // But ensure the scripts were run in the expected order.
240 EXPECT_THAT(m_order
, ElementsAre(1, 2, 3));
243 TEST_F(ScriptRunnerTest
, QueueMixedScripts
)
245 OwnPtrWillBeRawPtr
<MockScriptLoader
> scriptLoader1
= MockScriptLoader::create(m_element
.get());
246 OwnPtrWillBeRawPtr
<MockScriptLoader
> scriptLoader2
= MockScriptLoader::create(m_element
.get());
247 OwnPtrWillBeRawPtr
<MockScriptLoader
> scriptLoader3
= MockScriptLoader::create(m_element
.get());
248 OwnPtrWillBeRawPtr
<MockScriptLoader
> scriptLoader4
= MockScriptLoader::create(m_element
.get());
249 OwnPtrWillBeRawPtr
<MockScriptLoader
> scriptLoader5
= MockScriptLoader::create(m_element
.get());
251 EXPECT_CALL(*scriptLoader1
, isReady()).WillRepeatedly(Return(true));
252 EXPECT_CALL(*scriptLoader2
, isReady()).WillRepeatedly(Return(true));
253 EXPECT_CALL(*scriptLoader3
, isReady()).WillRepeatedly(Return(true));
255 m_scriptRunner
->queueScriptForExecution(scriptLoader1
.get(), ScriptRunner::IN_ORDER_EXECUTION
);
256 m_scriptRunner
->queueScriptForExecution(scriptLoader2
.get(), ScriptRunner::IN_ORDER_EXECUTION
);
257 m_scriptRunner
->queueScriptForExecution(scriptLoader3
.get(), ScriptRunner::IN_ORDER_EXECUTION
);
258 m_scriptRunner
->queueScriptForExecution(scriptLoader4
.get(), ScriptRunner::ASYNC_EXECUTION
);
259 m_scriptRunner
->queueScriptForExecution(scriptLoader5
.get(), ScriptRunner::ASYNC_EXECUTION
);
261 m_scriptRunner
->notifyScriptReady(scriptLoader4
.get(), ScriptRunner::ASYNC_EXECUTION
);
262 m_scriptRunner
->notifyScriptReady(scriptLoader5
.get(), ScriptRunner::ASYNC_EXECUTION
);
264 EXPECT_CALL(*scriptLoader1
, execute()).WillOnce(Invoke([this] {
265 m_order
.push_back(1);
267 EXPECT_CALL(*scriptLoader2
, execute()).WillOnce(Invoke([this] {
268 m_order
.push_back(2);
270 EXPECT_CALL(*scriptLoader3
, execute()).WillOnce(Invoke([this] {
271 m_order
.push_back(3);
273 EXPECT_CALL(*scriptLoader4
, execute()).WillOnce(Invoke([this] {
274 m_order
.push_back(4);
276 EXPECT_CALL(*scriptLoader5
, execute()).WillOnce(Invoke([this] {
277 m_order
.push_back(5);
280 m_platform
.runAllTasks();
282 // Make sure the async scripts were run before the in-order ones.
283 EXPECT_THAT(m_order
, ElementsAre(4, 5, 1, 2, 3));
286 TEST_F(ScriptRunnerTest
, QueueMixedScripts_YieldAfterEveryExecution
)
288 OwnPtrWillBeRawPtr
<MockScriptLoader
> scriptLoader1
= MockScriptLoader::create(m_element
.get());
289 OwnPtrWillBeRawPtr
<MockScriptLoader
> scriptLoader2
= MockScriptLoader::create(m_element
.get());
290 OwnPtrWillBeRawPtr
<MockScriptLoader
> scriptLoader3
= MockScriptLoader::create(m_element
.get());
291 OwnPtrWillBeRawPtr
<MockScriptLoader
> scriptLoader4
= MockScriptLoader::create(m_element
.get());
292 OwnPtrWillBeRawPtr
<MockScriptLoader
> scriptLoader5
= MockScriptLoader::create(m_element
.get());
294 m_platform
.setShouldYieldEveryOtherTime(true);
296 EXPECT_CALL(*scriptLoader1
, isReady()).WillRepeatedly(Return(true));
297 EXPECT_CALL(*scriptLoader2
, isReady()).WillRepeatedly(Return(true));
298 EXPECT_CALL(*scriptLoader3
, isReady()).WillRepeatedly(Return(true));
300 m_scriptRunner
->queueScriptForExecution(scriptLoader1
.get(), ScriptRunner::IN_ORDER_EXECUTION
);
301 m_scriptRunner
->queueScriptForExecution(scriptLoader2
.get(), ScriptRunner::IN_ORDER_EXECUTION
);
302 m_scriptRunner
->queueScriptForExecution(scriptLoader3
.get(), ScriptRunner::IN_ORDER_EXECUTION
);
303 m_scriptRunner
->queueScriptForExecution(scriptLoader4
.get(), ScriptRunner::ASYNC_EXECUTION
);
304 m_scriptRunner
->queueScriptForExecution(scriptLoader5
.get(), ScriptRunner::ASYNC_EXECUTION
);
306 m_scriptRunner
->notifyScriptReady(scriptLoader4
.get(), ScriptRunner::ASYNC_EXECUTION
);
307 m_scriptRunner
->notifyScriptReady(scriptLoader5
.get(), ScriptRunner::ASYNC_EXECUTION
);
309 EXPECT_CALL(*scriptLoader1
, execute()).WillOnce(Invoke([this] {
310 m_order
.push_back(1);
312 EXPECT_CALL(*scriptLoader2
, execute()).WillOnce(Invoke([this] {
313 m_order
.push_back(2);
315 EXPECT_CALL(*scriptLoader3
, execute()).WillOnce(Invoke([this] {
316 m_order
.push_back(3);
318 EXPECT_CALL(*scriptLoader4
, execute()).WillOnce(Invoke([this] {
319 m_order
.push_back(4);
321 EXPECT_CALL(*scriptLoader5
, execute()).WillOnce(Invoke([this] {
322 m_order
.push_back(5);
325 m_platform
.runAllTasks();
327 // Make sure the async scripts were run before the in-order ones.
328 EXPECT_THAT(m_order
, ElementsAre(4, 5, 1, 2, 3));
331 TEST_F(ScriptRunnerTest
, QueueReentrantScript_Async
)
333 OwnPtrWillBeRawPtr
<MockScriptLoader
> scriptLoader1
= MockScriptLoader::create(m_element
.get());
334 OwnPtrWillBeRawPtr
<MockScriptLoader
> scriptLoader2
= MockScriptLoader::create(m_element
.get());
335 OwnPtrWillBeRawPtr
<MockScriptLoader
> scriptLoader3
= MockScriptLoader::create(m_element
.get());
337 m_scriptRunner
->queueScriptForExecution(scriptLoader1
.get(), ScriptRunner::ASYNC_EXECUTION
);
338 m_scriptRunner
->queueScriptForExecution(scriptLoader2
.get(), ScriptRunner::ASYNC_EXECUTION
);
339 m_scriptRunner
->queueScriptForExecution(scriptLoader3
.get(), ScriptRunner::ASYNC_EXECUTION
);
340 m_scriptRunner
->notifyScriptReady(scriptLoader1
.get(), ScriptRunner::ASYNC_EXECUTION
);
342 MockScriptLoader
* scriptLoader
= scriptLoader2
.get();
343 EXPECT_CALL(*scriptLoader1
, execute()).WillOnce(Invoke([scriptLoader
, this] {
344 m_order
.push_back(1);
345 m_scriptRunner
->notifyScriptReady(scriptLoader
, ScriptRunner::ASYNC_EXECUTION
);
348 scriptLoader
= scriptLoader3
.get();
349 EXPECT_CALL(*scriptLoader2
, execute()).WillOnce(Invoke([scriptLoader
, this] {
350 m_order
.push_back(2);
351 m_scriptRunner
->notifyScriptReady(scriptLoader
, ScriptRunner::ASYNC_EXECUTION
);
354 EXPECT_CALL(*scriptLoader3
, execute()).WillOnce(Invoke([this] {
355 m_order
.push_back(3);
358 // Make sure that re-entrant calls to notifyScriptReady don't cause ScriptRunner::execute to do
359 // more work than expected.
360 m_platform
.runSingleTask();
361 EXPECT_THAT(m_order
, ElementsAre(1));
363 m_platform
.runSingleTask();
364 EXPECT_THAT(m_order
, ElementsAre(1, 2));
366 m_platform
.runSingleTask();
367 EXPECT_THAT(m_order
, ElementsAre(1, 2, 3));
370 TEST_F(ScriptRunnerTest
, QueueReentrantScript_InOrder
)
372 OwnPtrWillBeRawPtr
<MockScriptLoader
> scriptLoader1
= MockScriptLoader::create(m_element
.get());
373 OwnPtrWillBeRawPtr
<MockScriptLoader
> scriptLoader2
= MockScriptLoader::create(m_element
.get());
374 OwnPtrWillBeRawPtr
<MockScriptLoader
> scriptLoader3
= MockScriptLoader::create(m_element
.get());
376 EXPECT_CALL(*scriptLoader1
, isReady()).WillRepeatedly(Return(true));
377 EXPECT_CALL(*scriptLoader2
, isReady()).WillRepeatedly(Return(true));
378 EXPECT_CALL(*scriptLoader3
, isReady()).WillRepeatedly(Return(true));
380 m_scriptRunner
->queueScriptForExecution(scriptLoader1
.get(), ScriptRunner::IN_ORDER_EXECUTION
);
381 m_scriptRunner
->resume();
383 MockScriptLoader
* scriptLoader
= scriptLoader2
.get();
384 EXPECT_CALL(*scriptLoader1
, execute()).WillOnce(Invoke([scriptLoader
, this] {
385 m_order
.push_back(1);
386 m_scriptRunner
->queueScriptForExecution(scriptLoader
, ScriptRunner::IN_ORDER_EXECUTION
);
387 m_scriptRunner
->resume();
390 scriptLoader
= scriptLoader3
.get();
391 EXPECT_CALL(*scriptLoader2
, execute()).WillOnce(Invoke([scriptLoader
, this] {
392 m_order
.push_back(2);
393 m_scriptRunner
->queueScriptForExecution(scriptLoader
, ScriptRunner::IN_ORDER_EXECUTION
);
394 m_scriptRunner
->resume();
397 EXPECT_CALL(*scriptLoader3
, execute()).WillOnce(Invoke([this] {
398 m_order
.push_back(3);
401 // Make sure that re-entrant calls to queueScriptForExecution don't cause ScriptRunner::execute to do
402 // more work than expected.
403 m_platform
.runSingleTask();
404 EXPECT_THAT(m_order
, ElementsAre(1));
406 m_platform
.runSingleTask();
407 EXPECT_THAT(m_order
, ElementsAre(1, 2));
409 m_platform
.runSingleTask();
410 EXPECT_THAT(m_order
, ElementsAre(1, 2, 3));
413 TEST_F(ScriptRunnerTest
, ShouldYield_AsyncScripts
)
415 OwnPtrWillBeRawPtr
<MockScriptLoader
> scriptLoader1
= MockScriptLoader::create(m_element
.get());
416 OwnPtrWillBeRawPtr
<MockScriptLoader
> scriptLoader2
= MockScriptLoader::create(m_element
.get());
417 OwnPtrWillBeRawPtr
<MockScriptLoader
> scriptLoader3
= MockScriptLoader::create(m_element
.get());
419 m_scriptRunner
->queueScriptForExecution(scriptLoader1
.get(), ScriptRunner::ASYNC_EXECUTION
);
420 m_scriptRunner
->queueScriptForExecution(scriptLoader2
.get(), ScriptRunner::ASYNC_EXECUTION
);
421 m_scriptRunner
->queueScriptForExecution(scriptLoader3
.get(), ScriptRunner::ASYNC_EXECUTION
);
422 m_scriptRunner
->notifyScriptReady(scriptLoader1
.get(), ScriptRunner::ASYNC_EXECUTION
);
423 m_scriptRunner
->notifyScriptReady(scriptLoader2
.get(), ScriptRunner::ASYNC_EXECUTION
);
424 m_scriptRunner
->notifyScriptReady(scriptLoader3
.get(), ScriptRunner::ASYNC_EXECUTION
);
426 EXPECT_CALL(*scriptLoader1
, execute()).WillOnce(Invoke([this] {
427 m_order
.push_back(1);
428 m_platform
.setShouldYield(true);
430 EXPECT_CALL(*scriptLoader2
, execute()).WillOnce(Invoke([this] {
431 m_order
.push_back(2);
433 EXPECT_CALL(*scriptLoader3
, execute()).WillOnce(Invoke([this] {
434 m_order
.push_back(3);
437 m_platform
.runSingleTask();
438 EXPECT_THAT(m_order
, ElementsAre(1));
440 // Make sure the interrupted tasks are executed next 'tick'.
441 m_platform
.setShouldYield(false);
442 m_platform
.runSingleTask();
443 EXPECT_THAT(m_order
, ElementsAre(1, 2, 3));
446 TEST_F(ScriptRunnerTest
, QueueReentrantScript_ManyAsyncScripts
)
448 OwnPtrWillBeRawPtr
<MockScriptLoader
> scriptLoaders
[20];
449 for (int i
= 0; i
< 20; i
++)
450 scriptLoaders
[i
] = nullptr;
452 for (int i
= 0; i
< 20; i
++) {
453 scriptLoaders
[i
] = MockScriptLoader::create(m_element
.get());
454 EXPECT_CALL(*scriptLoaders
[i
], isReady()).WillRepeatedly(Return(true));
456 m_scriptRunner
->queueScriptForExecution(scriptLoaders
[i
].get(), ScriptRunner::ASYNC_EXECUTION
);
459 EXPECT_CALL(*scriptLoaders
[i
], execute()).WillOnce(Invoke([this, i
] {
460 m_order
.push_back(i
);
465 m_scriptRunner
->notifyScriptReady(scriptLoaders
[0].get(), ScriptRunner::ASYNC_EXECUTION
);
466 m_scriptRunner
->notifyScriptReady(scriptLoaders
[1].get(), ScriptRunner::ASYNC_EXECUTION
);
467 m_scriptRunner
->resume();
469 EXPECT_CALL(*scriptLoaders
[0], execute()).WillOnce(Invoke([&scriptLoaders
, this] {
470 for (int i
= 2; i
< 20; i
++)
471 m_scriptRunner
->notifyScriptReady(scriptLoaders
[i
].get(), ScriptRunner::ASYNC_EXECUTION
);
472 m_scriptRunner
->resume();
473 m_order
.push_back(0);
476 m_platform
.runAllTasks();
479 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19
482 EXPECT_THAT(m_order
, testing::ElementsAreArray(expected
));
485 TEST_F(ScriptRunnerTest
, ShouldYield_InOrderScripts
)
487 OwnPtrWillBeRawPtr
<MockScriptLoader
> scriptLoader1
= MockScriptLoader::create(m_element
.get());
488 OwnPtrWillBeRawPtr
<MockScriptLoader
> scriptLoader2
= MockScriptLoader::create(m_element
.get());
489 OwnPtrWillBeRawPtr
<MockScriptLoader
> scriptLoader3
= MockScriptLoader::create(m_element
.get());
491 EXPECT_CALL(*scriptLoader1
, isReady()).WillRepeatedly(Return(true));
492 EXPECT_CALL(*scriptLoader2
, isReady()).WillRepeatedly(Return(true));
493 EXPECT_CALL(*scriptLoader3
, isReady()).WillRepeatedly(Return(true));
495 m_scriptRunner
->queueScriptForExecution(scriptLoader1
.get(), ScriptRunner::IN_ORDER_EXECUTION
);
496 m_scriptRunner
->queueScriptForExecution(scriptLoader2
.get(), ScriptRunner::IN_ORDER_EXECUTION
);
497 m_scriptRunner
->queueScriptForExecution(scriptLoader3
.get(), ScriptRunner::IN_ORDER_EXECUTION
);
498 m_scriptRunner
->resume();
500 EXPECT_CALL(*scriptLoader1
, execute()).WillOnce(Invoke([this] {
501 m_order
.push_back(1);
502 m_platform
.setShouldYield(true);
504 EXPECT_CALL(*scriptLoader2
, execute()).WillOnce(Invoke([this] {
505 m_order
.push_back(2);
507 EXPECT_CALL(*scriptLoader3
, execute()).WillOnce(Invoke([this] {
508 m_order
.push_back(3);
511 m_platform
.runSingleTask();
512 EXPECT_THAT(m_order
, ElementsAre(1));
514 // Make sure the interrupted tasks are executed next 'tick'.
515 m_platform
.setShouldYield(false);
516 m_platform
.runSingleTask();
517 EXPECT_THAT(m_order
, ElementsAre(1, 2, 3));
520 TEST_F(ScriptRunnerTest
, ShouldYield_RunsAtLastOneTask_AsyncScripts
)
522 OwnPtrWillBeRawPtr
<MockScriptLoader
> scriptLoader1
= MockScriptLoader::create(m_element
.get());
523 OwnPtrWillBeRawPtr
<MockScriptLoader
> scriptLoader2
= MockScriptLoader::create(m_element
.get());
524 OwnPtrWillBeRawPtr
<MockScriptLoader
> scriptLoader3
= MockScriptLoader::create(m_element
.get());
526 m_scriptRunner
->queueScriptForExecution(scriptLoader1
.get(), ScriptRunner::ASYNC_EXECUTION
);
527 m_scriptRunner
->queueScriptForExecution(scriptLoader2
.get(), ScriptRunner::ASYNC_EXECUTION
);
528 m_scriptRunner
->queueScriptForExecution(scriptLoader3
.get(), ScriptRunner::ASYNC_EXECUTION
);
529 m_scriptRunner
->notifyScriptReady(scriptLoader1
.get(), ScriptRunner::ASYNC_EXECUTION
);
530 m_scriptRunner
->notifyScriptReady(scriptLoader2
.get(), ScriptRunner::ASYNC_EXECUTION
);
531 m_scriptRunner
->notifyScriptReady(scriptLoader3
.get(), ScriptRunner::ASYNC_EXECUTION
);
533 m_platform
.setShouldYield(true);
534 EXPECT_CALL(*scriptLoader1
, execute()).Times(1);
535 EXPECT_CALL(*scriptLoader2
, execute()).Times(0);
536 EXPECT_CALL(*scriptLoader3
, execute()).Times(0);
538 m_platform
.runSingleTask();
540 // We can't safely distruct ScriptRunner with unexecuted MockScriptLoaders (real ScriptLoader is fine) so drain them.
541 testing::Mock::VerifyAndClear(scriptLoader2
.get());
542 testing::Mock::VerifyAndClear(scriptLoader3
.get());
543 EXPECT_CALL(*scriptLoader2
, execute()).Times(1);
544 EXPECT_CALL(*scriptLoader3
, execute()).Times(1);
546 m_platform
.runAllTasks();
549 TEST_F(ScriptRunnerTest
, ShouldYield_RunsAtLastOneTask_InOrderScripts
)
551 OwnPtrWillBeRawPtr
<MockScriptLoader
> scriptLoader1
= MockScriptLoader::create(m_element
.get());
552 OwnPtrWillBeRawPtr
<MockScriptLoader
> scriptLoader2
= MockScriptLoader::create(m_element
.get());
553 OwnPtrWillBeRawPtr
<MockScriptLoader
> scriptLoader3
= MockScriptLoader::create(m_element
.get());
555 EXPECT_CALL(*scriptLoader1
, isReady()).WillRepeatedly(Return(true));
556 EXPECT_CALL(*scriptLoader2
, isReady()).WillRepeatedly(Return(true));
557 EXPECT_CALL(*scriptLoader3
, isReady()).WillRepeatedly(Return(true));
559 m_scriptRunner
->queueScriptForExecution(scriptLoader1
.get(), ScriptRunner::IN_ORDER_EXECUTION
);
560 m_scriptRunner
->queueScriptForExecution(scriptLoader2
.get(), ScriptRunner::IN_ORDER_EXECUTION
);
561 m_scriptRunner
->queueScriptForExecution(scriptLoader3
.get(), ScriptRunner::IN_ORDER_EXECUTION
);
562 m_scriptRunner
->resume();
564 m_platform
.setShouldYield(true);
565 EXPECT_CALL(*scriptLoader1
, execute()).Times(1);
566 EXPECT_CALL(*scriptLoader2
, execute()).Times(0);
567 EXPECT_CALL(*scriptLoader3
, execute()).Times(0);
569 m_platform
.runSingleTask();
571 // We can't safely distruct ScriptRunner with unexecuted MockScriptLoaders (real ScriptLoader is fine) so drain them.
572 testing::Mock::VerifyAndClear(scriptLoader2
.get());
573 testing::Mock::VerifyAndClear(scriptLoader3
.get());
574 EXPECT_CALL(*scriptLoader2
, execute()).Times(1);
575 EXPECT_CALL(*scriptLoader3
, execute()).Times(1);
576 EXPECT_CALL(*scriptLoader2
, isReady()).WillRepeatedly(Return(true));
577 EXPECT_CALL(*scriptLoader3
, isReady()).WillRepeatedly(Return(true));
578 m_platform
.runAllTasks();