Index: content/browser/service_worker/service_worker_version_unittest.cc |
diff --git a/content/browser/service_worker/service_worker_version_unittest.cc b/content/browser/service_worker/service_worker_version_unittest.cc |
index 40115716a72512acd92acf5ded87ebbef8ae7b0f..d2d9ae21018b6b383c9e5ac1202c28e28e5aca37 100644 |
--- a/content/browser/service_worker/service_worker_version_unittest.cc |
+++ b/content/browser/service_worker/service_worker_version_unittest.cc |
@@ -187,6 +187,70 @@ class ServiceWorkerFailToStartTest : public ServiceWorkerVersionTest { |
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerFailToStartTest); |
}; |
+class MessageReceiverHangAtScriptEvaluation : public MessageReceiver { |
+ public: |
+ MessageReceiverHangAtScriptEvaluation() : MessageReceiver() {} |
+ ~MessageReceiverHangAtScriptEvaluation() override {} |
+ |
+ void OnStartWorker(int embedded_worker_id, |
+ int64 service_worker_version_id, |
+ const GURL& scope, |
+ const GURL& script_url, |
+ bool pause_after_download) override { |
+ if (pause_after_download) { |
+ SimulatePausedAfterDownload(embedded_worker_id); |
+ return; |
+ } |
+ SimulateWorkerReadyForInspection(embedded_worker_id); |
+ SimulateWorkerScriptLoaded(next_thread_id_++, embedded_worker_id); |
+ // To simulate while(true) {} in the script, don't call the following: |
+ // SimulateWorkerScriptEvaluated(embedded_worker_id); |
+ // SimulateWorkerStarted(embedded_worker_id); |
+ } |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(MessageReceiverHangAtScriptEvaluation); |
+}; |
+ |
+class MessageReceiverHangAtInstall : public MessageReceiver { |
+ public: |
+ MessageReceiverHangAtInstall() : MessageReceiver() {} |
+ ~MessageReceiverHangAtInstall() override {} |
+ |
+ void OnInstallEvent(int embedded_worker_id, |
+ int request_id, |
+ int active_version_id) override { |
+ // Do nothing. |
+ } |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(MessageReceiverHangAtInstall); |
+}; |
+ |
+class ServiceWorkerStartTimeoutTest : public ServiceWorkerVersionTest { |
+ protected: |
+ ServiceWorkerStartTimeoutTest() : ServiceWorkerVersionTest() {} |
+ |
+ scoped_ptr<MessageReceiver> GetMessageReceiver() override { |
+ return make_scoped_ptr(new MessageReceiverHangAtScriptEvaluation()); |
+ } |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(ServiceWorkerStartTimeoutTest); |
+}; |
+ |
+class ServiceWorkerEventTimeoutTest : public ServiceWorkerVersionTest { |
+ protected: |
+ ServiceWorkerEventTimeoutTest() : ServiceWorkerVersionTest() {} |
+ |
+ scoped_ptr<MessageReceiver> GetMessageReceiver() override { |
+ return make_scoped_ptr(new MessageReceiverHangAtInstall()); |
+ } |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(ServiceWorkerEventTimeoutTest); |
+}; |
+ |
TEST_F(ServiceWorkerVersionTest, ConcurrentStartAndStop) { |
// Call StartWorker() multiple times. |
ServiceWorkerStatusCode status1 = SERVICE_WORKER_ERROR_FAILED; |
@@ -442,4 +506,59 @@ TEST_F(ServiceWorkerFailToStartTest, RendererCrash) { |
EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status()); |
} |
+// Test starting a "while(true) {}" worker. StartWorker should timeout. |
+TEST_F(ServiceWorkerStartTimeoutTest, ScriptEvaluationTimeout) { |
+ ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK; // dummy value |
+ version_->StartWorker(CreateReceiverOnCurrentThread(&status)); |
+ base::RunLoop().RunUntilIdle(); |
+ |
+ // The start callback has not completed yet. |
+ EXPECT_EQ(SERVICE_WORKER_ERROR_NETWORK, status); |
+ EXPECT_EQ(ServiceWorkerVersion::STARTING, version_->running_status()); |
+ |
+ // The pings have started. |
+ EXPECT_TRUE(version_->ping_worker_timer_.IsRunning()); |
+ |
+ // Simulate timing out. |
+ version_->PingWorker(); |
+ version_->OnPingTimeout(); |
+ base::RunLoop().RunUntilIdle(); |
+ |
+ // The start callback should have completed with failure. |
+ EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, status); |
+ EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status()); |
+} |
+ |
+// Test "while(true) {}" after successful startup (e.g., in an event |
+// handler). The worker should be stopped. |
+TEST_F(ServiceWorkerEventTimeoutTest, EventTimeout) { |
+ ServiceWorkerStatusCode status; |
+ version_->StartWorker(CreateReceiverOnCurrentThread(&status)); |
+ base::RunLoop().RunUntilIdle(); |
+ |
+ EXPECT_EQ(SERVICE_WORKER_OK, status); |
+ |
+ // The pings have started. |
+ EXPECT_TRUE(version_->ping_worker_timer_.IsRunning()); |
+ |
+ // Simulate a successful ping. |
+ version_->PingWorker(); |
+ version_->OnPongFromWorker(); |
+ EXPECT_TRUE(version_->ping_worker_timer_.IsRunning()); |
+ |
+ // Dispatch an event. |
+ version_->SetStatus(ServiceWorkerVersion::INSTALLING); |
+ version_->DispatchInstallEvent(0, CreateReceiverOnCurrentThread(&status)); |
+ |
+ // Simulate timing out. |
+ EXPECT_TRUE(version_->ping_worker_timer_.IsRunning()); |
+ version_->PingWorker(); |
+ version_->OnPingTimeout(); |
+ base::RunLoop().RunUntilIdle(); |
+ |
+ // The event callback should have completed with failure. |
+ EXPECT_EQ(SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED, status); |
+ EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status()); |
+} |
+ |
} // namespace content |