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

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

Powered by Google App Engine
This is Rietveld 408576698