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

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

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

Powered by Google App Engine
This is Rietveld 408576698