OLD | NEW |
(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 WorkerGlobalScope* createWorkerGlobalScope(std::unique_ptr<WorkerThreadStart
upData> 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, nullptr) |
| 42 { |
| 43 workerObjectProxy().m_maxDelayToCheckPendingActivityInMs = 1000; // 1 se
c |
| 44 |
| 45 m_mockWorkerLoaderProxyProvider = wrapUnique(new MockWorkerLoaderProxyPr
ovider()); |
| 46 m_workerThread = wrapUnique(new DedicatedWorkerThreadForTest(m_mockWorke
rLoaderProxyProvider.get(), workerObjectProxy())); |
| 47 |
| 48 m_mockWorkerThreadLifecycleObserver = new MockWorkerThreadLifecycleObser
ver(m_workerThread->getWorkerThreadLifecycleContext()); |
| 49 EXPECT_CALL(*m_mockWorkerThreadLifecycleObserver, contextDestroyed()).Ti
mes(1); |
| 50 } |
| 51 |
| 52 ~InProcessWorkerMessagingProxyForTest() override |
| 53 { |
| 54 EXPECT_EQ(WaitUntilMode::DontWait, m_waitUntilMode); |
| 55 m_workerThread->workerLoaderProxy()->detachProvider(m_mockWorkerLoaderPr
oxyProvider.get()); |
| 56 } |
| 57 |
| 58 enum class WaitUntilMode { |
| 59 DontWait, |
| 60 PendingActivityReported, |
| 61 PendingActivityChanged, |
| 62 ThreadTerminated, |
| 63 }; |
| 64 |
| 65 // Blocks the main thread until a specified event happens. |
| 66 void waitUntil(WaitUntilMode mode) |
| 67 { |
| 68 EXPECT_TRUE(isMainThread()); |
| 69 EXPECT_EQ(WaitUntilMode::DontWait, m_waitUntilMode); |
| 70 m_waitUntilMode = mode; |
| 71 testing::enterRunLoop(); |
| 72 } |
| 73 |
| 74 void reportPendingActivity(bool hasPendingActivity) override |
| 75 { |
| 76 EXPECT_TRUE(isMainThread()); |
| 77 bool changed = m_workerThreadHadPendingActivity != hasPendingActivity; |
| 78 InProcessWorkerMessagingProxy::reportPendingActivity(hasPendingActivity)
; |
| 79 |
| 80 if (m_waitUntilMode == WaitUntilMode::PendingActivityReported || (m_wait
UntilMode == WaitUntilMode::PendingActivityChanged && changed)) { |
| 81 m_waitUntilMode = WaitUntilMode::DontWait; |
| 82 testing::exitRunLoop(); |
| 83 } |
| 84 } |
| 85 |
| 86 void workerThreadTerminated() override |
| 87 { |
| 88 EXPECT_TRUE(isMainThread()); |
| 89 if (m_waitUntilMode != WaitUntilMode::ThreadTerminated) |
| 90 return; |
| 91 m_waitUntilMode = WaitUntilMode::DontWait; |
| 92 testing::exitRunLoop(); |
| 93 } |
| 94 |
| 95 std::unique_ptr<WorkerThread> createWorkerThread(double originTime) override |
| 96 { |
| 97 NOTREACHED(); |
| 98 return nullptr; |
| 99 } |
| 100 |
| 101 DedicatedWorkerThreadForTest* workerThread() |
| 102 { |
| 103 return static_cast<DedicatedWorkerThreadForTest*>(m_workerThread.get()); |
| 104 } |
| 105 |
| 106 private: |
| 107 std::unique_ptr<MockWorkerLoaderProxyProvider> m_mockWorkerLoaderProxyProvid
er; |
| 108 std::unique_ptr<DedicatedWorkerThreadForTest> m_workerThread; |
| 109 Persistent<MockWorkerThreadLifecycleObserver> m_mockWorkerThreadLifecycleObs
erver; |
| 110 |
| 111 WaitUntilMode m_waitUntilMode = WaitUntilMode::DontWait; |
| 112 }; |
| 113 |
| 114 using WaitUntilMode = InProcessWorkerMessagingProxyForTest::WaitUntilMode; |
| 115 |
| 116 class DedicatedWorkerTest : public ::testing::Test { |
| 117 public: |
| 118 void SetUp() override |
| 119 { |
| 120 m_page = DummyPageHolder::create(); |
| 121 m_workerMessagingProxy = wrapUnique(new InProcessWorkerMessagingProxyFor
Test(&m_page->document())); |
| 122 m_securityOrigin = SecurityOrigin::create(KURL(ParsedURLString, "http://
fake.url/")); |
| 123 } |
| 124 |
| 125 void TearDown() override |
| 126 { |
| 127 workerThread()->terminate(); |
| 128 workerMessagingProxy()->waitUntil(WaitUntilMode::ThreadTerminated); |
| 129 } |
| 130 |
| 131 void startWithSourceCode(const String& source) |
| 132 { |
| 133 std::unique_ptr<Vector<CSPHeaderAndType>> headers = wrapUnique(new Vecto
r<CSPHeaderAndType>()); |
| 134 CSPHeaderAndType headerAndType("contentSecurityPolicy", ContentSecurityP
olicyHeaderTypeReport); |
| 135 headers->append(headerAndType); |
| 136 workerThread()->start(WorkerThreadStartupData::create( |
| 137 KURL(ParsedURLString, "http://fake.url/"), |
| 138 "fake user agent", |
| 139 source, |
| 140 nullptr /* cachedMetaData */, |
| 141 DontPauseWorkerGlobalScopeOnStart, |
| 142 headers.get(), |
| 143 "" /* referrerPolicy */, |
| 144 m_securityOrigin.get(), |
| 145 nullptr /* workerClients */, |
| 146 WebAddressSpaceLocal, |
| 147 nullptr /* originTrialTokens */, |
| 148 nullptr /* workerSettings */, |
| 149 V8CacheOptionsDefault)); |
| 150 } |
| 151 |
| 152 void dispatchMessageEventOnWorkerThread() |
| 153 { |
| 154 toWorkerGlobalScope(workerThread()->globalScope())->dispatchEvent(Messag
eEvent::create(nullptr, SerializedScriptValue::create())); |
| 155 } |
| 156 |
| 157 InProcessWorkerMessagingProxyForTest* workerMessagingProxy() |
| 158 { |
| 159 return m_workerMessagingProxy.get(); |
| 160 } |
| 161 |
| 162 DedicatedWorkerThreadForTest* workerThread() |
| 163 { |
| 164 return m_workerMessagingProxy->workerThread(); |
| 165 } |
| 166 |
| 167 private: |
| 168 RefPtr<SecurityOrigin> m_securityOrigin; |
| 169 std::unique_ptr<DummyPageHolder> m_page; |
| 170 std::unique_ptr<InProcessWorkerMessagingProxyForTest> m_workerMessagingProxy
; |
| 171 }; |
| 172 |
| 173 TEST_F(DedicatedWorkerTest, PendingActivity_NoActivity) |
| 174 { |
| 175 const String sourceCode = "// Do nothing"; |
| 176 startWithSourceCode(sourceCode); |
| 177 EXPECT_FALSE(workerMessagingProxy()->hasPendingActivity()); |
| 178 |
| 179 // There should be no pending activities. |
| 180 workerMessagingProxy()->waitUntil(WaitUntilMode::PendingActivityReported); |
| 181 EXPECT_FALSE(workerMessagingProxy()->hasPendingActivity()); |
| 182 } |
| 183 |
| 184 TEST_F(DedicatedWorkerTest, PendingActivity_SetTimeout) |
| 185 { |
| 186 // Start an oneshot timer on initial script evaluation. |
| 187 const String sourceCode = "setTimeout(function() {}, 50);"; |
| 188 |
| 189 startWithSourceCode(sourceCode); |
| 190 EXPECT_FALSE(workerMessagingProxy()->hasPendingActivity()); |
| 191 |
| 192 // The initial report should be true because the active timer is counted as |
| 193 // a pending activity. |
| 194 workerMessagingProxy()->waitUntil(WaitUntilMode::PendingActivityReported); |
| 195 EXPECT_TRUE(workerMessagingProxy()->hasPendingActivity()); |
| 196 |
| 197 // The timer is fired soon and there should be no pending activities after |
| 198 // that. |
| 199 workerMessagingProxy()->waitUntil(WaitUntilMode::PendingActivityChanged); |
| 200 EXPECT_FALSE(workerMessagingProxy()->hasPendingActivity()); |
| 201 } |
| 202 |
| 203 TEST_F(DedicatedWorkerTest, PendingActivity_SetInterval) |
| 204 { |
| 205 // Start a repeated timer on initial script evaluation, and stop it when a |
| 206 // message is received. |
| 207 const String sourceCode = |
| 208 "var id = setInterval(function() {}, 1000);" |
| 209 "addEventListener('message', function(event) { clearInterval(id); });"; |
| 210 |
| 211 startWithSourceCode(sourceCode); |
| 212 EXPECT_FALSE(workerMessagingProxy()->hasPendingActivity()); |
| 213 |
| 214 // The initial report should be true because the active timer is counted as |
| 215 // a pending activity. |
| 216 workerMessagingProxy()->waitUntil(WaitUntilMode::PendingActivityReported); |
| 217 EXPECT_TRUE(workerMessagingProxy()->hasPendingActivity()); |
| 218 |
| 219 // Stop the timer. |
| 220 workerThread()->postTask(BLINK_FROM_HERE, createCrossThreadTask(&DedicatedWo
rkerTest::dispatchMessageEventOnWorkerThread, crossThreadUnretained(this))); |
| 221 |
| 222 // There should be no pending activities after the timer is stopped. |
| 223 workerMessagingProxy()->waitUntil(WaitUntilMode::PendingActivityChanged); |
| 224 EXPECT_FALSE(workerMessagingProxy()->hasPendingActivity()); |
| 225 } |
| 226 |
| 227 } // namespace blink |
OLD | NEW |