Chromium Code Reviews| 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 // Takes a scoped_ptr<>* because the object is passed in via Bind() where Pass() |
| 25 *out = status; | 25 // 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
| |
| 26 void DestroyWorker(scoped_ptr<EmbeddedWorkerInstance>* worker, | |
| 27 ServiceWorkerStatusCode* out_status, | |
| 28 ServiceWorkerStatusCode status) { | |
| 29 *out_status = status; | |
| 30 worker->reset(); | |
| 26 } | 31 } |
| 27 | 32 |
| 28 void SaveStatusAndCall(ServiceWorkerStatusCode* out, | 33 void SaveStatusAndCall(ServiceWorkerStatusCode* out, |
| 29 const base::Closure& callback, | 34 const base::Closure& callback, |
| 30 ServiceWorkerStatusCode status) { | 35 ServiceWorkerStatusCode status) { |
| 31 *out = status; | 36 *out = status; |
| 32 callback.Run(); | 37 callback.Run(); |
| 33 } | 38 } |
| 34 | 39 |
| 35 } // namespace | 40 } // namespace |
| 36 | 41 |
| 37 class EmbeddedWorkerInstanceTest : public testing::Test, | 42 class EmbeddedWorkerInstanceTest : public testing::Test, |
| 38 public EmbeddedWorkerInstance::Listener { | 43 public EmbeddedWorkerInstance::Listener { |
| 39 protected: | 44 protected: |
| 40 EmbeddedWorkerInstanceTest() | 45 EmbeddedWorkerInstanceTest() |
| 41 : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {} | 46 : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {} |
| 42 | 47 |
| 48 void OnStopped(EmbeddedWorkerInstance::Status old_status) override { | |
| 49 stopped_ = true; | |
| 50 stopped_old_status_ = old_status; | |
| 51 } | |
| 52 | |
| 43 void OnDetached(EmbeddedWorkerInstance::Status old_status) override { | 53 void OnDetached(EmbeddedWorkerInstance::Status old_status) override { |
| 44 detached_ = true; | 54 detached_ = true; |
| 45 detached_old_status_ = old_status; | 55 detached_old_status_ = old_status; |
| 46 } | 56 } |
| 47 | 57 |
| 48 bool OnMessageReceived(const IPC::Message& message) override { return false; } | 58 bool OnMessageReceived(const IPC::Message& message) override { return false; } |
| 49 | 59 |
| 50 void SetUp() override { | 60 void SetUp() override { |
| 51 helper_.reset( | 61 helper_.reset( |
| 52 new EmbeddedWorkerTestHelper(base::FilePath(), kRenderProcessId)); | 62 new EmbeddedWorkerTestHelper(base::FilePath(), kRenderProcessId)); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 72 return context()->embedded_worker_registry(); | 82 return context()->embedded_worker_registry(); |
| 73 } | 83 } |
| 74 | 84 |
| 75 IPC::TestSink* ipc_sink() { return helper_->ipc_sink(); } | 85 IPC::TestSink* ipc_sink() { return helper_->ipc_sink(); } |
| 76 | 86 |
| 77 TestBrowserThreadBundle thread_bundle_; | 87 TestBrowserThreadBundle thread_bundle_; |
| 78 scoped_ptr<EmbeddedWorkerTestHelper> helper_; | 88 scoped_ptr<EmbeddedWorkerTestHelper> helper_; |
| 79 bool detached_ = false; | 89 bool detached_ = false; |
| 80 EmbeddedWorkerInstance::Status detached_old_status_ = | 90 EmbeddedWorkerInstance::Status detached_old_status_ = |
| 81 EmbeddedWorkerInstance::STOPPED; | 91 EmbeddedWorkerInstance::STOPPED; |
| 92 bool stopped_ = false; | |
| 93 EmbeddedWorkerInstance::Status stopped_old_status_ = | |
| 94 EmbeddedWorkerInstance::STOPPED; | |
| 82 | 95 |
| 83 private: | 96 private: |
| 84 DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerInstanceTest); | 97 DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerInstanceTest); |
| 85 }; | 98 }; |
| 86 | 99 |
| 100 class FailToSendIPCHelper : public EmbeddedWorkerTestHelper { | |
| 101 public: | |
| 102 FailToSendIPCHelper() | |
| 103 : EmbeddedWorkerTestHelper(base::FilePath(), kRenderProcessId) {} | |
| 104 ~FailToSendIPCHelper() override {} | |
| 105 bool Send(IPC::Message* message) override { return false; } | |
| 106 }; | |
| 107 | |
| 87 TEST_F(EmbeddedWorkerInstanceTest, StartAndStop) { | 108 TEST_F(EmbeddedWorkerInstanceTest, StartAndStop) { |
| 88 scoped_ptr<EmbeddedWorkerInstance> worker = | 109 scoped_ptr<EmbeddedWorkerInstance> worker = |
| 89 embedded_worker_registry()->CreateWorker(); | 110 embedded_worker_registry()->CreateWorker(); |
| 90 EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status()); | 111 EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status()); |
| 91 | 112 |
| 92 const int64 service_worker_version_id = 55L; | 113 const int64 service_worker_version_id = 55L; |
| 93 const GURL pattern("http://example.com/"); | 114 const GURL pattern("http://example.com/"); |
| 94 const GURL url("http://example.com/worker.js"); | 115 const GURL url("http://example.com/worker.js"); |
| 95 | 116 |
| 96 // Simulate adding one process to the pattern. | 117 // Simulate adding one process to the pattern. |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 221 EmbeddedWorkerRegistry* registry = | 242 EmbeddedWorkerRegistry* registry = |
| 222 helper_->context()->embedded_worker_registry(); | 243 helper_->context()->embedded_worker_registry(); |
| 223 EXPECT_EQ(0UL, | 244 EXPECT_EQ(0UL, |
| 224 registry->worker_process_map_[kRenderProcessId].count(worker1_id)); | 245 registry->worker_process_map_[kRenderProcessId].count(worker1_id)); |
| 225 EXPECT_EQ(1UL, registry->worker_process_map_[kRenderProcessId].count( | 246 EXPECT_EQ(1UL, registry->worker_process_map_[kRenderProcessId].count( |
| 226 worker2->embedded_worker_id())); | 247 worker2->embedded_worker_id())); |
| 227 | 248 |
| 228 worker2->Stop(); | 249 worker2->Stop(); |
| 229 } | 250 } |
| 230 | 251 |
| 231 // Test detaching in the middle of the start worker sequence. | 252 // Test detaching in the middle of the start worker sequence. Additionally, have |
| 253 // the start callback destroy the worker, as is usual when starting a worker | |
| 254 // fails, and ensure a crash doesn't occur. | |
| 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(); |
| 235 scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params( | 258 scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params( |
| 236 new EmbeddedWorkerMsg_StartWorker_Params()); | 259 new EmbeddedWorkerMsg_StartWorker_Params()); |
| 237 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED; | 260 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED; |
| 261 | |
| 238 // Pretend we had a process allocated but then got detached before | 262 // Pretend we had a process allocated but then got detached before |
| 239 // the start sequence reached SendStartWorker. | 263 // the start sequence reached SendStartWorker. |
| 240 worker->process_id_ = -1; | 264 worker->status_ = EmbeddedWorkerInstance::STOPPED; |
| 241 worker->SendStartWorker(params.Pass(), base::Bind(&SaveStatus, &status), true, | 265 worker->SendStartWorker(params.Pass(), |
| 266 base::Bind(&DestroyWorker, &worker, &status), true, | |
| 242 -1, false); | 267 -1, false); |
| 268 // The callback destroys the worker, but we shouldn't have crashed. | |
| 243 EXPECT_EQ(SERVICE_WORKER_ERROR_ABORT, status); | 269 EXPECT_EQ(SERVICE_WORKER_ERROR_ABORT, status); |
| 244 } | 270 } |
| 245 | 271 |
| 246 // Test stopping in the middle of the start worker sequence, before | 272 // Test stopping in the middle of the start worker sequence, before |
| 247 // a process is allocated. | 273 // a process is allocated. |
| 248 TEST_F(EmbeddedWorkerInstanceTest, StopDuringStart) { | 274 TEST_F(EmbeddedWorkerInstanceTest, StopDuringStart) { |
| 249 scoped_ptr<EmbeddedWorkerInstance> worker = | 275 scoped_ptr<EmbeddedWorkerInstance> worker = |
| 250 embedded_worker_registry()->CreateWorker(); | 276 embedded_worker_registry()->CreateWorker(); |
| 251 worker->AddListener(this); | 277 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. | 278 // Pretend we stop during starting before we got a process allocated. |
| 255 worker->status_ = EmbeddedWorkerInstance::STARTING; | 279 worker->status_ = EmbeddedWorkerInstance::STARTING; |
| 256 worker->process_id_ = -1; | 280 worker->process_id_ = -1; |
| 257 worker->Stop(); | 281 worker->Stop(); |
| 258 EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status()); | 282 EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status()); |
| 259 EXPECT_TRUE(detached_); | 283 EXPECT_TRUE(detached_); |
| 260 EXPECT_EQ(EmbeddedWorkerInstance::STARTING, detached_old_status_); | 284 EXPECT_EQ(EmbeddedWorkerInstance::STARTING, detached_old_status_); |
| 261 } | 285 } |
| 262 | 286 |
| 287 // Test for when sending the start IPC failed. | |
| 288 TEST_F(EmbeddedWorkerInstanceTest, FailToSendStartIPC) { | |
| 289 helper_.reset(new FailToSendIPCHelper()); | |
| 290 | |
| 291 const int64 version_id = 55L; | |
| 292 const GURL pattern("http://example.com/"); | |
| 293 const GURL url("http://example.com/worker.js"); | |
| 294 | |
| 295 scoped_ptr<EmbeddedWorkerInstance> worker = | |
| 296 embedded_worker_registry()->CreateWorker(); | |
| 297 helper_->SimulateAddProcessToPattern(pattern, kRenderProcessId); | |
| 298 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED; | |
| 299 worker->AddListener(this); | |
| 300 | |
| 301 // Attempt to start the worker. | |
| 302 base::RunLoop run_loop; | |
| 303 worker->Start( | |
| 304 version_id, pattern, url, | |
| 305 base::Bind(&SaveStatusAndCall, &status, run_loop.QuitClosure())); | |
| 306 run_loop.Run(); | |
| 307 | |
| 308 // The callback should have run, and we should have got an OnStopped message. | |
| 309 EXPECT_EQ(SERVICE_WORKER_ERROR_IPC_FAILED, status); | |
| 310 EXPECT_TRUE(stopped_); | |
| 311 EXPECT_EQ(EmbeddedWorkerInstance::STARTING, stopped_old_status_); | |
| 312 } | |
| 313 | |
| 263 } // namespace content | 314 } // namespace content |
| OLD | NEW |