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

Side by Side Diff: third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThreadTest.cpp

Issue 1728803002: Rename WorkerThread to WorkerScript Base URL: https://chromium.googlesource.com/chromium/src.git@workerscript-controller
Patch Set: Created 4 years, 9 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 unified diff | Download patch
OLDNEW
(Empty)
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.
4
5 #include "modules/compositorworker/CompositorWorkerThread.h"
6
7 #include "bindings/core/v8/ScriptSourceCode.h"
8 #include "bindings/core/v8/V8GCController.h"
9 #include "core/inspector/ConsoleMessage.h"
10 #include "core/testing/DummyPageHolder.h"
11 #include "core/workers/WorkerLoaderProxy.h"
12 #include "core/workers/WorkerObjectProxy.h"
13 #include "core/workers/WorkerThreadStartupData.h"
14 #include "platform/NotImplemented.h"
15 #include "platform/ThreadSafeFunctional.h"
16 #include "platform/WaitableEvent.h"
17 #include "platform/heap/Handle.h"
18 #include "platform/testing/TestingPlatformSupport.h"
19 #include "platform/testing/UnitTestHelpers.h"
20 #include "public/platform/Platform.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22
23 namespace blink {
24 namespace {
25
26 class TestCompositorWorkerThread : public CompositorWorkerThread {
27 public:
28 TestCompositorWorkerThread(WorkerLoaderProxyProvider* loaderProxyProvider, W orkerObjectProxy& objectProxy, double timeOrigin, WaitableEvent* startEvent)
29 : CompositorWorkerThread(WorkerLoaderProxy::create(loaderProxyProvider), objectProxy, timeOrigin)
30 , m_startEvent(startEvent)
31 {
32 }
33
34 ~TestCompositorWorkerThread() override {}
35
36 void setCallbackAfterV8Termination(PassOwnPtr<Function<void()>> callback)
37 {
38 m_v8TerminationCallback = callback;
39 }
40
41 private:
42 // WorkerThread:
43 void didStartWorkerThread() override
44 {
45 m_startEvent->signal();
46 }
47 void terminateV8Execution() override
48 {
49 CompositorWorkerThread::terminateV8Execution();
50 if (m_v8TerminationCallback)
51 (*m_v8TerminationCallback)();
52 }
53
54 void willDestroyIsolate() override
55 {
56 v8::Isolate::GetCurrent()->RequestGarbageCollectionForTesting(v8::Isolat e::kFullGarbageCollection);
57 Heap::collectAllGarbage();
58 CompositorWorkerThread::willDestroyIsolate();
59 }
60
61 WaitableEvent* m_startEvent;
62 OwnPtr<Function<void()>> m_v8TerminationCallback;
63 };
64
65 // A null WorkerObjectProxy, supplied when creating CompositorWorkerThreads.
66 class TestCompositorWorkerObjectProxy : public WorkerObjectProxy {
67 public:
68 static PassOwnPtr<TestCompositorWorkerObjectProxy> create(ExecutionContext* context)
69 {
70 return adoptPtr(new TestCompositorWorkerObjectProxy(context));
71 }
72
73 // (Empty) WorkerReportingProxy implementation:
74 virtual void reportException(const String& errorMessage, int lineNumber, int columnNumber, const String& sourceURL, int exceptionId) {}
75 void reportConsoleMessage(PassRefPtrWillBeRawPtr<ConsoleMessage>) override { }
76 void postMessageToPageInspector(const String&) override {}
77 void postWorkerConsoleAgentEnabled() override {}
78
79 void didEvaluateWorkerScript(bool success) override {}
80 void workerGlobalScopeStarted(WorkerGlobalScope*) override {}
81 void workerGlobalScopeClosed() override {}
82 void workerThreadTerminated() override {}
83 void willDestroyWorkerGlobalScope() override {}
84
85 ExecutionContext* executionContext() override { return m_executionContext.ge t(); }
86
87 private:
88 TestCompositorWorkerObjectProxy(ExecutionContext* context)
89 : WorkerObjectProxy(nullptr)
90 , m_executionContext(context)
91 {
92 }
93
94 RefPtrWillBePersistent<ExecutionContext> m_executionContext;
95 };
96
97 class CompositorWorkerTestPlatform : public TestingPlatformSupport {
98 public:
99 CompositorWorkerTestPlatform()
100 : m_thread(adoptPtr(m_oldPlatform->createThread("Compositor")))
101 {
102 }
103
104 WebThread* compositorThread() const override
105 {
106 return m_thread.get();
107 }
108
109 WebCompositorSupport* compositorSupport() override { return &m_compositorSup port; }
110
111 private:
112 OwnPtr<WebThread> m_thread;
113 TestingCompositorSupport m_compositorSupport;
114 };
115
116 } // namespace
117
118 class CompositorWorkerThreadTest : public ::testing::Test {
119 public:
120 void SetUp() override
121 {
122 m_page = DummyPageHolder::create();
123 m_objectProxy = TestCompositorWorkerObjectProxy::create(&m_page->documen t());
124 m_securityOrigin = SecurityOrigin::create(KURL(ParsedURLString, "http:// fake.url/"));
125 }
126
127 void TearDown() override
128 {
129 ASSERT(!hasThread());
130 ASSERT(!hasIsolate());
131 m_page.clear();
132 }
133
134 PassRefPtr<TestCompositorWorkerThread> createCompositorWorker(WaitableEvent* startEvent)
135 {
136 TestCompositorWorkerThread* workerThread = new TestCompositorWorkerThrea d(nullptr, *m_objectProxy, 0, startEvent);
137 OwnPtrWillBeRawPtr<WorkerClients> clients = nullptr;
138 workerThread->start(WorkerThreadStartupData::create(
139 KURL(ParsedURLString, "http://fake.url/"),
140 "fake user agent",
141 "//fake source code",
142 nullptr,
143 DontPauseWorkerGlobalScopeOnStart,
144 adoptPtr(new Vector<CSPHeaderAndType>()),
145 m_securityOrigin.get(),
146 clients.release(),
147 V8CacheOptionsDefault));
148 return adoptRef(workerThread);
149 }
150
151 void createWorkerAdapter(RefPtr<CompositorWorkerThread>* workerThread, Waita bleEvent* creationEvent)
152 {
153 *workerThread = createCompositorWorker(creationEvent);
154 }
155
156 // Attempts to run some simple script for |worker|.
157 void checkWorkerCanExecuteScript(WorkerThread* worker)
158 {
159 OwnPtr<WaitableEvent> waitEvent = adoptPtr(new WaitableEvent());
160 worker->backingThread().platformThread().taskRunner()->postTask(BLINK_FR OM_HERE, threadSafeBind(&CompositorWorkerThreadTest::executeScriptInWorker, Allo wCrossThreadAccess(this),
161 AllowCrossThreadAccess(worker), AllowCrossThreadAccess(waitEvent.get ())));
162 waitEvent->wait();
163 }
164
165 void waitForWaitableEventAfterIteratingCurrentLoop(WaitableEvent* waitEvent)
166 {
167 testing::runPendingTasks();
168 waitEvent->wait();
169 }
170
171 bool hasThread() const
172 {
173 return CompositorWorkerThread::hasThreadForTest();
174 }
175
176 bool hasIsolate() const
177 {
178 return CompositorWorkerThread::hasIsolateForTest();
179 }
180
181 private:
182 void executeScriptInWorker(WorkerThread* worker, WaitableEvent* waitEvent)
183 {
184 WorkerOrWorkletScriptController* scriptController = worker->workerGlobal Scope()->scriptController();
185 bool evaluateResult = scriptController->evaluate(ScriptSourceCode("var c ounter = 0; ++counter;"));
186 ASSERT_UNUSED(evaluateResult, evaluateResult);
187 waitEvent->signal();
188 }
189
190 OwnPtr<DummyPageHolder> m_page;
191 RefPtr<SecurityOrigin> m_securityOrigin;
192 OwnPtr<WorkerObjectProxy> m_objectProxy;
193 CompositorWorkerTestPlatform m_testPlatform;
194 };
195
196 TEST_F(CompositorWorkerThreadTest, Basic)
197 {
198 OwnPtr<WaitableEvent> creationEvent = adoptPtr(new WaitableEvent());
199 RefPtr<CompositorWorkerThread> compositorWorker = createCompositorWorker(cre ationEvent.get());
200 waitForWaitableEventAfterIteratingCurrentLoop(creationEvent.get());
201 checkWorkerCanExecuteScript(compositorWorker.get());
202 compositorWorker->terminateAndWait();
203 }
204
205 // Tests that the same WebThread is used for new workers if the WebThread is sti ll alive.
206 TEST_F(CompositorWorkerThreadTest, CreateSecondAndTerminateFirst)
207 {
208 // Create the first worker and wait until it is initialized.
209 OwnPtr<WaitableEvent> firstCreationEvent = adoptPtr(new WaitableEvent());
210 RefPtr<CompositorWorkerThread> firstWorker = createCompositorWorker(firstCre ationEvent.get());
211 WebThreadSupportingGC* firstThread = CompositorWorkerThread::sharedBackingTh read();
212 ASSERT(firstThread);
213 waitForWaitableEventAfterIteratingCurrentLoop(firstCreationEvent.get());
214 v8::Isolate* firstIsolate = firstWorker->isolate();
215 ASSERT(firstIsolate);
216
217 // Create the second worker and immediately destroy the first worker.
218 OwnPtr<WaitableEvent> secondCreationEvent = adoptPtr(new WaitableEvent());
219 RefPtr<CompositorWorkerThread> secondWorker = createCompositorWorker(secondC reationEvent.get());
220 firstWorker->terminateAndWait();
221
222 // Wait until the second worker is initialized. Verify that the second worke r is using the same
223 // thread and Isolate as the first worker.
224 WebThreadSupportingGC* secondThread = CompositorWorkerThread::sharedBackingT hread();
225 ASSERT(secondThread);
226 waitForWaitableEventAfterIteratingCurrentLoop(secondCreationEvent.get());
227 EXPECT_EQ(firstThread, secondThread);
228
229 v8::Isolate* secondIsolate = secondWorker->isolate();
230 ASSERT(secondIsolate);
231 EXPECT_EQ(firstIsolate, secondIsolate);
232
233 // Verify that the worker can still successfully execute script.
234 checkWorkerCanExecuteScript(secondWorker.get());
235
236 secondWorker->terminateAndWait();
237 }
238
239 static void checkCurrentIsolate(v8::Isolate* isolate, WaitableEvent* event)
240 {
241 EXPECT_EQ(v8::Isolate::GetCurrent(), isolate);
242 event->signal();
243 }
244
245 // Tests that a new WebThread is created if all existing workers are terminated before a new worker is created.
246 TEST_F(CompositorWorkerThreadTest, TerminateFirstAndCreateSecond)
247 {
248 // Create the first worker, wait until it is initialized, and terminate it.
249 OwnPtr<WaitableEvent> creationEvent = adoptPtr(new WaitableEvent());
250 RefPtr<CompositorWorkerThread> compositorWorker = createCompositorWorker(cre ationEvent.get());
251 WebThreadSupportingGC* firstThread = CompositorWorkerThread::sharedBackingTh read();
252 waitForWaitableEventAfterIteratingCurrentLoop(creationEvent.get());
253 ASSERT(compositorWorker->isolate());
254 compositorWorker->terminateAndWait();
255
256 // Create the second worker. Verify that the second worker lives in a differ ent WebThread since the first
257 // thread will have been destroyed after destroying the first worker.
258 creationEvent = adoptPtr(new WaitableEvent());
259 compositorWorker = createCompositorWorker(creationEvent.get());
260 WebThreadSupportingGC* secondThread = CompositorWorkerThread::sharedBackingT hread();
261 EXPECT_NE(firstThread, secondThread);
262 waitForWaitableEventAfterIteratingCurrentLoop(creationEvent.get());
263
264 // Jump over to the worker's thread to verify that the Isolate is set up cor rectly and execute script.
265 OwnPtr<WaitableEvent> checkEvent = adoptPtr(new WaitableEvent());
266 secondThread->platformThread().taskRunner()->postTask(BLINK_FROM_HERE, threa dSafeBind(&checkCurrentIsolate, AllowCrossThreadAccess(compositorWorker->isolate ()), AllowCrossThreadAccess(checkEvent.get())));
267 waitForWaitableEventAfterIteratingCurrentLoop(checkEvent.get());
268 checkWorkerCanExecuteScript(compositorWorker.get());
269
270 compositorWorker->terminateAndWait();
271 }
272
273 // Tests that v8::Isolate and WebThread are correctly set-up if a worker is crea ted while another is terminating.
274 TEST_F(CompositorWorkerThreadTest, CreatingSecondDuringTerminationOfFirst)
275 {
276 OwnPtr<WaitableEvent> firstCreationEvent = adoptPtr(new WaitableEvent());
277 RefPtr<TestCompositorWorkerThread> firstWorker = createCompositorWorker(firs tCreationEvent.get());
278 waitForWaitableEventAfterIteratingCurrentLoop(firstCreationEvent.get());
279 v8::Isolate* firstIsolate = firstWorker->isolate();
280 ASSERT(firstIsolate);
281
282 // Request termination of the first worker, and set-up to make sure the seco nd worker is created right as
283 // the first worker terminates its isolate.
284 OwnPtr<WaitableEvent> secondCreationEvent = adoptPtr(new WaitableEvent());
285 RefPtr<CompositorWorkerThread> secondWorker;
286 firstWorker->setCallbackAfterV8Termination(bind(&CompositorWorkerThreadTest: :createWorkerAdapter, this, &secondWorker, secondCreationEvent.get()));
287 firstWorker->terminateAndWait();
288 ASSERT(secondWorker);
289
290 waitForWaitableEventAfterIteratingCurrentLoop(secondCreationEvent.get());
291 v8::Isolate* secondIsolate = secondWorker->isolate();
292 ASSERT(secondIsolate);
293 EXPECT_EQ(firstIsolate, secondIsolate);
294
295 // Verify that the isolate can run some scripts correctly in the second work er.
296 checkWorkerCanExecuteScript(secondWorker.get());
297 secondWorker->terminateAndWait();
298 }
299
300 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698