Blink roll 25b6bd3a7a131ffe68d809546ad1a20707915cdc:3a503f41ae42e5b79cfcd2ff10e65afde...
[chromium-blink-merge.git] / content / browser / service_worker / service_worker_version_unittest.cc
blob31225e963572de85d6919aa1767c42039edfc5ff
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/basictypes.h"
6 #include "base/run_loop.h"
7 #include "content/browser/service_worker/embedded_worker_registry.h"
8 #include "content/browser/service_worker/embedded_worker_test_helper.h"
9 #include "content/browser/service_worker/service_worker_context_core.h"
10 #include "content/browser/service_worker/service_worker_registration.h"
11 #include "content/browser/service_worker/service_worker_test_utils.h"
12 #include "content/browser/service_worker/service_worker_version.h"
13 #include "content/public/test/test_browser_thread_bundle.h"
14 #include "testing/gtest/include/gtest/gtest.h"
16 // IPC messages for testing ---------------------------------------------------
18 #define IPC_MESSAGE_IMPL
19 #include "ipc/ipc_message_macros.h"
21 #define IPC_MESSAGE_START TestMsgStart
23 IPC_MESSAGE_CONTROL0(TestMsg_Message);
24 IPC_MESSAGE_ROUTED1(TestMsg_MessageFromWorker, int);
26 // ---------------------------------------------------------------------------
28 namespace content {
30 namespace {
32 static const int kRenderProcessId = 1;
34 class MessageReceiver : public EmbeddedWorkerTestHelper {
35 public:
36 MessageReceiver()
37 : EmbeddedWorkerTestHelper(kRenderProcessId),
38 current_embedded_worker_id_(0) {}
39 ~MessageReceiver() override {}
41 bool OnMessageToWorker(int thread_id,
42 int embedded_worker_id,
43 const IPC::Message& message) override {
44 if (EmbeddedWorkerTestHelper::OnMessageToWorker(
45 thread_id, embedded_worker_id, message)) {
46 return true;
48 current_embedded_worker_id_ = embedded_worker_id;
49 bool handled = true;
50 IPC_BEGIN_MESSAGE_MAP(MessageReceiver, message)
51 IPC_MESSAGE_HANDLER(TestMsg_Message, OnMessage)
52 IPC_MESSAGE_UNHANDLED(handled = false)
53 IPC_END_MESSAGE_MAP()
54 return handled;
57 void SimulateSendValueToBrowser(int embedded_worker_id, int value) {
58 SimulateSend(new TestMsg_MessageFromWorker(embedded_worker_id, value));
61 private:
62 void OnMessage() {
63 // Do nothing.
66 int current_embedded_worker_id_;
67 DISALLOW_COPY_AND_ASSIGN(MessageReceiver);
70 void VerifyCalled(bool* called) {
71 *called = true;
74 void ObserveStatusChanges(ServiceWorkerVersion* version,
75 std::vector<ServiceWorkerVersion::Status>* statuses) {
76 statuses->push_back(version->status());
77 version->RegisterStatusChangeCallback(
78 base::Bind(&ObserveStatusChanges, base::Unretained(version), statuses));
81 // A specialized listener class to receive test messages from a worker.
82 class MessageReceiverFromWorker : public EmbeddedWorkerInstance::Listener {
83 public:
84 explicit MessageReceiverFromWorker(EmbeddedWorkerInstance* instance)
85 : instance_(instance) {
86 instance_->AddListener(this);
88 ~MessageReceiverFromWorker() override { instance_->RemoveListener(this); }
90 void OnStarted() override { NOTREACHED(); }
91 void OnStopped() override { NOTREACHED(); }
92 bool OnMessageReceived(const IPC::Message& message) override {
93 bool handled = true;
94 IPC_BEGIN_MESSAGE_MAP(MessageReceiverFromWorker, message)
95 IPC_MESSAGE_HANDLER(TestMsg_MessageFromWorker, OnMessageFromWorker)
96 IPC_MESSAGE_UNHANDLED(handled = false)
97 IPC_END_MESSAGE_MAP()
98 return handled;
101 void OnMessageFromWorker(int value) { received_values_.push_back(value); }
102 const std::vector<int>& received_values() const { return received_values_; }
104 private:
105 EmbeddedWorkerInstance* instance_;
106 std::vector<int> received_values_;
107 DISALLOW_COPY_AND_ASSIGN(MessageReceiverFromWorker);
110 } // namespace
112 class ServiceWorkerVersionTest : public testing::Test {
113 protected:
114 ServiceWorkerVersionTest()
115 : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
117 void SetUp() override {
118 helper_ = GetMessageReceiver();
120 pattern_ = GURL("http://www.example.com/");
121 registration_ = new ServiceWorkerRegistration(
122 pattern_,
124 helper_->context()->AsWeakPtr());
125 version_ = new ServiceWorkerVersion(
126 registration_.get(),
127 GURL("http://www.example.com/service_worker.js"),
129 helper_->context()->AsWeakPtr());
131 // Simulate adding one process to the pattern.
132 helper_->SimulateAddProcessToPattern(pattern_, kRenderProcessId);
133 ASSERT_TRUE(helper_->context()->process_manager()
134 ->PatternHasProcessToRun(pattern_));
137 virtual scoped_ptr<MessageReceiver> GetMessageReceiver() {
138 return make_scoped_ptr(new MessageReceiver());
141 void TearDown() override {
142 version_ = 0;
143 registration_ = 0;
144 helper_.reset();
147 TestBrowserThreadBundle thread_bundle_;
148 scoped_ptr<MessageReceiver> helper_;
149 scoped_refptr<ServiceWorkerRegistration> registration_;
150 scoped_refptr<ServiceWorkerVersion> version_;
151 GURL pattern_;
153 private:
154 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerVersionTest);
157 class MessageReceiverDisallowStart : public MessageReceiver {
158 public:
159 MessageReceiverDisallowStart()
160 : MessageReceiver() {}
161 ~MessageReceiverDisallowStart() override {}
163 void OnStartWorker(int embedded_worker_id,
164 int64 service_worker_version_id,
165 const GURL& scope,
166 const GURL& script_url,
167 bool pause_after_download) override {
168 // Do nothing.
171 private:
172 DISALLOW_COPY_AND_ASSIGN(MessageReceiverDisallowStart);
175 class ServiceWorkerFailToStartTest : public ServiceWorkerVersionTest {
176 protected:
177 ServiceWorkerFailToStartTest()
178 : ServiceWorkerVersionTest() {}
180 virtual scoped_ptr<MessageReceiver> GetMessageReceiver() override {
181 return make_scoped_ptr(new MessageReceiverDisallowStart());
184 private:
185 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerFailToStartTest);
188 TEST_F(ServiceWorkerVersionTest, ConcurrentStartAndStop) {
189 // Call StartWorker() multiple times.
190 ServiceWorkerStatusCode status1 = SERVICE_WORKER_ERROR_FAILED;
191 ServiceWorkerStatusCode status2 = SERVICE_WORKER_ERROR_FAILED;
192 ServiceWorkerStatusCode status3 = SERVICE_WORKER_ERROR_FAILED;
193 version_->StartWorker(CreateReceiverOnCurrentThread(&status1));
194 version_->StartWorker(CreateReceiverOnCurrentThread(&status2));
196 EXPECT_EQ(ServiceWorkerVersion::STARTING, version_->running_status());
197 base::RunLoop().RunUntilIdle();
198 EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
200 // Call StartWorker() after it's started.
201 version_->StartWorker(CreateReceiverOnCurrentThread(&status3));
202 base::RunLoop().RunUntilIdle();
204 // All should just succeed.
205 EXPECT_EQ(SERVICE_WORKER_OK, status1);
206 EXPECT_EQ(SERVICE_WORKER_OK, status2);
207 EXPECT_EQ(SERVICE_WORKER_OK, status3);
209 // Call StopWorker() multiple times.
210 status1 = SERVICE_WORKER_ERROR_FAILED;
211 status2 = SERVICE_WORKER_ERROR_FAILED;
212 status3 = SERVICE_WORKER_ERROR_FAILED;
213 version_->StopWorker(CreateReceiverOnCurrentThread(&status1));
214 version_->StopWorker(CreateReceiverOnCurrentThread(&status2));
216 // Also try calling StartWorker while StopWorker is in queue.
217 version_->StartWorker(CreateReceiverOnCurrentThread(&status3));
219 EXPECT_EQ(ServiceWorkerVersion::STOPPING, version_->running_status());
220 base::RunLoop().RunUntilIdle();
221 EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
223 // All StopWorker should just succeed, while StartWorker fails.
224 EXPECT_EQ(SERVICE_WORKER_OK, status1);
225 EXPECT_EQ(SERVICE_WORKER_OK, status2);
226 EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, status3);
229 TEST_F(ServiceWorkerVersionTest, SendMessage) {
230 EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
232 // Send a message without starting the worker.
233 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
234 version_->SendMessage(TestMsg_Message(),
235 CreateReceiverOnCurrentThread(&status));
236 base::RunLoop().RunUntilIdle();
237 EXPECT_EQ(SERVICE_WORKER_OK, status);
239 // The worker should be now started.
240 EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
242 // Stop the worker, and then send the message immediately.
243 ServiceWorkerStatusCode msg_status = SERVICE_WORKER_ERROR_FAILED;
244 ServiceWorkerStatusCode stop_status = SERVICE_WORKER_ERROR_FAILED;
245 version_->StopWorker(CreateReceiverOnCurrentThread(&stop_status));
246 version_->SendMessage(TestMsg_Message(),
247 CreateReceiverOnCurrentThread(&msg_status));
248 base::RunLoop().RunUntilIdle();
249 EXPECT_EQ(SERVICE_WORKER_OK, stop_status);
251 // SendMessage should return START_WORKER_FAILED error since it tried to
252 // start a worker while it was stopping.
253 EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, msg_status);
256 TEST_F(ServiceWorkerVersionTest, ReSendMessageAfterStop) {
257 EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
259 // Start the worker.
260 ServiceWorkerStatusCode start_status = SERVICE_WORKER_ERROR_FAILED;
261 version_->StartWorker(CreateReceiverOnCurrentThread(&start_status));
262 base::RunLoop().RunUntilIdle();
263 EXPECT_EQ(SERVICE_WORKER_OK, start_status);
264 EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
266 // Stop the worker, and then send the message immediately.
267 ServiceWorkerStatusCode msg_status = SERVICE_WORKER_ERROR_FAILED;
268 ServiceWorkerStatusCode stop_status = SERVICE_WORKER_ERROR_FAILED;
269 version_->StopWorker(CreateReceiverOnCurrentThread(&stop_status));
270 version_->SendMessage(TestMsg_Message(),
271 CreateReceiverOnCurrentThread(&msg_status));
272 base::RunLoop().RunUntilIdle();
273 EXPECT_EQ(SERVICE_WORKER_OK, stop_status);
275 // SendMessage should return START_WORKER_FAILED error since it tried to
276 // start a worker while it was stopping.
277 EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, msg_status);
279 // Resend the message, which should succeed and restart the worker.
280 version_->SendMessage(TestMsg_Message(),
281 CreateReceiverOnCurrentThread(&msg_status));
282 base::RunLoop().RunUntilIdle();
283 EXPECT_EQ(SERVICE_WORKER_OK, msg_status);
284 EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
287 TEST_F(ServiceWorkerVersionTest, ReceiveMessageFromWorker) {
288 MessageReceiverFromWorker receiver(version_->embedded_worker());
290 // Simulate sending some dummy values from the worker.
291 helper_->SimulateSendValueToBrowser(
292 version_->embedded_worker()->embedded_worker_id(), 555);
293 helper_->SimulateSendValueToBrowser(
294 version_->embedded_worker()->embedded_worker_id(), 777);
296 // Verify the receiver received the values.
297 ASSERT_EQ(2U, receiver.received_values().size());
298 EXPECT_EQ(555, receiver.received_values()[0]);
299 EXPECT_EQ(777, receiver.received_values()[1]);
302 TEST_F(ServiceWorkerVersionTest, InstallAndWaitCompletion) {
303 version_->SetStatus(ServiceWorkerVersion::INSTALLING);
305 // Dispatch an install event.
306 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
307 version_->DispatchInstallEvent(-1, CreateReceiverOnCurrentThread(&status));
309 // Wait for the completion.
310 bool status_change_called = false;
311 version_->RegisterStatusChangeCallback(
312 base::Bind(&VerifyCalled, &status_change_called));
314 base::RunLoop().RunUntilIdle();
316 // Version's status must not have changed during installation.
317 EXPECT_EQ(SERVICE_WORKER_OK, status);
318 EXPECT_FALSE(status_change_called);
319 EXPECT_EQ(ServiceWorkerVersion::INSTALLING, version_->status());
322 TEST_F(ServiceWorkerVersionTest, ActivateAndWaitCompletion) {
323 version_->SetStatus(ServiceWorkerVersion::ACTIVATING);
325 // Dispatch an activate event.
326 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
327 version_->DispatchActivateEvent(CreateReceiverOnCurrentThread(&status));
329 // Wait for the completion.
330 bool status_change_called = false;
331 version_->RegisterStatusChangeCallback(
332 base::Bind(&VerifyCalled, &status_change_called));
334 base::RunLoop().RunUntilIdle();
336 // Version's status must not have changed during activation.
337 EXPECT_EQ(SERVICE_WORKER_OK, status);
338 EXPECT_FALSE(status_change_called);
339 EXPECT_EQ(ServiceWorkerVersion::ACTIVATING, version_->status());
342 TEST_F(ServiceWorkerVersionTest, RepeatedlyObserveStatusChanges) {
343 EXPECT_EQ(ServiceWorkerVersion::NEW, version_->status());
345 // Repeatedly observe status changes (the callback re-registers itself).
346 std::vector<ServiceWorkerVersion::Status> statuses;
347 version_->RegisterStatusChangeCallback(
348 base::Bind(&ObserveStatusChanges, version_, &statuses));
350 version_->SetStatus(ServiceWorkerVersion::INSTALLING);
351 version_->SetStatus(ServiceWorkerVersion::INSTALLED);
352 version_->SetStatus(ServiceWorkerVersion::ACTIVATING);
353 version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
354 version_->SetStatus(ServiceWorkerVersion::REDUNDANT);
356 // Verify that we could successfully observe repeated status changes.
357 ASSERT_EQ(5U, statuses.size());
358 ASSERT_EQ(ServiceWorkerVersion::INSTALLING, statuses[0]);
359 ASSERT_EQ(ServiceWorkerVersion::INSTALLED, statuses[1]);
360 ASSERT_EQ(ServiceWorkerVersion::ACTIVATING, statuses[2]);
361 ASSERT_EQ(ServiceWorkerVersion::ACTIVATED, statuses[3]);
362 ASSERT_EQ(ServiceWorkerVersion::REDUNDANT, statuses[4]);
365 TEST_F(ServiceWorkerVersionTest, ScheduleStopWorker) {
366 // Verify the timer is not running when version initializes its status.
367 version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
368 EXPECT_FALSE(version_->stop_worker_timer_.IsRunning());
370 // Verify the timer is running when version status changes frome ACTIVATING
371 // to ACTIVATED.
372 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
373 version_->StartWorker(CreateReceiverOnCurrentThread(&status));
374 base::RunLoop().RunUntilIdle();
375 EXPECT_EQ(SERVICE_WORKER_OK, status);
376 version_->SetStatus(ServiceWorkerVersion::ACTIVATING);
377 version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
378 EXPECT_TRUE(version_->stop_worker_timer_.IsRunning());
380 // The timer should be running if the worker is restarted without controllee.
381 status = SERVICE_WORKER_ERROR_FAILED;
382 version_->StopWorker(CreateReceiverOnCurrentThread(&status));
383 base::RunLoop().RunUntilIdle();
384 EXPECT_EQ(SERVICE_WORKER_OK, status);
385 status = SERVICE_WORKER_ERROR_FAILED;
386 version_->StartWorker(CreateReceiverOnCurrentThread(&status));
387 base::RunLoop().RunUntilIdle();
388 EXPECT_EQ(SERVICE_WORKER_OK, status);
389 EXPECT_TRUE(version_->stop_worker_timer_.IsRunning());
391 // The timer should not be running if a controllee is added.
392 scoped_ptr<ServiceWorkerProviderHost> host(
393 new ServiceWorkerProviderHost(33 /* dummy render process id */,
394 1 /* dummy provider_id */,
395 helper_->context()->AsWeakPtr(),
396 NULL));
397 version_->AddControllee(host.get());
398 EXPECT_FALSE(version_->stop_worker_timer_.IsRunning());
400 // The timer should be running if the controllee is removed.
401 version_->RemoveControllee(host.get());
402 EXPECT_TRUE(version_->stop_worker_timer_.IsRunning());
405 TEST_F(ServiceWorkerVersionTest, ListenerAvailability) {
406 // Initially the worker is not running. There should be no cache_listener_.
407 EXPECT_FALSE(version_->cache_listener_.get());
409 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
410 version_->StartWorker(
411 CreateReceiverOnCurrentThread(&status));
412 base::RunLoop().RunUntilIdle();
414 // A new cache listener should be available once the worker starts.
415 EXPECT_TRUE(version_->cache_listener_.get());
417 version_->StopWorker(
418 CreateReceiverOnCurrentThread(&status));
419 base::RunLoop().RunUntilIdle();
421 // Should be destroyed when the worker stops.
422 EXPECT_FALSE(version_->cache_listener_.get());
424 version_->StartWorker(
425 CreateReceiverOnCurrentThread(&status));
426 base::RunLoop().RunUntilIdle();
428 // Recreated when the worker starts again.
429 EXPECT_TRUE(version_->cache_listener_.get());
432 TEST_F(ServiceWorkerFailToStartTest, RendererCrash) {
433 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK; // dummy value
434 version_->StartWorker(
435 CreateReceiverOnCurrentThread(&status));
436 base::RunLoop().RunUntilIdle();
438 // Callback has not completed yet.
439 EXPECT_EQ(SERVICE_WORKER_ERROR_NETWORK, status);
440 EXPECT_EQ(ServiceWorkerVersion::STARTING, version_->running_status());
442 // Simulate renderer crash: do what
443 // ServiceWorkerDispatcherHost::OnFilterRemoved does.
444 int process_id = helper_->mock_render_process_id();
445 helper_->context()->RemoveAllProviderHostsForProcess(process_id);
446 helper_->context()->embedded_worker_registry()->RemoveChildProcessSender(
447 process_id);
448 base::RunLoop().RunUntilIdle();
450 // Callback completed.
451 EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, status);
452 EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
455 } // namespace content