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

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

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

Powered by Google App Engine
This is Rietveld 408576698