| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/basictypes.h" | 5 #include "base/basictypes.h" |
| 6 #include "base/run_loop.h" | 6 #include "base/run_loop.h" |
| 7 #include "base/stl_util.h" | 7 #include "base/stl_util.h" |
| 8 #include "content/browser/service_worker/embedded_worker_instance.h" | 8 #include "content/browser/service_worker/embedded_worker_instance.h" |
| 9 #include "content/browser/service_worker/embedded_worker_registry.h" | 9 #include "content/browser/service_worker/embedded_worker_registry.h" |
| 10 #include "content/browser/service_worker/embedded_worker_test_helper.h" | 10 #include "content/browser/service_worker/embedded_worker_test_helper.h" |
| 11 #include "content/browser/service_worker/service_worker_context_core.h" | 11 #include "content/browser/service_worker/service_worker_context_core.h" |
| 12 #include "content/browser/service_worker/service_worker_context_wrapper.h" | 12 #include "content/browser/service_worker/service_worker_context_wrapper.h" |
| 13 #include "content/common/service_worker/embedded_worker_messages.h" | 13 #include "content/common/service_worker/embedded_worker_messages.h" |
| 14 #include "content/public/test/test_browser_thread_bundle.h" | 14 #include "content/public/test/test_browser_thread_bundle.h" |
| 15 #include "testing/gmock/include/gmock/gmock.h" | 15 #include "testing/gmock/include/gmock/gmock.h" |
| 16 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
| 17 | 17 |
| 18 namespace content { | 18 namespace content { |
| 19 | 19 |
| 20 namespace { | 20 namespace { |
| 21 | 21 |
| 22 const int kRenderProcessId = 11; | 22 const int kRenderProcessId = 11; |
| 23 | 23 |
| 24 void SaveStatus(ServiceWorkerStatusCode* out, ServiceWorkerStatusCode status) { | 24 void DestroyWorker(scoped_ptr<EmbeddedWorkerInstance> worker, |
| 25 *out = status; | 25 ServiceWorkerStatusCode* out_status, |
| 26 ServiceWorkerStatusCode status) { |
| 27 *out_status = status; |
| 28 worker.reset(); |
| 26 } | 29 } |
| 27 | 30 |
| 28 void SaveStatusAndCall(ServiceWorkerStatusCode* out, | 31 void SaveStatusAndCall(ServiceWorkerStatusCode* out, |
| 29 const base::Closure& callback, | 32 const base::Closure& callback, |
| 30 ServiceWorkerStatusCode status) { | 33 ServiceWorkerStatusCode status) { |
| 31 *out = status; | 34 *out = status; |
| 32 callback.Run(); | 35 callback.Run(); |
| 33 } | 36 } |
| 34 | 37 |
| 35 } // namespace | 38 } // namespace |
| 36 | 39 |
| 37 class EmbeddedWorkerInstanceTest : public testing::Test, | 40 class EmbeddedWorkerInstanceTest : public testing::Test, |
| 38 public EmbeddedWorkerInstance::Listener { | 41 public EmbeddedWorkerInstance::Listener { |
| 39 protected: | 42 protected: |
| 40 EmbeddedWorkerInstanceTest() | 43 EmbeddedWorkerInstanceTest() |
| 41 : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {} | 44 : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {} |
| 42 | 45 |
| 46 void OnStopped(EmbeddedWorkerInstance::Status old_status) override { |
| 47 stopped_ = true; |
| 48 stopped_old_status_ = old_status; |
| 49 } |
| 50 |
| 43 void OnDetached(EmbeddedWorkerInstance::Status old_status) override { | 51 void OnDetached(EmbeddedWorkerInstance::Status old_status) override { |
| 44 detached_ = true; | 52 detached_ = true; |
| 45 detached_old_status_ = old_status; | 53 detached_old_status_ = old_status; |
| 46 } | 54 } |
| 47 | 55 |
| 48 bool OnMessageReceived(const IPC::Message& message) override { return false; } | 56 bool OnMessageReceived(const IPC::Message& message) override { return false; } |
| 49 | 57 |
| 50 void SetUp() override { | 58 void SetUp() override { |
| 51 helper_.reset( | 59 helper_.reset( |
| 52 new EmbeddedWorkerTestHelper(base::FilePath(), kRenderProcessId)); | 60 new EmbeddedWorkerTestHelper(base::FilePath(), kRenderProcessId)); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 72 return context()->embedded_worker_registry(); | 80 return context()->embedded_worker_registry(); |
| 73 } | 81 } |
| 74 | 82 |
| 75 IPC::TestSink* ipc_sink() { return helper_->ipc_sink(); } | 83 IPC::TestSink* ipc_sink() { return helper_->ipc_sink(); } |
| 76 | 84 |
| 77 TestBrowserThreadBundle thread_bundle_; | 85 TestBrowserThreadBundle thread_bundle_; |
| 78 scoped_ptr<EmbeddedWorkerTestHelper> helper_; | 86 scoped_ptr<EmbeddedWorkerTestHelper> helper_; |
| 79 bool detached_ = false; | 87 bool detached_ = false; |
| 80 EmbeddedWorkerInstance::Status detached_old_status_ = | 88 EmbeddedWorkerInstance::Status detached_old_status_ = |
| 81 EmbeddedWorkerInstance::STOPPED; | 89 EmbeddedWorkerInstance::STOPPED; |
| 90 bool stopped_ = false; |
| 91 EmbeddedWorkerInstance::Status stopped_old_status_ = |
| 92 EmbeddedWorkerInstance::STOPPED; |
| 82 | 93 |
| 83 private: | 94 private: |
| 84 DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerInstanceTest); | 95 DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerInstanceTest); |
| 85 }; | 96 }; |
| 86 | 97 |
| 98 class FailToSendIPCHelper : public EmbeddedWorkerTestHelper { |
| 99 public: |
| 100 FailToSendIPCHelper() |
| 101 : EmbeddedWorkerTestHelper(base::FilePath(), kRenderProcessId) {} |
| 102 ~FailToSendIPCHelper() override {} |
| 103 |
| 104 bool Send(IPC::Message* message) override { |
| 105 delete message; |
| 106 return false; |
| 107 } |
| 108 }; |
| 109 |
| 87 TEST_F(EmbeddedWorkerInstanceTest, StartAndStop) { | 110 TEST_F(EmbeddedWorkerInstanceTest, StartAndStop) { |
| 88 scoped_ptr<EmbeddedWorkerInstance> worker = | 111 scoped_ptr<EmbeddedWorkerInstance> worker = |
| 89 embedded_worker_registry()->CreateWorker(); | 112 embedded_worker_registry()->CreateWorker(); |
| 90 EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status()); | 113 EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status()); |
| 91 | 114 |
| 92 const int64 service_worker_version_id = 55L; | 115 const int64 service_worker_version_id = 55L; |
| 93 const GURL pattern("http://example.com/"); | 116 const GURL pattern("http://example.com/"); |
| 94 const GURL url("http://example.com/worker.js"); | 117 const GURL url("http://example.com/worker.js"); |
| 95 | 118 |
| 96 // Simulate adding one process to the pattern. | 119 // Simulate adding one process to the pattern. |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 225 EXPECT_EQ(1UL, registry->worker_process_map_[kRenderProcessId].count( | 248 EXPECT_EQ(1UL, registry->worker_process_map_[kRenderProcessId].count( |
| 226 worker2->embedded_worker_id())); | 249 worker2->embedded_worker_id())); |
| 227 | 250 |
| 228 worker2->Stop(); | 251 worker2->Stop(); |
| 229 } | 252 } |
| 230 | 253 |
| 231 // Test detaching in the middle of the start worker sequence. | 254 // Test detaching in the middle of the start worker sequence. |
| 232 TEST_F(EmbeddedWorkerInstanceTest, DetachDuringStart) { | 255 TEST_F(EmbeddedWorkerInstanceTest, DetachDuringStart) { |
| 233 scoped_ptr<EmbeddedWorkerInstance> worker = | 256 scoped_ptr<EmbeddedWorkerInstance> worker = |
| 234 embedded_worker_registry()->CreateWorker(); | 257 embedded_worker_registry()->CreateWorker(); |
| 258 worker->AddListener(this); |
| 259 |
| 235 scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params( | 260 scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params( |
| 236 new EmbeddedWorkerMsg_StartWorker_Params()); | 261 new EmbeddedWorkerMsg_StartWorker_Params()); |
| 237 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED; | 262 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED; |
| 238 // Pretend we had a process allocated but then got detached before | 263 |
| 239 // the start sequence reached SendStartWorker. | 264 // Pretend the worker got stopped before the start sequence reached |
| 240 worker->process_id_ = -1; | 265 // SendStartWorker. |
| 241 worker->SendStartWorker(params.Pass(), base::Bind(&SaveStatus, &status), true, | 266 worker->status_ = EmbeddedWorkerInstance::STOPPED; |
| 242 -1, false); | 267 base::RunLoop run_loop; |
| 268 worker->SendStartWorker(params.Pass(), base::Bind(&SaveStatusAndCall, &status, |
| 269 run_loop.QuitClosure()), |
| 270 true, -1, false); |
| 271 run_loop.Run(); |
| 272 EXPECT_EQ(SERVICE_WORKER_ERROR_ABORT, status); |
| 273 // Don't expect SendStartWorker() to dispatch an OnStopped/Detached() message |
| 274 // since the worker was already stopped. |
| 275 EXPECT_FALSE(stopped_); |
| 276 EXPECT_FALSE(detached_); |
| 277 |
| 278 // Repeat, this time have the start callback destroy the worker, as is |
| 279 // usual when starting a worker fails, and ensure a crash doesn't occur. |
| 280 worker->status_ = EmbeddedWorkerInstance::STOPPED; |
| 281 EmbeddedWorkerInstance* worker_ptr = worker.get(); |
| 282 worker_ptr->SendStartWorker( |
| 283 params.Pass(), base::Bind(&DestroyWorker, base::Passed(&worker), &status), |
| 284 true, -1, false); |
| 285 // No crash. |
| 243 EXPECT_EQ(SERVICE_WORKER_ERROR_ABORT, status); | 286 EXPECT_EQ(SERVICE_WORKER_ERROR_ABORT, status); |
| 244 } | 287 } |
| 245 | 288 |
| 246 // Test stopping in the middle of the start worker sequence, before | 289 // Test stopping in the middle of the start worker sequence, before |
| 247 // a process is allocated. | 290 // a process is allocated. |
| 248 TEST_F(EmbeddedWorkerInstanceTest, StopDuringStart) { | 291 TEST_F(EmbeddedWorkerInstanceTest, StopDuringStart) { |
| 249 scoped_ptr<EmbeddedWorkerInstance> worker = | 292 scoped_ptr<EmbeddedWorkerInstance> worker = |
| 250 embedded_worker_registry()->CreateWorker(); | 293 embedded_worker_registry()->CreateWorker(); |
| 251 worker->AddListener(this); | 294 worker->AddListener(this); |
| 252 scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params( | |
| 253 new EmbeddedWorkerMsg_StartWorker_Params()); | |
| 254 // Pretend we stop during starting before we got a process allocated. | 295 // Pretend we stop during starting before we got a process allocated. |
| 255 worker->status_ = EmbeddedWorkerInstance::STARTING; | 296 worker->status_ = EmbeddedWorkerInstance::STARTING; |
| 256 worker->process_id_ = -1; | 297 worker->process_id_ = -1; |
| 257 worker->Stop(); | 298 worker->Stop(); |
| 258 EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status()); | 299 EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status()); |
| 259 EXPECT_TRUE(detached_); | 300 EXPECT_TRUE(detached_); |
| 260 EXPECT_EQ(EmbeddedWorkerInstance::STARTING, detached_old_status_); | 301 EXPECT_EQ(EmbeddedWorkerInstance::STARTING, detached_old_status_); |
| 261 } | 302 } |
| 262 | 303 |
| 304 // Test for when sending the start IPC failed. |
| 305 TEST_F(EmbeddedWorkerInstanceTest, FailToSendStartIPC) { |
| 306 helper_.reset(new FailToSendIPCHelper()); |
| 307 |
| 308 const int64 version_id = 55L; |
| 309 const GURL pattern("http://example.com/"); |
| 310 const GURL url("http://example.com/worker.js"); |
| 311 |
| 312 scoped_ptr<EmbeddedWorkerInstance> worker = |
| 313 embedded_worker_registry()->CreateWorker(); |
| 314 helper_->SimulateAddProcessToPattern(pattern, kRenderProcessId); |
| 315 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED; |
| 316 worker->AddListener(this); |
| 317 |
| 318 // Attempt to start the worker. |
| 319 base::RunLoop run_loop; |
| 320 worker->Start( |
| 321 version_id, pattern, url, |
| 322 base::Bind(&SaveStatusAndCall, &status, run_loop.QuitClosure())); |
| 323 run_loop.Run(); |
| 324 |
| 325 // The callback should have run, and we should have got an OnStopped message. |
| 326 EXPECT_EQ(SERVICE_WORKER_ERROR_IPC_FAILED, status); |
| 327 EXPECT_TRUE(stopped_); |
| 328 EXPECT_EQ(EmbeddedWorkerInstance::STARTING, stopped_old_status_); |
| 329 } |
| 330 |
| 263 } // namespace content | 331 } // namespace content |
| OLD | NEW |