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

Unified Diff: third_party/WebKit/Source/core/workers/WorkerThreadTest.cpp

Issue 2335343006: Worker: Refine WorkerThreadTest (Closed)
Patch Set: address review comments Created 4 years, 3 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
« no previous file with comments | « third_party/WebKit/Source/core/workers/WorkerThread.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/WebKit/Source/core/workers/WorkerThreadTest.cpp
diff --git a/third_party/WebKit/Source/core/workers/WorkerThreadTest.cpp b/third_party/WebKit/Source/core/workers/WorkerThreadTest.cpp
index f9f6886d1e5ee1d55c5c465c5d3550e583667bd9..03322ed79abe776de72eb3681954f70dd6d74a2a 100644
--- a/third_party/WebKit/Source/core/workers/WorkerThreadTest.cpp
+++ b/third_party/WebKit/Source/core/workers/WorkerThreadTest.cpp
@@ -21,61 +21,32 @@ using ExitCode = WorkerThread::ExitCode;
namespace {
-// Called from WorkerThread::startRunningDebuggerTasksOnPauseOnWorkerThread as a
-// debugger task.
-void waitForTermination(WorkerThread* workerThread, WaitableEvent* waitableEvent)
+// Used as a debugger task. Waits for a signal from the main thread.
+void waitForSignalTask(WorkerThread* workerThread, WaitableEvent* waitableEvent)
{
EXPECT_TRUE(workerThread->isCurrentThread());
- // Notify the main thread that the debugger task is waiting for termination.
+ // Notify the main thread that the debugger task is waiting for the signal.
Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FROM_HERE, crossThreadBind(&testing::exitRunLoop));
waitableEvent->wait();
}
} // namespace
-class WorkerThreadLifecycleObserverForTest final : public GarbageCollectedFinalized<WorkerThreadLifecycleObserverForTest>, public WorkerThreadLifecycleObserver {
- USING_GARBAGE_COLLECTED_MIXIN(WorkerThreadLifecycleObserverForTest);
- WTF_MAKE_NONCOPYABLE(WorkerThreadLifecycleObserverForTest);
-public:
- explicit WorkerThreadLifecycleObserverForTest(WorkerThreadLifecycleContext* context)
- : WorkerThreadLifecycleObserver(context)
- {
- DCHECK(!wasContextDestroyedBeforeObserverCreation());
- }
- ~WorkerThreadLifecycleObserverForTest() override {}
-
- void contextDestroyed() override
- {
- if (m_closure)
- (*m_closure)();
- }
-
- void setClosure(std::unique_ptr<WTF::Closure> closure)
- {
- m_closure = std::move(closure);
- }
-
-private:
- std::unique_ptr<WTF::Closure> m_closure;
-};
-
class WorkerThreadTest : public ::testing::Test {
public:
void SetUp() override
{
- m_mockWorkerLoaderProxyProvider = wrapUnique(new MockWorkerLoaderProxyProvider());
- m_mockWorkerReportingProxy = wrapUnique(new MockWorkerReportingProxy());
+ m_loaderProxyProvider = wrapUnique(new MockWorkerLoaderProxyProvider());
+ m_reportingProxy = wrapUnique(new MockWorkerReportingProxy());
m_securityOrigin = SecurityOrigin::create(KURL(ParsedURLString, "http://fake.url/"));
- m_workerThread = wrapUnique(new WorkerThreadForTest(
- m_mockWorkerLoaderProxyProvider.get(),
- *m_mockWorkerReportingProxy));
- m_workerThreadLifecycleObserver = new WorkerThreadLifecycleObserverForTest(m_workerThread->getWorkerThreadLifecycleContext());
+ m_workerThread = wrapUnique(new WorkerThreadForTest(m_loaderProxyProvider.get(), *m_reportingProxy));
+ m_lifecycleObserver = new MockWorkerThreadLifecycleObserver(m_workerThread->getWorkerThreadLifecycleContext());
}
void TearDown() override
{
- m_workerThread->workerLoaderProxy()->detachProvider(m_mockWorkerLoaderProxyProvider.get());
+ m_workerThread->workerLoaderProxy()->detachProvider(m_loaderProxyProvider.get());
}
void start()
@@ -103,32 +74,35 @@ public:
protected:
void expectReportingCalls()
{
- EXPECT_CALL(*m_mockWorkerReportingProxy, didLoadWorkerScriptMock(_, _)).Times(1);
- EXPECT_CALL(*m_mockWorkerReportingProxy, didCreateWorkerGlobalScope(_)).Times(1);
- EXPECT_CALL(*m_mockWorkerReportingProxy, didInitializeWorkerContext()).Times(1);
- EXPECT_CALL(*m_mockWorkerReportingProxy, didEvaluateWorkerScript(true)).Times(1);
- EXPECT_CALL(*m_mockWorkerReportingProxy, willDestroyWorkerGlobalScope()).Times(1);
- EXPECT_CALL(*m_mockWorkerReportingProxy, didTerminateWorkerThread()).Times(1);
+ EXPECT_CALL(*m_reportingProxy, didLoadWorkerScriptMock(_, _)).Times(1);
+ EXPECT_CALL(*m_reportingProxy, didCreateWorkerGlobalScope(_)).Times(1);
+ EXPECT_CALL(*m_reportingProxy, didInitializeWorkerContext()).Times(1);
+ EXPECT_CALL(*m_reportingProxy, didEvaluateWorkerScript(true)).Times(1);
+ EXPECT_CALL(*m_reportingProxy, willDestroyWorkerGlobalScope()).Times(1);
+ EXPECT_CALL(*m_reportingProxy, didTerminateWorkerThread()).Times(1);
+ EXPECT_CALL(*m_lifecycleObserver, contextDestroyed()).Times(1);
}
void expectReportingCallsForWorkerPossiblyTerminatedBeforeInitialization()
{
- EXPECT_CALL(*m_mockWorkerReportingProxy, didLoadWorkerScriptMock(_, _)).Times(AtMost(1));
- EXPECT_CALL(*m_mockWorkerReportingProxy, didCreateWorkerGlobalScope(_)).Times(AtMost(1));
- EXPECT_CALL(*m_mockWorkerReportingProxy, didInitializeWorkerContext()).Times(AtMost(1));
- EXPECT_CALL(*m_mockWorkerReportingProxy, didEvaluateWorkerScript(_)).Times(AtMost(1));
- EXPECT_CALL(*m_mockWorkerReportingProxy, willDestroyWorkerGlobalScope()).Times(AtMost(1));
- EXPECT_CALL(*m_mockWorkerReportingProxy, didTerminateWorkerThread()).Times(1);
+ EXPECT_CALL(*m_reportingProxy, didLoadWorkerScriptMock(_, _)).Times(AtMost(1));
+ EXPECT_CALL(*m_reportingProxy, didCreateWorkerGlobalScope(_)).Times(AtMost(1));
+ EXPECT_CALL(*m_reportingProxy, didInitializeWorkerContext()).Times(AtMost(1));
+ EXPECT_CALL(*m_reportingProxy, didEvaluateWorkerScript(_)).Times(AtMost(1));
+ EXPECT_CALL(*m_reportingProxy, willDestroyWorkerGlobalScope()).Times(AtMost(1));
+ EXPECT_CALL(*m_reportingProxy, didTerminateWorkerThread()).Times(1);
+ EXPECT_CALL(*m_lifecycleObserver, contextDestroyed()).Times(1);
}
void expectReportingCallsForWorkerForciblyTerminated()
{
- EXPECT_CALL(*m_mockWorkerReportingProxy, didLoadWorkerScriptMock(_, _)).Times(1);
- EXPECT_CALL(*m_mockWorkerReportingProxy, didCreateWorkerGlobalScope(_)).Times(1);
- EXPECT_CALL(*m_mockWorkerReportingProxy, didInitializeWorkerContext()).Times(1);
- EXPECT_CALL(*m_mockWorkerReportingProxy, didEvaluateWorkerScript(false)).Times(1);
- EXPECT_CALL(*m_mockWorkerReportingProxy, willDestroyWorkerGlobalScope()).Times(1);
- EXPECT_CALL(*m_mockWorkerReportingProxy, didTerminateWorkerThread()).Times(1);
+ EXPECT_CALL(*m_reportingProxy, didLoadWorkerScriptMock(_, _)).Times(1);
+ EXPECT_CALL(*m_reportingProxy, didCreateWorkerGlobalScope(_)).Times(1);
+ EXPECT_CALL(*m_reportingProxy, didInitializeWorkerContext()).Times(1);
+ EXPECT_CALL(*m_reportingProxy, didEvaluateWorkerScript(false)).Times(1);
+ EXPECT_CALL(*m_reportingProxy, willDestroyWorkerGlobalScope()).Times(1);
+ EXPECT_CALL(*m_reportingProxy, didTerminateWorkerThread()).Times(1);
+ EXPECT_CALL(*m_lifecycleObserver, contextDestroyed()).Times(1);
}
ExitCode getExitCode()
@@ -137,10 +111,10 @@ protected:
}
RefPtr<SecurityOrigin> m_securityOrigin;
- std::unique_ptr<MockWorkerLoaderProxyProvider> m_mockWorkerLoaderProxyProvider;
- std::unique_ptr<MockWorkerReportingProxy> m_mockWorkerReportingProxy;
+ std::unique_ptr<MockWorkerLoaderProxyProvider> m_loaderProxyProvider;
+ std::unique_ptr<MockWorkerReportingProxy> m_reportingProxy;
std::unique_ptr<WorkerThreadForTest> m_workerThread;
- Persistent<WorkerThreadLifecycleObserverForTest> m_workerThreadLifecycleObserver;
+ Persistent<MockWorkerThreadLifecycleObserver> m_lifecycleObserver;
};
TEST_F(WorkerThreadTest, ShouldScheduleToTerminateExecution)
@@ -165,10 +139,13 @@ TEST_F(WorkerThreadTest, ShouldScheduleToTerminateExecution)
m_workerThread->setExitCode(dummyLock, ExitCode::GracefullyTerminated);
}
-TEST_F(WorkerThreadTest, StartAndTerminate_AsyncTerminate)
+TEST_F(WorkerThreadTest, AsyncTerminate_OnIdle)
{
expectReportingCalls();
start();
+
+ // Wait until the initialization completes and the worker thread becomes
+ // idle.
m_workerThread->waitForInit();
// The worker thread is not being blocked, so the worker thread should be
@@ -179,16 +156,20 @@ TEST_F(WorkerThreadTest, StartAndTerminate_AsyncTerminate)
EXPECT_EQ(ExitCode::GracefullyTerminated, getExitCode());
}
-TEST_F(WorkerThreadTest, StartAndTerminate_SyncTerminate)
+TEST_F(WorkerThreadTest, SyncTerminate_OnIdle)
{
expectReportingCalls();
start();
+
+ // Wait until the initialization completes and the worker thread becomes
+ // idle.
m_workerThread->waitForInit();
+
m_workerThread->terminateAndWait();
EXPECT_EQ(ExitCode::SyncForciblyTerminated, getExitCode());
}
-TEST_F(WorkerThreadTest, StartAndTerminateImmediately_AsyncTerminate)
+TEST_F(WorkerThreadTest, AsyncTerminate_ImmediatelyAfterStart)
{
expectReportingCallsForWorkerPossiblyTerminatedBeforeInitialization();
start();
@@ -204,7 +185,7 @@ TEST_F(WorkerThreadTest, StartAndTerminateImmediately_AsyncTerminate)
EXPECT_EQ(ExitCode::GracefullyTerminated, exitCode);
}
-TEST_F(WorkerThreadTest, StartAndTerminateImmediately_SyncTerminate)
+TEST_F(WorkerThreadTest, SyncTerminate_ImmediatelyAfterStart)
{
expectReportingCallsForWorkerPossiblyTerminatedBeforeInitialization();
start();
@@ -220,136 +201,139 @@ TEST_F(WorkerThreadTest, StartAndTerminateImmediately_SyncTerminate)
EXPECT_TRUE(ExitCode::GracefullyTerminated == exitCode || ExitCode::SyncForciblyTerminated == exitCode);
}
-TEST_F(WorkerThreadTest, StartAndTerminateOnInitialization_TerminateWhileDebuggerTaskIsRunning)
+TEST_F(WorkerThreadTest, AsyncTerminate_WhileTaskIsRunning)
{
- EXPECT_CALL(*m_mockWorkerReportingProxy, didLoadWorkerScriptMock(_, _)).Times(1);
- EXPECT_CALL(*m_mockWorkerReportingProxy, didCreateWorkerGlobalScope(_)).Times(1);
- EXPECT_CALL(*m_mockWorkerReportingProxy, willDestroyWorkerGlobalScope()).Times(1);
- EXPECT_CALL(*m_mockWorkerReportingProxy, didTerminateWorkerThread()).Times(1);
-
- std::unique_ptr<Vector<CSPHeaderAndType>> headers = wrapUnique(new Vector<CSPHeaderAndType>());
- CSPHeaderAndType headerAndType("contentSecurityPolicy", ContentSecurityPolicyHeaderTypeReport);
- headers->append(headerAndType);
+ const long long kForceTerminationDelayInMs = 10;
+ setForceTerminationDelayInMs(kForceTerminationDelayInMs);
- // Specify PauseWorkerGlobalScopeOnStart so that the worker thread can pause
- // on initialziation to run debugger tasks.
- std::unique_ptr<WorkerThreadStartupData> startupData = WorkerThreadStartupData::create(
- KURL(ParsedURLString, "http://fake.url/"),
- "fake user agent",
- "//fake source code",
- nullptr, /* cachedMetaData */
- PauseWorkerGlobalScopeOnStart,
- headers.get(),
- "",
- m_securityOrigin.get(),
- nullptr, /* workerClients */
- WebAddressSpaceLocal,
- nullptr /* originTrialToken */,
- nullptr /* WorkerSettings */,
- V8CacheOptionsDefault);
- m_workerThread->start(std::move(startupData));
+ expectReportingCallsForWorkerForciblyTerminated();
+ startWithSourceCodeNotToFinish();
+ m_reportingProxy->waitUntilScriptLoaded();
- // Used to wait for worker thread termination in a debugger task on the
- // worker thread. Signaled when WorkerThreadLifecycleContext is destroyed on
- // the main thread.
- WaitableEvent waitableEvent(WaitableEvent::ResetPolicy::Manual, WaitableEvent::InitialState::NonSignaled);
- m_workerThread->appendDebuggerTask(crossThreadBind(&waitForTermination, crossThreadUnretained(m_workerThread.get()), crossThreadUnretained(&waitableEvent)));
- m_workerThreadLifecycleObserver->setClosure(WTF::bind(&WaitableEvent::signal, unretained(&waitableEvent)));
+ // terminate() schedules a force termination task.
+ m_workerThread->terminate();
+ EXPECT_TRUE(isForceTerminationTaskScheduled());
+ EXPECT_EQ(ExitCode::NotTerminated, getExitCode());
- // Wait for the debugger task.
- testing::enterRunLoop();
+ // Multiple terminate() calls should not take effect.
+ m_workerThread->terminate();
+ m_workerThread->terminate();
+ EXPECT_EQ(ExitCode::NotTerminated, getExitCode());
- // Start termination while the debugger task is running.
- EXPECT_TRUE(m_workerThread->m_runningDebuggerTask);
- m_workerThread->terminateAndWait();
- EXPECT_EQ(ExitCode::GracefullyTerminated, getExitCode());
+ // Wait until the force termination task runs.
+ testing::runDelayedTasks(kForceTerminationDelayInMs);
+ m_workerThread->waitForShutdownForTesting();
+ EXPECT_EQ(ExitCode::AsyncForciblyTerminated, getExitCode());
}
-TEST_F(WorkerThreadTest, StartAndTerminateOnScriptLoaded_SyncForciblyTerminate)
+TEST_F(WorkerThreadTest, SyncTerminate_WhileTaskIsRunning)
{
expectReportingCallsForWorkerForciblyTerminated();
startWithSourceCodeNotToFinish();
- m_mockWorkerReportingProxy->waitUntilScriptLoaded();
+ m_reportingProxy->waitUntilScriptLoaded();
// terminateAndWait() synchronously terminates the worker execution.
m_workerThread->terminateAndWait();
EXPECT_EQ(ExitCode::SyncForciblyTerminated, getExitCode());
}
-TEST_F(WorkerThreadTest, StartAndTerminateOnScriptLoaded_AsyncForciblyTerminate)
+TEST_F(WorkerThreadTest, AsyncTerminateAndThenSyncTerminate_WhileTaskIsRunning)
{
const long long kForceTerminationDelayInMs = 10;
setForceTerminationDelayInMs(kForceTerminationDelayInMs);
expectReportingCallsForWorkerForciblyTerminated();
startWithSourceCodeNotToFinish();
- m_mockWorkerReportingProxy->waitUntilScriptLoaded();
+ m_reportingProxy->waitUntilScriptLoaded();
// terminate() schedules a force termination task.
m_workerThread->terminate();
EXPECT_TRUE(isForceTerminationTaskScheduled());
EXPECT_EQ(ExitCode::NotTerminated, getExitCode());
- // Wait until the force termination task runs.
- testing::runDelayedTasks(kForceTerminationDelayInMs);
- m_workerThread->waitForShutdownForTesting();
- EXPECT_EQ(ExitCode::AsyncForciblyTerminated, getExitCode());
+ // terminateAndWait() should overtake the scheduled force termination task.
+ m_workerThread->terminateAndWait();
+ EXPECT_FALSE(isForceTerminationTaskScheduled());
+ EXPECT_EQ(ExitCode::SyncForciblyTerminated, getExitCode());
}
-TEST_F(WorkerThreadTest, StartAndTerminateOnScriptLoaded_AsyncForciblyTerminate_MultipleTimes)
+TEST_F(WorkerThreadTest, Terminate_WhileDebuggerTaskIsRunningOnInitialization)
{
- const long long kForceTerminationDelayInMs = 10;
- setForceTerminationDelayInMs(kForceTerminationDelayInMs);
+ EXPECT_CALL(*m_reportingProxy, didLoadWorkerScriptMock(_, _)).Times(1);
+ EXPECT_CALL(*m_reportingProxy, didCreateWorkerGlobalScope(_)).Times(1);
+ EXPECT_CALL(*m_reportingProxy, willDestroyWorkerGlobalScope()).Times(1);
+ EXPECT_CALL(*m_reportingProxy, didTerminateWorkerThread()).Times(1);
+ EXPECT_CALL(*m_lifecycleObserver, contextDestroyed()).Times(1);
- expectReportingCallsForWorkerForciblyTerminated();
- startWithSourceCodeNotToFinish();
- m_mockWorkerReportingProxy->waitUntilScriptLoaded();
+ std::unique_ptr<Vector<CSPHeaderAndType>> headers = wrapUnique(new Vector<CSPHeaderAndType>());
+ CSPHeaderAndType headerAndType("contentSecurityPolicy", ContentSecurityPolicyHeaderTypeReport);
+ headers->append(headerAndType);
- // terminate() schedules a force termination task.
+ // Specify PauseWorkerGlobalScopeOnStart so that the worker thread can pause
+ // on initialziation to run debugger tasks.
+ std::unique_ptr<WorkerThreadStartupData> startupData = WorkerThreadStartupData::create(
+ KURL(ParsedURLString, "http://fake.url/"),
+ "fake user agent",
+ "//fake source code",
+ nullptr, /* cachedMetaData */
+ PauseWorkerGlobalScopeOnStart,
+ headers.get(),
+ "",
+ m_securityOrigin.get(),
+ nullptr, /* workerClients */
+ WebAddressSpaceLocal,
+ nullptr /* originTrialToken */,
+ nullptr /* WorkerSettings */,
+ V8CacheOptionsDefault);
+ m_workerThread->start(std::move(startupData));
+
+ // Used to wait for worker thread termination in a debugger task on the
+ // worker thread.
+ WaitableEvent waitableEvent;
+ m_workerThread->appendDebuggerTask(crossThreadBind(&waitForSignalTask, crossThreadUnretained(m_workerThread.get()), crossThreadUnretained(&waitableEvent)));
+
+ // Wait for the debugger task.
+ testing::enterRunLoop();
+ EXPECT_TRUE(m_workerThread->m_runningDebuggerTask);
+
+ // terminate() should not schedule a force termination task because there is
+ // a running debugger task.
m_workerThread->terminate();
- EXPECT_TRUE(isForceTerminationTaskScheduled());
+ EXPECT_FALSE(isForceTerminationTaskScheduled());
EXPECT_EQ(ExitCode::NotTerminated, getExitCode());
// Multiple terminate() calls should not take effect.
m_workerThread->terminate();
m_workerThread->terminate();
+ EXPECT_FALSE(isForceTerminationTaskScheduled());
EXPECT_EQ(ExitCode::NotTerminated, getExitCode());
- // Wait until the force termination task runs.
- testing::runDelayedTasks(kForceTerminationDelayInMs);
- m_workerThread->waitForShutdownForTesting();
- EXPECT_EQ(ExitCode::AsyncForciblyTerminated, getExitCode());
-}
-
-TEST_F(WorkerThreadTest, StartAndTerminateOnScriptLoaded_SyncForciblyTerminateAfterTerminationTaskIsScheduled)
-{
- const long long kForceTerminationDelayInMs = 10;
- setForceTerminationDelayInMs(kForceTerminationDelayInMs);
-
- expectReportingCallsForWorkerForciblyTerminated();
- startWithSourceCodeNotToFinish();
- m_mockWorkerReportingProxy->waitUntilScriptLoaded();
-
- // terminate() schedules a force termination task.
- m_workerThread->terminate();
- EXPECT_TRUE(isForceTerminationTaskScheduled());
+ // Focible termination request should also respect the running debugger
+ // task.
+ m_workerThread->terminateInternal(WorkerThread::TerminationMode::Forcible);
+ EXPECT_FALSE(isForceTerminationTaskScheduled());
EXPECT_EQ(ExitCode::NotTerminated, getExitCode());
- // terminateAndWait() should overtake the scheduled force termination task.
- m_workerThread->terminateAndWait();
- EXPECT_FALSE(isForceTerminationTaskScheduled());
- EXPECT_EQ(ExitCode::SyncForciblyTerminated, getExitCode());
+ // Resume the debugger task. Shutdown starts after that.
+ waitableEvent.signal();
+ m_workerThread->waitForShutdownForTesting();
+ EXPECT_EQ(ExitCode::GracefullyTerminated, getExitCode());
}
-TEST_F(WorkerThreadTest, StartAndTerminateOnScriptLoaded_TerminateWhileDebuggerTaskIsRunning)
+TEST_F(WorkerThreadTest, Terminate_WhileDebuggerTaskIsRunning)
{
- expectReportingCallsForWorkerForciblyTerminated();
- startWithSourceCodeNotToFinish();
- m_mockWorkerReportingProxy->waitUntilScriptLoaded();
+ expectReportingCalls();
+ start();
+ m_workerThread->waitForInit();
- // Simulate that a debugger task is running.
- // TODO(nhiroki): Run a real debugger task instead of simulation.
- m_workerThread->m_runningDebuggerTask = true;
+ // Used to wait for worker thread termination in a debugger task on the
+ // worker thread.
+ WaitableEvent waitableEvent;
+ m_workerThread->appendDebuggerTask(crossThreadBind(&waitForSignalTask, crossThreadUnretained(m_workerThread.get()), crossThreadUnretained(&waitableEvent)));
+
+ // Wait for the debugger task.
+ testing::enterRunLoop();
+ EXPECT_TRUE(m_workerThread->m_runningDebuggerTask);
// terminate() should not schedule a force termination task because there is
// a running debugger task.
@@ -369,10 +353,10 @@ TEST_F(WorkerThreadTest, StartAndTerminateOnScriptLoaded_TerminateWhileDebuggerT
EXPECT_FALSE(isForceTerminationTaskScheduled());
EXPECT_EQ(ExitCode::NotTerminated, getExitCode());
- // Clean up in order to satisfy DCHECK in the dtor of WorkerThread.
- m_workerThread->m_runningDebuggerTask = false;
- m_workerThread->isolate()->TerminateExecution();
+ // Resume the debugger task. Shutdown starts after that.
+ waitableEvent.signal();
m_workerThread->waitForShutdownForTesting();
+ EXPECT_EQ(ExitCode::GracefullyTerminated, getExitCode());
}
// TODO(nhiroki): Add tests for terminateAndWaitForAllWorkers.
« no previous file with comments | « third_party/WebKit/Source/core/workers/WorkerThread.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698