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

Unified 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: 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 side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/workers/DedicatedWorkerTest.cpp
diff --git a/third_party/WebKit/Source/core/workers/DedicatedWorkerTest.cpp b/third_party/WebKit/Source/core/workers/DedicatedWorkerTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3ebc568c39a2755491eac5d115a7e776da0962e6
--- /dev/null
+++ b/third_party/WebKit/Source/core/workers/DedicatedWorkerTest.cpp
@@ -0,0 +1,227 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/dom/CrossThreadTask.h"
+#include "core/events/MessageEvent.h"
+#include "core/testing/DummyPageHolder.h"
+#include "core/workers/DedicatedWorkerGlobalScope.h"
+#include "core/workers/DedicatedWorkerThread.h"
+#include "core/workers/InProcessWorkerMessagingProxy.h"
+#include "core/workers/InProcessWorkerObjectProxy.h"
+#include "core/workers/WorkerThread.h"
+#include "core/workers/WorkerThreadStartupData.h"
+#include "core/workers/WorkerThreadTestHelper.h"
+#include "platform/testing/UnitTestHelpers.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include <memory>
+
+namespace blink {
+
+class DedicatedWorkerThreadForTest final : public DedicatedWorkerThread {
+public:
+ DedicatedWorkerThreadForTest(
+ WorkerLoaderProxyProvider* workerLoaderProxyProvider,
+ InProcessWorkerObjectProxy& workerObjectProxy)
+ : DedicatedWorkerThread(WorkerLoaderProxy::create(workerLoaderProxyProvider), workerObjectProxy, monotonicallyIncreasingTime())
+ {
+ m_workerBackingThread = WorkerBackingThread::createForTest("Test thread");
+ }
+
+ WorkerGlobalScope* createWorkerGlobalScope(std::unique_ptr<WorkerThreadStartupData> startupData) override
+ {
+ return new DedicatedWorkerGlobalScope(startupData->m_scriptURL, startupData->m_userAgent, this, m_timeOrigin, std::move(startupData->m_starterOriginPrivilegeData), std::move(startupData->m_workerClients));
+ };
+};
+
+class InProcessWorkerMessagingProxyForTest : public InProcessWorkerMessagingProxy {
+public:
+ InProcessWorkerMessagingProxyForTest(ExecutionContext* executionContext)
+ : InProcessWorkerMessagingProxy(executionContext, nullptr, nullptr)
+ {
+ workerObjectProxy().m_maxDelayToCheckPendingActivityInMs = 1000; // 1 sec
+
+ m_mockWorkerLoaderProxyProvider = wrapUnique(new MockWorkerLoaderProxyProvider());
+ m_workerThread = wrapUnique(new DedicatedWorkerThreadForTest(m_mockWorkerLoaderProxyProvider.get(), workerObjectProxy()));
+
+ m_mockWorkerThreadLifecycleObserver = new MockWorkerThreadLifecycleObserver(m_workerThread->getWorkerThreadLifecycleContext());
+ EXPECT_CALL(*m_mockWorkerThreadLifecycleObserver, contextDestroyed()).Times(1);
+ }
+
+ ~InProcessWorkerMessagingProxyForTest() override
+ {
+ EXPECT_EQ(WaitUntilMode::DontWait, m_waitUntilMode);
+ m_workerThread->workerLoaderProxy()->detachProvider(m_mockWorkerLoaderProxyProvider.get());
+ }
+
+ enum class WaitUntilMode {
+ DontWait,
+ PendingActivityReported,
+ PendingActivityChanged,
+ ThreadTerminated,
+ };
+
+ // Blocks the main thread until a specified event happens.
+ void waitUntil(WaitUntilMode mode)
+ {
+ EXPECT_TRUE(isMainThread());
+ EXPECT_EQ(WaitUntilMode::DontWait, m_waitUntilMode);
+ m_waitUntilMode = mode;
+ testing::enterRunLoop();
+ }
+
+ void reportPendingActivity(bool hasPendingActivity) override
+ {
+ EXPECT_TRUE(isMainThread());
+ bool changed = m_workerThreadHadPendingActivity != hasPendingActivity;
+ InProcessWorkerMessagingProxy::reportPendingActivity(hasPendingActivity);
+
+ if (m_waitUntilMode == WaitUntilMode::PendingActivityReported || (m_waitUntilMode == WaitUntilMode::PendingActivityChanged && changed)) {
+ m_waitUntilMode = WaitUntilMode::DontWait;
+ testing::exitRunLoop();
+ }
+ }
+
+ void workerThreadTerminated() override
+ {
+ EXPECT_TRUE(isMainThread());
+ if (m_waitUntilMode != WaitUntilMode::ThreadTerminated)
+ return;
+ m_waitUntilMode = WaitUntilMode::DontWait;
+ testing::exitRunLoop();
+ }
+
+ std::unique_ptr<WorkerThread> createWorkerThread(double originTime) override
+ {
+ NOTREACHED();
+ return nullptr;
+ }
+
+ DedicatedWorkerThreadForTest* workerThread()
+ {
+ return static_cast<DedicatedWorkerThreadForTest*>(m_workerThread.get());
+ }
+
+private:
+ std::unique_ptr<MockWorkerLoaderProxyProvider> m_mockWorkerLoaderProxyProvider;
+ std::unique_ptr<DedicatedWorkerThreadForTest> m_workerThread;
+ Persistent<MockWorkerThreadLifecycleObserver> m_mockWorkerThreadLifecycleObserver;
+
+ WaitUntilMode m_waitUntilMode = WaitUntilMode::DontWait;
+};
+
+using WaitUntilMode = InProcessWorkerMessagingProxyForTest::WaitUntilMode;
+
+class DedicatedWorkerTest : public ::testing::Test {
+public:
+ void SetUp() override
+ {
+ m_page = DummyPageHolder::create();
+ m_workerMessagingProxy = wrapUnique(new InProcessWorkerMessagingProxyForTest(&m_page->document()));
+ m_securityOrigin = SecurityOrigin::create(KURL(ParsedURLString, "http://fake.url/"));
+ }
+
+ void TearDown() override
+ {
+ workerThread()->terminate();
+ workerMessagingProxy()->waitUntil(WaitUntilMode::ThreadTerminated);
+ }
+
+ void startWithSourceCode(const String& source)
+ {
+ std::unique_ptr<Vector<CSPHeaderAndType>> headers = wrapUnique(new Vector<CSPHeaderAndType>());
+ CSPHeaderAndType headerAndType("contentSecurityPolicy", ContentSecurityPolicyHeaderTypeReport);
+ headers->append(headerAndType);
+ workerThread()->start(WorkerThreadStartupData::create(
+ KURL(ParsedURLString, "http://fake.url/"),
+ "fake user agent",
+ source,
+ nullptr /* cachedMetaData */,
+ DontPauseWorkerGlobalScopeOnStart,
+ headers.get(),
+ "" /* referrerPolicy */,
+ m_securityOrigin.get(),
+ nullptr /* workerClients */,
+ WebAddressSpaceLocal,
+ nullptr /* originTrialTokens */,
+ nullptr /* workerSettings */,
+ V8CacheOptionsDefault));
+ }
+
+ void dispatchMessageEventOnWorkerThread()
+ {
+ toWorkerGlobalScope(workerThread()->globalScope())->dispatchEvent(MessageEvent::create(nullptr, SerializedScriptValue::create()));
+ }
+
+ InProcessWorkerMessagingProxyForTest* workerMessagingProxy()
+ {
+ return m_workerMessagingProxy.get();
+ }
+
+ DedicatedWorkerThreadForTest* workerThread()
+ {
+ return m_workerMessagingProxy->workerThread();
+ }
+
+private:
+ RefPtr<SecurityOrigin> m_securityOrigin;
+ std::unique_ptr<DummyPageHolder> m_page;
+ std::unique_ptr<InProcessWorkerMessagingProxyForTest> m_workerMessagingProxy;
+};
+
+TEST_F(DedicatedWorkerTest, PendingActivity_NoActivity)
+{
+ const String sourceCode = "// Do nothing";
+ startWithSourceCode(sourceCode);
+ EXPECT_FALSE(workerMessagingProxy()->hasPendingActivity());
+
+ // There should be no pending activities.
+ workerMessagingProxy()->waitUntil(WaitUntilMode::PendingActivityReported);
+ EXPECT_FALSE(workerMessagingProxy()->hasPendingActivity());
+}
+
+TEST_F(DedicatedWorkerTest, PendingActivity_SetTimeout)
+{
+ // Start an oneshot timer on initial script evaluation.
+ const String sourceCode = "setTimeout(function() {}, 50);";
+
+ startWithSourceCode(sourceCode);
+ EXPECT_FALSE(workerMessagingProxy()->hasPendingActivity());
+
+ // The initial report should be true because the active timer is counted as
+ // a pending activity.
+ workerMessagingProxy()->waitUntil(WaitUntilMode::PendingActivityReported);
+ EXPECT_TRUE(workerMessagingProxy()->hasPendingActivity());
+
+ // The timer is fired soon and there should be no pending activities after
+ // that.
+ workerMessagingProxy()->waitUntil(WaitUntilMode::PendingActivityChanged);
+ EXPECT_FALSE(workerMessagingProxy()->hasPendingActivity());
+}
+
+TEST_F(DedicatedWorkerTest, PendingActivity_SetInterval)
+{
+ // Start a repeated timer on initial script evaluation, and stop it when a
+ // message is received.
+ const String sourceCode =
+ "var id = setInterval(function() {}, 1000);"
+ "addEventListener('message', function(event) { clearInterval(id); });";
+
+ startWithSourceCode(sourceCode);
+ EXPECT_FALSE(workerMessagingProxy()->hasPendingActivity());
+
+ // The initial report should be true because the active timer is counted as
+ // a pending activity.
+ workerMessagingProxy()->waitUntil(WaitUntilMode::PendingActivityReported);
+ EXPECT_TRUE(workerMessagingProxy()->hasPendingActivity());
+
+ // Stop the timer.
+ workerThread()->postTask(BLINK_FROM_HERE, createCrossThreadTask(&DedicatedWorkerTest::dispatchMessageEventOnWorkerThread, crossThreadUnretained(this)));
+
+ // There should be no pending activities after the timer is stopped.
+ workerMessagingProxy()->waitUntil(WaitUntilMode::PendingActivityChanged);
+ EXPECT_FALSE(workerMessagingProxy()->hasPendingActivity());
+}
+
+} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698