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 |