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

Side by Side Diff: third_party/WebKit/Source/core/workers/DedicatedWorkerTest.cpp

Issue 2124693002: Worker: Fix broken GC logic on Dedicated Worker while DOMTimer is set (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 4 years, 4 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 2016 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 "core/dom/CrossThreadTask.h"
6 #include "core/events/MessageEvent.h"
7 #include "core/testing/DummyPageHolder.h"
8 #include "core/workers/DedicatedWorkerGlobalScope.h"
9 #include "core/workers/DedicatedWorkerThread.h"
10 #include "core/workers/InProcessWorkerMessagingProxy.h"
11 #include "core/workers/InProcessWorkerObjectProxy.h"
12 #include "core/workers/WorkerThread.h"
13 #include "core/workers/WorkerThreadStartupData.h"
14 #include "core/workers/WorkerThreadTestHelper.h"
15 #include "platform/testing/UnitTestHelpers.h"
16 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 #include <memory>
19
20 namespace blink {
21
22 class DedicatedWorkerThreadForTest final : public DedicatedWorkerThread {
23 public:
24 DedicatedWorkerThreadForTest(
25 WorkerLoaderProxyProvider* workerLoaderProxyProvider,
26 InProcessWorkerObjectProxy& workerObjectProxy)
27 : DedicatedWorkerThread(WorkerLoaderProxy::create(workerLoaderProxyProvi der), workerObjectProxy, monotonicallyIncreasingTime())
28 {
29 m_workerBackingThread = WorkerBackingThread::createForTest("Test thread" );
30 }
31
32 WorkerOrWorkletGlobalScope* createWorkerGlobalScope(std::unique_ptr<WorkerTh readStartupData> startupData) override
33 {
34 return new DedicatedWorkerGlobalScope(startupData->m_scriptURL, startupD ata->m_userAgent, this, m_timeOrigin, std::move(startupData->m_starterOriginPriv ilegeData), std::move(startupData->m_workerClients));
35 }
36 };
37
38 class InProcessWorkerMessagingProxyForTest : public InProcessWorkerMessagingProx y {
39 public:
40 InProcessWorkerMessagingProxyForTest(ExecutionContext* executionContext)
41 : InProcessWorkerMessagingProxy(executionContext, nullptr /* workerObjec t */ , nullptr /* workerClients */)
42 {
43 workerObjectProxy().m_nextIntervalInSec = 0.1;
44 workerObjectProxy().m_maxIntervalInSec = 0.2;
45
46 m_mockWorkerLoaderProxyProvider = wrapUnique(new MockWorkerLoaderProxyPr ovider());
47 m_workerThread = wrapUnique(new DedicatedWorkerThreadForTest(m_mockWorke rLoaderProxyProvider.get(), workerObjectProxy()));
48 workerThreadCreated();
49
50 m_mockWorkerThreadLifecycleObserver = new MockWorkerThreadLifecycleObser ver(m_workerThread->getWorkerThreadLifecycleContext());
51 EXPECT_CALL(*m_mockWorkerThreadLifecycleObserver, contextDestroyed()).Ti mes(1);
52 }
53
54 ~InProcessWorkerMessagingProxyForTest() override
55 {
56 EXPECT_EQ(WaitUntilMode::DontWait, m_waitUntilMode);
57 m_workerThread->workerLoaderProxy()->detachProvider(m_mockWorkerLoaderPr oxyProvider.get());
58 }
59
60 enum class WaitUntilMode {
61 DontWait,
62 MessageConfirmed,
63 PendingActivityReported,
64 ThreadTerminated,
65 };
66
67 // Blocks the main thread until a specified event happens.
68 void waitUntil(WaitUntilMode mode)
69 {
70 EXPECT_TRUE(isMainThread());
71 EXPECT_EQ(WaitUntilMode::DontWait, m_waitUntilMode);
72 m_waitUntilMode = mode;
73 testing::enterRunLoop();
74 }
75
76 void confirmMessageFromWorkerObject() override
77 {
78 EXPECT_TRUE(isMainThread());
79 InProcessWorkerMessagingProxy::confirmMessageFromWorkerObject();
80 if (m_waitUntilMode != WaitUntilMode::MessageConfirmed)
81 return;
82 m_waitUntilMode = WaitUntilMode::DontWait;
83 testing::exitRunLoop();
84 }
85
86 void pendingActivityFinished() override
87 {
88 EXPECT_TRUE(isMainThread());
89 InProcessWorkerMessagingProxy::pendingActivityFinished();
90 if (m_waitUntilMode != WaitUntilMode::PendingActivityReported)
91 return;
92 m_waitUntilMode = WaitUntilMode::DontWait;
93 testing::exitRunLoop();
94 }
95
96 void workerThreadTerminated() override
97 {
98 EXPECT_TRUE(isMainThread());
99 if (m_waitUntilMode != WaitUntilMode::ThreadTerminated)
100 return;
101 m_waitUntilMode = WaitUntilMode::DontWait;
102 testing::exitRunLoop();
103 }
104
105 std::unique_ptr<WorkerThread> createWorkerThread(double originTime) override
106 {
107 NOTREACHED();
108 return nullptr;
109 }
110
111 DedicatedWorkerThreadForTest* workerThread()
112 {
113 return static_cast<DedicatedWorkerThreadForTest*>(m_workerThread.get());
114 }
115
116 bool workerGlobalScopeMayHavePendingActivity() const { return m_workerGlobal ScopeMayHavePendingActivity; }
117 unsigned unconfirmedMessageCount() const { return m_unconfirmedMessageCount; }
118
119 private:
120 std::unique_ptr<MockWorkerLoaderProxyProvider> m_mockWorkerLoaderProxyProvid er;
121 Persistent<MockWorkerThreadLifecycleObserver> m_mockWorkerThreadLifecycleObs erver;
122
123 WaitUntilMode m_waitUntilMode = WaitUntilMode::DontWait;
124 };
125
126 using WaitUntilMode = InProcessWorkerMessagingProxyForTest::WaitUntilMode;
127
128 class DedicatedWorkerTest : public ::testing::Test {
129 public:
130 void SetUp() override
131 {
132 m_page = DummyPageHolder::create();
133 m_workerMessagingProxy = wrapUnique(new InProcessWorkerMessagingProxyFor Test(&m_page->document()));
134 m_securityOrigin = SecurityOrigin::create(KURL(ParsedURLString, "http:// fake.url/"));
135 }
136
137 void TearDown() override
138 {
139 workerThread()->terminate();
140 workerMessagingProxy()->waitUntil(WaitUntilMode::ThreadTerminated);
141 }
142
143 void startWithSourceCode(const String& source)
144 {
145 std::unique_ptr<Vector<CSPHeaderAndType>> headers = wrapUnique(new Vecto r<CSPHeaderAndType>());
146 CSPHeaderAndType headerAndType("contentSecurityPolicy", ContentSecurityP olicyHeaderTypeReport);
147 headers->append(headerAndType);
148 workerThread()->start(WorkerThreadStartupData::create(
149 KURL(ParsedURLString, "http://fake.url/"),
150 "fake user agent",
151 source,
152 nullptr /* cachedMetaData */,
153 DontPauseWorkerGlobalScopeOnStart,
154 headers.get(),
155 "" /* referrerPolicy */,
156 m_securityOrigin.get(),
157 nullptr /* workerClients */,
158 WebAddressSpaceLocal,
159 nullptr /* originTrialTokens */,
160 nullptr /* workerSettings */,
161 V8CacheOptionsDefault));
162 }
163
164 void dispatchMessageEvent()
165 {
166 workerMessagingProxy()->postMessageToWorkerGlobalScope(nullptr /* messag e */, nullptr /* channels */);
167 }
168
169 InProcessWorkerMessagingProxyForTest* workerMessagingProxy()
170 {
171 return m_workerMessagingProxy.get();
172 }
173
174 DedicatedWorkerThreadForTest* workerThread()
175 {
176 return m_workerMessagingProxy->workerThread();
177 }
178
179 private:
180 RefPtr<SecurityOrigin> m_securityOrigin;
181 std::unique_ptr<DummyPageHolder> m_page;
182 std::unique_ptr<InProcessWorkerMessagingProxyForTest> m_workerMessagingProxy ;
183 };
184
185 TEST_F(DedicatedWorkerTest, PendingActivity_NoActivity)
186 {
187 const String sourceCode = "// Do nothing";
188 startWithSourceCode(sourceCode);
189
190 // Worker initialization should be counted as a pending activity.
191 EXPECT_TRUE(workerMessagingProxy()->workerGlobalScopeMayHavePendingActivity( ));
192
193 // There should be no pending activities after the initialization.
194 workerMessagingProxy()->waitUntil(WaitUntilMode::PendingActivityReported);
195 EXPECT_FALSE(workerMessagingProxy()->hasPendingActivity());
196 }
197
198 TEST_F(DedicatedWorkerTest, PendingActivity_SetTimeout)
199 {
200 // Start an oneshot timer on initial script evaluation.
201 const String sourceCode = "setTimeout(function() {}, 50);";
202 startWithSourceCode(sourceCode);
203
204 // Worker initialization should be counted as a pending activity.
205 EXPECT_TRUE(workerMessagingProxy()->workerGlobalScopeMayHavePendingActivity( ));
206
207 // The timer is fired soon and there should be no pending activities after
208 // that.
209 workerMessagingProxy()->waitUntil(WaitUntilMode::PendingActivityReported);
210 EXPECT_FALSE(workerMessagingProxy()->hasPendingActivity());
211 }
212
213 TEST_F(DedicatedWorkerTest, PendingActivity_SetInterval)
214 {
215 // Start a repeated timer on initial script evaluation, and stop it when a
216 // message is received.
217 const String sourceCode =
218 "var id = setInterval(function() {}, 50);"
219 "addEventListener('message', function(event) { clearInterval(id); });";
220 startWithSourceCode(sourceCode);
221
222 // Worker initialization should be counted as a pending activity.
223 EXPECT_TRUE(workerMessagingProxy()->workerGlobalScopeMayHavePendingActivity( ));
224
225 // Stop the timer.
226 dispatchMessageEvent();
227 EXPECT_EQ(1u, workerMessagingProxy()->unconfirmedMessageCount());
228 EXPECT_TRUE(workerMessagingProxy()->workerGlobalScopeMayHavePendingActivity( ));
229 workerMessagingProxy()->waitUntil(WaitUntilMode::MessageConfirmed);
230 EXPECT_EQ(0u, workerMessagingProxy()->unconfirmedMessageCount());
231 EXPECT_TRUE(workerMessagingProxy()->workerGlobalScopeMayHavePendingActivity( ));
232
233 // There should be no pending activities after the timer is stopped.
234 workerMessagingProxy()->waitUntil(WaitUntilMode::PendingActivityReported);
235 EXPECT_FALSE(workerMessagingProxy()->workerGlobalScopeMayHavePendingActivity ());
236 }
237
238 TEST_F(DedicatedWorkerTest, PendingActivity_SetTimeoutOnMessageEvent)
239 {
240 // Start an oneshot timer on a message event.
241 const String sourceCode =
242 "addEventListener('message', function(event) {"
243 " setTimeout(function() {}, 50);"
244 "});";
245 startWithSourceCode(sourceCode);
246
247 // Worker initialization should be counted as a pending activity.
248 EXPECT_TRUE(workerMessagingProxy()->workerGlobalScopeMayHavePendingActivity( ));
249 workerMessagingProxy()->waitUntil(WaitUntilMode::PendingActivityReported);
250 EXPECT_FALSE(workerMessagingProxy()->workerGlobalScopeMayHavePendingActivity ());
251
252 // A message starts the oneshot timer that is counted as a pending activity.
253 dispatchMessageEvent();
254 EXPECT_EQ(1u, workerMessagingProxy()->unconfirmedMessageCount());
255 EXPECT_TRUE(workerMessagingProxy()->workerGlobalScopeMayHavePendingActivity( ));
256 workerMessagingProxy()->waitUntil(WaitUntilMode::MessageConfirmed);
257 EXPECT_EQ(0u, workerMessagingProxy()->unconfirmedMessageCount());
258 EXPECT_TRUE(workerMessagingProxy()->workerGlobalScopeMayHavePendingActivity( ));
259
260 // The timer is fired soon and there should be no pending activities after
261 // that.
262 workerMessagingProxy()->waitUntil(WaitUntilMode::PendingActivityReported);
263 EXPECT_FALSE(workerMessagingProxy()->workerGlobalScopeMayHavePendingActivity ());
264 }
265
266 TEST_F(DedicatedWorkerTest, PendingActivity_SetIntervalOnMessageEvent)
267 {
268 // Start a repeated timer on a message event, and stop it when another
269 // message is received.
270 const String sourceCode =
271 "var count = 0;"
272 "var id;"
273 "addEventListener('message', function(event) {"
274 " if (count++ == 0) {"
275 " id = setInterval(function() {}, 50);"
276 " } else {"
277 " clearInterval(id);"
278 " }"
279 "});";
280 startWithSourceCode(sourceCode);
281
282 // Worker initialization should be counted as a pending activity.
283 EXPECT_TRUE(workerMessagingProxy()->workerGlobalScopeMayHavePendingActivity( ));
284 workerMessagingProxy()->waitUntil(WaitUntilMode::PendingActivityReported);
285 EXPECT_FALSE(workerMessagingProxy()->workerGlobalScopeMayHavePendingActivity ());
286
287 // The first message event sets the active timer that is counted as a
288 // pending activity.
289 dispatchMessageEvent();
290 EXPECT_EQ(1u, workerMessagingProxy()->unconfirmedMessageCount());
291 EXPECT_TRUE(workerMessagingProxy()->workerGlobalScopeMayHavePendingActivity( ));
292 workerMessagingProxy()->waitUntil(WaitUntilMode::MessageConfirmed);
293 EXPECT_EQ(0u, workerMessagingProxy()->unconfirmedMessageCount());
294 EXPECT_TRUE(workerMessagingProxy()->workerGlobalScopeMayHavePendingActivity( ));
295
296 // Run the message loop for a while to make sure the timer is counted as a
297 // pending activity until it's stopped.
298 testing::runDelayedTasks(1000);
299 EXPECT_TRUE(workerMessagingProxy()->workerGlobalScopeMayHavePendingActivity( ));
300
301 // Stop the timer.
302 dispatchMessageEvent();
303 EXPECT_EQ(1u, workerMessagingProxy()->unconfirmedMessageCount());
304 EXPECT_TRUE(workerMessagingProxy()->workerGlobalScopeMayHavePendingActivity( ));
305 workerMessagingProxy()->waitUntil(WaitUntilMode::MessageConfirmed);
306 EXPECT_EQ(0u, workerMessagingProxy()->unconfirmedMessageCount());
307 EXPECT_TRUE(workerMessagingProxy()->workerGlobalScopeMayHavePendingActivity( ));
308
309 // There should be no pending activities after the timer is stopped.
310 workerMessagingProxy()->waitUntil(WaitUntilMode::PendingActivityReported);
311 EXPECT_FALSE(workerMessagingProxy()->workerGlobalScopeMayHavePendingActivity ());
312 }
313
314 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698