Index: content/browser/service_worker/embedded_worker_instance_unittest.cc |
diff --git a/content/browser/service_worker/embedded_worker_instance_unittest.cc b/content/browser/service_worker/embedded_worker_instance_unittest.cc |
index 727fcca1f8208fd03ce9bba3f5d5ba1833509d3f..e61e2b393ae117fa07b6a20e23b5ea1ca4eb986a 100644 |
--- a/content/browser/service_worker/embedded_worker_instance_unittest.cc |
+++ b/content/browser/service_worker/embedded_worker_instance_unittest.cc |
@@ -21,8 +21,13 @@ namespace { |
const int kRenderProcessId = 11; |
-void SaveStatus(ServiceWorkerStatusCode* out, ServiceWorkerStatusCode status) { |
- *out = status; |
+// Takes a scoped_ptr<>* because the object is passed in via Bind() where Pass() |
+// cannot be used. |
kinuko (google)
2015/09/10 22:14:19
base::Passed() or base::Owned() works?
falken
2015/09/11 09:48:16
Huh yes... I must have made a mistake on my first
|
+void DestroyWorker(scoped_ptr<EmbeddedWorkerInstance>* worker, |
+ ServiceWorkerStatusCode* out_status, |
+ ServiceWorkerStatusCode status) { |
+ *out_status = status; |
+ worker->reset(); |
} |
void SaveStatusAndCall(ServiceWorkerStatusCode* out, |
@@ -40,6 +45,11 @@ class EmbeddedWorkerInstanceTest : public testing::Test, |
EmbeddedWorkerInstanceTest() |
: thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {} |
+ void OnStopped(EmbeddedWorkerInstance::Status old_status) override { |
+ stopped_ = true; |
+ stopped_old_status_ = old_status; |
+ } |
+ |
void OnDetached(EmbeddedWorkerInstance::Status old_status) override { |
detached_ = true; |
detached_old_status_ = old_status; |
@@ -79,11 +89,22 @@ class EmbeddedWorkerInstanceTest : public testing::Test, |
bool detached_ = false; |
EmbeddedWorkerInstance::Status detached_old_status_ = |
EmbeddedWorkerInstance::STOPPED; |
+ bool stopped_ = false; |
+ EmbeddedWorkerInstance::Status stopped_old_status_ = |
+ EmbeddedWorkerInstance::STOPPED; |
private: |
DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerInstanceTest); |
}; |
+class FailToSendIPCHelper : public EmbeddedWorkerTestHelper { |
+ public: |
+ FailToSendIPCHelper() |
+ : EmbeddedWorkerTestHelper(base::FilePath(), kRenderProcessId) {} |
+ ~FailToSendIPCHelper() override {} |
+ bool Send(IPC::Message* message) override { return false; } |
+}; |
+ |
TEST_F(EmbeddedWorkerInstanceTest, StartAndStop) { |
scoped_ptr<EmbeddedWorkerInstance> worker = |
embedded_worker_registry()->CreateWorker(); |
@@ -228,18 +249,23 @@ TEST_F(EmbeddedWorkerInstanceTest, RemoveWorkerInSharedProcess) { |
worker2->Stop(); |
} |
-// Test detaching in the middle of the start worker sequence. |
+// Test detaching in the middle of the start worker sequence. Additionally, have |
+// the start callback destroy the worker, as is usual when starting a worker |
+// fails, and ensure a crash doesn't occur. |
TEST_F(EmbeddedWorkerInstanceTest, DetachDuringStart) { |
scoped_ptr<EmbeddedWorkerInstance> worker = |
embedded_worker_registry()->CreateWorker(); |
scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params( |
new EmbeddedWorkerMsg_StartWorker_Params()); |
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED; |
+ |
// Pretend we had a process allocated but then got detached before |
// the start sequence reached SendStartWorker. |
- worker->process_id_ = -1; |
- worker->SendStartWorker(params.Pass(), base::Bind(&SaveStatus, &status), true, |
+ worker->status_ = EmbeddedWorkerInstance::STOPPED; |
+ worker->SendStartWorker(params.Pass(), |
+ base::Bind(&DestroyWorker, &worker, &status), true, |
-1, false); |
+ // The callback destroys the worker, but we shouldn't have crashed. |
EXPECT_EQ(SERVICE_WORKER_ERROR_ABORT, status); |
} |
@@ -249,8 +275,6 @@ TEST_F(EmbeddedWorkerInstanceTest, StopDuringStart) { |
scoped_ptr<EmbeddedWorkerInstance> worker = |
embedded_worker_registry()->CreateWorker(); |
worker->AddListener(this); |
- scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params( |
- new EmbeddedWorkerMsg_StartWorker_Params()); |
// Pretend we stop during starting before we got a process allocated. |
worker->status_ = EmbeddedWorkerInstance::STARTING; |
worker->process_id_ = -1; |
@@ -260,4 +284,31 @@ TEST_F(EmbeddedWorkerInstanceTest, StopDuringStart) { |
EXPECT_EQ(EmbeddedWorkerInstance::STARTING, detached_old_status_); |
} |
+// Test for when sending the start IPC failed. |
+TEST_F(EmbeddedWorkerInstanceTest, FailToSendStartIPC) { |
+ helper_.reset(new FailToSendIPCHelper()); |
+ |
+ const int64 version_id = 55L; |
+ const GURL pattern("http://example.com/"); |
+ const GURL url("http://example.com/worker.js"); |
+ |
+ scoped_ptr<EmbeddedWorkerInstance> worker = |
+ embedded_worker_registry()->CreateWorker(); |
+ helper_->SimulateAddProcessToPattern(pattern, kRenderProcessId); |
+ ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED; |
+ worker->AddListener(this); |
+ |
+ // Attempt to start the worker. |
+ base::RunLoop run_loop; |
+ worker->Start( |
+ version_id, pattern, url, |
+ base::Bind(&SaveStatusAndCall, &status, run_loop.QuitClosure())); |
+ run_loop.Run(); |
+ |
+ // The callback should have run, and we should have got an OnStopped message. |
+ EXPECT_EQ(SERVICE_WORKER_ERROR_IPC_FAILED, status); |
+ EXPECT_TRUE(stopped_); |
+ EXPECT_EQ(EmbeddedWorkerInstance::STARTING, stopped_old_status_); |
+} |
+ |
} // namespace content |