Battery Status API: add UMA logging for Linux.
[chromium-blink-merge.git] / content / browser / service_worker / service_worker_job_unittest.cc
blobdd2c165450ba992171ef5f597408cdb37e27fc35
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/files/scoped_temp_dir.h"
6 #include "base/logging.h"
7 #include "base/run_loop.h"
8 #include "content/browser/browser_thread_impl.h"
9 #include "content/browser/service_worker/embedded_worker_registry.h"
10 #include "content/browser/service_worker/embedded_worker_test_helper.h"
11 #include "content/browser/service_worker/service_worker_context_core.h"
12 #include "content/browser/service_worker/service_worker_disk_cache.h"
13 #include "content/browser/service_worker/service_worker_job_coordinator.h"
14 #include "content/browser/service_worker/service_worker_registration.h"
15 #include "content/browser/service_worker/service_worker_registration_status.h"
16 #include "content/browser/service_worker/service_worker_test_utils.h"
17 #include "content/public/test/test_browser_thread_bundle.h"
18 #include "ipc/ipc_test_sink.h"
19 #include "net/base/io_buffer.h"
20 #include "net/base/net_errors.h"
21 #include "net/base/test_completion_callback.h"
22 #include "net/http/http_response_headers.h"
23 #include "testing/gtest/include/gtest/gtest.h"
25 using net::IOBuffer;
26 using net::TestCompletionCallback;
27 using net::WrappedIOBuffer;
29 // Unit tests for testing all job registration tasks.
30 namespace content {
32 namespace {
34 int kMockRenderProcessId = 88;
36 void SaveRegistrationCallback(
37 ServiceWorkerStatusCode expected_status,
38 bool* called,
39 scoped_refptr<ServiceWorkerRegistration>* registration_out,
40 ServiceWorkerStatusCode status,
41 ServiceWorkerRegistration* registration,
42 ServiceWorkerVersion* version) {
43 ASSERT_TRUE(!version || version->registration_id() == registration->id())
44 << version << " " << registration;
45 EXPECT_EQ(expected_status, status);
46 *called = true;
47 *registration_out = registration;
50 void SaveFoundRegistrationCallback(
51 ServiceWorkerStatusCode expected_status,
52 bool* called,
53 scoped_refptr<ServiceWorkerRegistration>* registration,
54 ServiceWorkerStatusCode status,
55 const scoped_refptr<ServiceWorkerRegistration>& result) {
56 EXPECT_EQ(expected_status, status);
57 *called = true;
58 *registration = result;
61 // Creates a callback which both keeps track of if it's been called,
62 // as well as the resulting registration. Whent the callback is fired,
63 // it ensures that the resulting status matches the expectation.
64 // 'called' is useful for making sure a sychronous callback is or
65 // isn't called.
66 ServiceWorkerRegisterJob::RegistrationCallback SaveRegistration(
67 ServiceWorkerStatusCode expected_status,
68 bool* called,
69 scoped_refptr<ServiceWorkerRegistration>* registration) {
70 *called = false;
71 return base::Bind(
72 &SaveRegistrationCallback, expected_status, called, registration);
75 ServiceWorkerStorage::FindRegistrationCallback SaveFoundRegistration(
76 ServiceWorkerStatusCode expected_status,
77 bool* called,
78 scoped_refptr<ServiceWorkerRegistration>* registration) {
79 *called = false;
80 return base::Bind(&SaveFoundRegistrationCallback,
81 expected_status,
82 called,
83 registration);
86 void SaveUnregistrationCallback(ServiceWorkerStatusCode expected_status,
87 bool* called,
88 ServiceWorkerStatusCode status) {
89 EXPECT_EQ(expected_status, status);
90 *called = true;
93 ServiceWorkerUnregisterJob::UnregistrationCallback SaveUnregistration(
94 ServiceWorkerStatusCode expected_status,
95 bool* called) {
96 *called = false;
97 return base::Bind(&SaveUnregistrationCallback, expected_status, called);
100 } // namespace
102 class ServiceWorkerJobTest : public testing::Test {
103 public:
104 ServiceWorkerJobTest()
105 : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
106 render_process_id_(kMockRenderProcessId) {}
108 virtual void SetUp() OVERRIDE {
109 helper_.reset(new EmbeddedWorkerTestHelper(render_process_id_));
112 virtual void TearDown() OVERRIDE {
113 helper_.reset();
116 ServiceWorkerContextCore* context() const { return helper_->context(); }
118 ServiceWorkerJobCoordinator* job_coordinator() const {
119 return context()->job_coordinator();
121 ServiceWorkerStorage* storage() const { return context()->storage(); }
123 protected:
124 TestBrowserThreadBundle browser_thread_bundle_;
125 scoped_ptr<EmbeddedWorkerTestHelper> helper_;
126 int render_process_id_;
129 TEST_F(ServiceWorkerJobTest, SameDocumentSameRegistration) {
130 scoped_refptr<ServiceWorkerRegistration> original_registration;
131 bool called;
132 job_coordinator()->Register(
133 GURL("http://www.example.com/"),
134 GURL("http://www.example.com/service_worker.js"),
135 render_process_id_,
136 SaveRegistration(SERVICE_WORKER_OK, &called, &original_registration));
137 EXPECT_FALSE(called);
138 base::RunLoop().RunUntilIdle();
139 EXPECT_TRUE(called);
141 scoped_refptr<ServiceWorkerRegistration> registration1;
142 storage()->FindRegistrationForDocument(
143 GURL("http://www.example.com/"),
144 SaveFoundRegistration(SERVICE_WORKER_OK, &called, &registration1));
145 scoped_refptr<ServiceWorkerRegistration> registration2;
146 storage()->FindRegistrationForDocument(
147 GURL("http://www.example.com/"),
148 SaveFoundRegistration(SERVICE_WORKER_OK, &called, &registration2));
149 base::RunLoop().RunUntilIdle();
150 EXPECT_TRUE(called);
151 ASSERT_TRUE(registration1.get());
152 ASSERT_EQ(registration1, original_registration);
153 ASSERT_EQ(registration1, registration2);
156 TEST_F(ServiceWorkerJobTest, SameMatchSameRegistration) {
157 bool called;
158 scoped_refptr<ServiceWorkerRegistration> original_registration;
159 job_coordinator()->Register(
160 GURL("http://www.example.com/"),
161 GURL("http://www.example.com/service_worker.js"),
162 render_process_id_,
163 SaveRegistration(SERVICE_WORKER_OK, &called, &original_registration));
164 EXPECT_FALSE(called);
165 base::RunLoop().RunUntilIdle();
166 EXPECT_TRUE(called);
167 ASSERT_NE(static_cast<ServiceWorkerRegistration*>(NULL),
168 original_registration.get());
170 scoped_refptr<ServiceWorkerRegistration> registration1;
171 storage()->FindRegistrationForDocument(
172 GURL("http://www.example.com/one"),
173 SaveFoundRegistration(SERVICE_WORKER_OK, &called, &registration1));
174 base::RunLoop().RunUntilIdle();
175 EXPECT_TRUE(called);
177 scoped_refptr<ServiceWorkerRegistration> registration2;
178 storage()->FindRegistrationForDocument(
179 GURL("http://www.example.com/two"),
180 SaveFoundRegistration(SERVICE_WORKER_OK, &called, &registration2));
181 base::RunLoop().RunUntilIdle();
182 EXPECT_TRUE(called);
183 ASSERT_EQ(registration1, original_registration);
184 ASSERT_EQ(registration1, registration2);
187 TEST_F(ServiceWorkerJobTest, DifferentMatchDifferentRegistration) {
188 bool called1;
189 scoped_refptr<ServiceWorkerRegistration> original_registration1;
190 job_coordinator()->Register(
191 GURL("http://www.example.com/one/"),
192 GURL("http://www.example.com/service_worker.js"),
193 render_process_id_,
194 SaveRegistration(SERVICE_WORKER_OK, &called1, &original_registration1));
196 bool called2;
197 scoped_refptr<ServiceWorkerRegistration> original_registration2;
198 job_coordinator()->Register(
199 GURL("http://www.example.com/two/"),
200 GURL("http://www.example.com/service_worker.js"),
201 render_process_id_,
202 SaveRegistration(SERVICE_WORKER_OK, &called2, &original_registration2));
204 EXPECT_FALSE(called1);
205 EXPECT_FALSE(called2);
206 base::RunLoop().RunUntilIdle();
207 EXPECT_TRUE(called2);
208 EXPECT_TRUE(called1);
210 scoped_refptr<ServiceWorkerRegistration> registration1;
211 storage()->FindRegistrationForDocument(
212 GURL("http://www.example.com/one/"),
213 SaveFoundRegistration(SERVICE_WORKER_OK, &called1, &registration1));
214 scoped_refptr<ServiceWorkerRegistration> registration2;
215 storage()->FindRegistrationForDocument(
216 GURL("http://www.example.com/two/"),
217 SaveFoundRegistration(SERVICE_WORKER_OK, &called2, &registration2));
219 base::RunLoop().RunUntilIdle();
220 EXPECT_TRUE(called2);
221 EXPECT_TRUE(called1);
222 ASSERT_NE(registration1, registration2);
225 // Make sure basic registration is working.
226 TEST_F(ServiceWorkerJobTest, Register) {
227 bool called = false;
228 scoped_refptr<ServiceWorkerRegistration> registration;
229 job_coordinator()->Register(
230 GURL("http://www.example.com/"),
231 GURL("http://www.example.com/service_worker.js"),
232 render_process_id_,
233 SaveRegistration(SERVICE_WORKER_OK, &called, &registration));
235 ASSERT_FALSE(called);
236 base::RunLoop().RunUntilIdle();
237 ASSERT_TRUE(called);
239 ASSERT_NE(scoped_refptr<ServiceWorkerRegistration>(NULL), registration);
242 // Make sure registrations are cleaned up when they are unregistered.
243 TEST_F(ServiceWorkerJobTest, Unregister) {
244 GURL pattern("http://www.example.com/");
246 bool called;
247 scoped_refptr<ServiceWorkerRegistration> registration;
248 job_coordinator()->Register(
249 pattern,
250 GURL("http://www.example.com/service_worker.js"),
251 render_process_id_,
252 SaveRegistration(SERVICE_WORKER_OK, &called, &registration));
254 ASSERT_FALSE(called);
255 base::RunLoop().RunUntilIdle();
256 ASSERT_TRUE(called);
258 job_coordinator()->Unregister(pattern,
259 SaveUnregistration(SERVICE_WORKER_OK, &called));
261 ASSERT_FALSE(called);
262 base::RunLoop().RunUntilIdle();
263 ASSERT_TRUE(called);
265 ASSERT_TRUE(registration->HasOneRef());
267 storage()->FindRegistrationForPattern(
268 pattern,
269 SaveFoundRegistration(SERVICE_WORKER_ERROR_NOT_FOUND,
270 &called, &registration));
272 ASSERT_FALSE(called);
273 base::RunLoop().RunUntilIdle();
274 ASSERT_TRUE(called);
276 ASSERT_EQ(scoped_refptr<ServiceWorkerRegistration>(NULL), registration);
279 TEST_F(ServiceWorkerJobTest, Unregister_NothingRegistered) {
280 GURL pattern("http://www.example.com/");
282 bool called;
283 job_coordinator()->Unregister(pattern,
284 SaveUnregistration(SERVICE_WORKER_OK, &called));
286 ASSERT_FALSE(called);
287 base::RunLoop().RunUntilIdle();
288 ASSERT_TRUE(called);
291 // Make sure registering a new script creates a new version and shares an
292 // existing registration.
293 TEST_F(ServiceWorkerJobTest, RegisterNewScript) {
294 GURL pattern("http://www.example.com/");
296 bool called;
297 scoped_refptr<ServiceWorkerRegistration> old_registration;
298 job_coordinator()->Register(
299 pattern,
300 GURL("http://www.example.com/service_worker.js"),
301 render_process_id_,
302 SaveRegistration(SERVICE_WORKER_OK, &called, &old_registration));
304 ASSERT_FALSE(called);
305 base::RunLoop().RunUntilIdle();
306 ASSERT_TRUE(called);
308 scoped_refptr<ServiceWorkerRegistration> old_registration_by_pattern;
309 storage()->FindRegistrationForPattern(
310 pattern,
311 SaveFoundRegistration(
312 SERVICE_WORKER_OK, &called, &old_registration_by_pattern));
314 ASSERT_FALSE(called);
315 base::RunLoop().RunUntilIdle();
316 ASSERT_TRUE(called);
318 ASSERT_EQ(old_registration, old_registration_by_pattern);
319 old_registration_by_pattern = NULL;
321 scoped_refptr<ServiceWorkerRegistration> new_registration;
322 job_coordinator()->Register(
323 pattern,
324 GURL("http://www.example.com/service_worker_new.js"),
325 render_process_id_,
326 SaveRegistration(SERVICE_WORKER_OK, &called, &new_registration));
328 ASSERT_FALSE(called);
329 base::RunLoop().RunUntilIdle();
330 ASSERT_TRUE(called);
332 ASSERT_EQ(old_registration, new_registration);
334 scoped_refptr<ServiceWorkerRegistration> new_registration_by_pattern;
335 storage()->FindRegistrationForPattern(
336 pattern,
337 SaveFoundRegistration(
338 SERVICE_WORKER_OK, &called, &new_registration));
340 ASSERT_FALSE(called);
341 base::RunLoop().RunUntilIdle();
342 ASSERT_TRUE(called);
344 ASSERT_NE(new_registration_by_pattern, old_registration);
347 // Make sure that when registering a duplicate pattern+script_url
348 // combination, that the same registration is used.
349 TEST_F(ServiceWorkerJobTest, RegisterDuplicateScript) {
350 GURL pattern("http://www.example.com/");
351 GURL script_url("http://www.example.com/service_worker.js");
353 bool called;
354 scoped_refptr<ServiceWorkerRegistration> old_registration;
355 job_coordinator()->Register(
356 pattern,
357 script_url,
358 render_process_id_,
359 SaveRegistration(SERVICE_WORKER_OK, &called, &old_registration));
361 ASSERT_FALSE(called);
362 base::RunLoop().RunUntilIdle();
363 ASSERT_TRUE(called);
365 scoped_refptr<ServiceWorkerRegistration> old_registration_by_pattern;
366 storage()->FindRegistrationForPattern(
367 pattern,
368 SaveFoundRegistration(
369 SERVICE_WORKER_OK, &called, &old_registration_by_pattern));
370 ASSERT_FALSE(called);
371 base::RunLoop().RunUntilIdle();
372 ASSERT_TRUE(called);
374 ASSERT_TRUE(old_registration_by_pattern.get());
376 scoped_refptr<ServiceWorkerRegistration> new_registration;
377 job_coordinator()->Register(
378 pattern,
379 script_url,
380 render_process_id_,
381 SaveRegistration(SERVICE_WORKER_OK, &called, &new_registration));
383 ASSERT_FALSE(called);
384 base::RunLoop().RunUntilIdle();
385 ASSERT_TRUE(called);
387 ASSERT_EQ(old_registration, new_registration);
389 ASSERT_FALSE(old_registration->HasOneRef());
391 scoped_refptr<ServiceWorkerRegistration> new_registration_by_pattern;
392 storage()->FindRegistrationForPattern(
393 pattern,
394 SaveFoundRegistration(
395 SERVICE_WORKER_OK, &called, &new_registration_by_pattern));
397 ASSERT_FALSE(called);
398 base::RunLoop().RunUntilIdle();
399 ASSERT_TRUE(called);
401 ASSERT_EQ(new_registration, old_registration);
404 class FailToStartWorkerTestHelper : public EmbeddedWorkerTestHelper {
405 public:
406 explicit FailToStartWorkerTestHelper(int mock_render_process_id)
407 : EmbeddedWorkerTestHelper(mock_render_process_id) {}
409 virtual void OnStartWorker(int embedded_worker_id,
410 int64 service_worker_version_id,
411 const GURL& scope,
412 const GURL& script_url,
413 bool pause_after_download) OVERRIDE {
414 EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
415 registry()->OnWorkerStopped(worker->process_id(), embedded_worker_id);
419 TEST_F(ServiceWorkerJobTest, Register_FailToStartWorker) {
420 helper_.reset(new FailToStartWorkerTestHelper(render_process_id_));
422 bool called = false;
423 scoped_refptr<ServiceWorkerRegistration> registration;
424 job_coordinator()->Register(
425 GURL("http://www.example.com/"),
426 GURL("http://www.example.com/service_worker.js"),
427 render_process_id_,
428 SaveRegistration(
429 SERVICE_WORKER_ERROR_START_WORKER_FAILED, &called, &registration));
431 ASSERT_FALSE(called);
432 base::RunLoop().RunUntilIdle();
434 ASSERT_TRUE(called);
435 ASSERT_EQ(scoped_refptr<ServiceWorkerRegistration>(NULL), registration);
438 // Register and then unregister the pattern, in parallel. Job coordinator should
439 // process jobs until the last job.
440 TEST_F(ServiceWorkerJobTest, ParallelRegUnreg) {
441 GURL pattern("http://www.example.com/");
442 GURL script_url("http://www.example.com/service_worker.js");
444 bool registration_called = false;
445 scoped_refptr<ServiceWorkerRegistration> registration;
446 job_coordinator()->Register(
447 pattern,
448 script_url,
449 render_process_id_,
450 SaveRegistration(SERVICE_WORKER_OK, &registration_called, &registration));
452 bool unregistration_called = false;
453 job_coordinator()->Unregister(
454 pattern,
455 SaveUnregistration(SERVICE_WORKER_OK, &unregistration_called));
457 ASSERT_FALSE(registration_called);
458 ASSERT_FALSE(unregistration_called);
459 base::RunLoop().RunUntilIdle();
460 ASSERT_TRUE(registration_called);
461 ASSERT_TRUE(unregistration_called);
463 bool find_called = false;
464 storage()->FindRegistrationForPattern(
465 pattern,
466 SaveFoundRegistration(
467 SERVICE_WORKER_ERROR_NOT_FOUND, &find_called, &registration));
469 base::RunLoop().RunUntilIdle();
471 ASSERT_EQ(scoped_refptr<ServiceWorkerRegistration>(), registration);
474 // Register conflicting scripts for the same pattern. The most recent
475 // registration should win, and the old registration should have been
476 // shutdown.
477 TEST_F(ServiceWorkerJobTest, ParallelRegNewScript) {
478 GURL pattern("http://www.example.com/");
480 GURL script_url1("http://www.example.com/service_worker1.js");
481 bool registration1_called = false;
482 scoped_refptr<ServiceWorkerRegistration> registration1;
483 job_coordinator()->Register(
484 pattern,
485 script_url1,
486 render_process_id_,
487 SaveRegistration(
488 SERVICE_WORKER_OK, &registration1_called, &registration1));
490 GURL script_url2("http://www.example.com/service_worker2.js");
491 bool registration2_called = false;
492 scoped_refptr<ServiceWorkerRegistration> registration2;
493 job_coordinator()->Register(
494 pattern,
495 script_url2,
496 render_process_id_,
497 SaveRegistration(
498 SERVICE_WORKER_OK, &registration2_called, &registration2));
500 ASSERT_FALSE(registration1_called);
501 ASSERT_FALSE(registration2_called);
502 base::RunLoop().RunUntilIdle();
503 ASSERT_TRUE(registration1_called);
504 ASSERT_TRUE(registration2_called);
506 scoped_refptr<ServiceWorkerRegistration> registration;
507 bool find_called = false;
508 storage()->FindRegistrationForPattern(
509 pattern,
510 SaveFoundRegistration(
511 SERVICE_WORKER_OK, &find_called, &registration));
513 base::RunLoop().RunUntilIdle();
515 ASSERT_EQ(registration2, registration);
518 // Register the exact same pattern + script. Requests should be
519 // coalesced such that both callers get the exact same registration
520 // object.
521 TEST_F(ServiceWorkerJobTest, ParallelRegSameScript) {
522 GURL pattern("http://www.example.com/");
524 GURL script_url("http://www.example.com/service_worker1.js");
525 bool registration1_called = false;
526 scoped_refptr<ServiceWorkerRegistration> registration1;
527 job_coordinator()->Register(
528 pattern,
529 script_url,
530 render_process_id_,
531 SaveRegistration(
532 SERVICE_WORKER_OK, &registration1_called, &registration1));
534 bool registration2_called = false;
535 scoped_refptr<ServiceWorkerRegistration> registration2;
536 job_coordinator()->Register(
537 pattern,
538 script_url,
539 render_process_id_,
540 SaveRegistration(
541 SERVICE_WORKER_OK, &registration2_called, &registration2));
543 ASSERT_FALSE(registration1_called);
544 ASSERT_FALSE(registration2_called);
545 base::RunLoop().RunUntilIdle();
546 ASSERT_TRUE(registration1_called);
547 ASSERT_TRUE(registration2_called);
549 ASSERT_EQ(registration1, registration2);
551 scoped_refptr<ServiceWorkerRegistration> registration;
552 bool find_called = false;
553 storage()->FindRegistrationForPattern(
554 pattern,
555 SaveFoundRegistration(
556 SERVICE_WORKER_OK, &find_called, &registration));
558 base::RunLoop().RunUntilIdle();
559 ASSERT_EQ(registration, registration1);
562 // Call simulataneous unregister calls.
563 TEST_F(ServiceWorkerJobTest, ParallelUnreg) {
564 GURL pattern("http://www.example.com/");
566 GURL script_url("http://www.example.com/service_worker.js");
567 bool unregistration1_called = false;
568 job_coordinator()->Unregister(
569 pattern,
570 SaveUnregistration(SERVICE_WORKER_OK, &unregistration1_called));
572 bool unregistration2_called = false;
573 job_coordinator()->Unregister(
574 pattern, SaveUnregistration(SERVICE_WORKER_OK, &unregistration2_called));
576 ASSERT_FALSE(unregistration1_called);
577 ASSERT_FALSE(unregistration2_called);
578 base::RunLoop().RunUntilIdle();
579 ASSERT_TRUE(unregistration1_called);
580 ASSERT_TRUE(unregistration2_called);
582 // There isn't really a way to test that they are being coalesced,
583 // but we can make sure they can exist simultaneously without
584 // crashing.
585 scoped_refptr<ServiceWorkerRegistration> registration;
586 bool find_called = false;
587 storage()->FindRegistrationForPattern(
588 pattern,
589 SaveFoundRegistration(
590 SERVICE_WORKER_ERROR_NOT_FOUND, &find_called, &registration));
592 base::RunLoop().RunUntilIdle();
593 ASSERT_EQ(scoped_refptr<ServiceWorkerRegistration>(), registration);
596 TEST_F(ServiceWorkerJobTest, AbortAll_Register) {
597 GURL pattern1("http://www1.example.com/");
598 GURL pattern2("http://www2.example.com/");
599 GURL script_url1("http://www1.example.com/service_worker.js");
600 GURL script_url2("http://www2.example.com/service_worker.js");
602 bool registration_called1 = false;
603 scoped_refptr<ServiceWorkerRegistration> registration1;
604 job_coordinator()->Register(
605 pattern1,
606 script_url1,
607 render_process_id_,
608 SaveRegistration(SERVICE_WORKER_ERROR_ABORT,
609 &registration_called1, &registration1));
611 bool registration_called2 = false;
612 scoped_refptr<ServiceWorkerRegistration> registration2;
613 job_coordinator()->Register(
614 pattern2,
615 script_url2,
616 render_process_id_,
617 SaveRegistration(SERVICE_WORKER_ERROR_ABORT,
618 &registration_called2, &registration2));
620 ASSERT_FALSE(registration_called1);
621 ASSERT_FALSE(registration_called2);
622 job_coordinator()->AbortAll();
624 base::RunLoop().RunUntilIdle();
625 ASSERT_TRUE(registration_called1);
626 ASSERT_TRUE(registration_called2);
628 bool find_called1 = false;
629 storage()->FindRegistrationForPattern(
630 pattern1,
631 SaveFoundRegistration(
632 SERVICE_WORKER_ERROR_NOT_FOUND, &find_called1, &registration1));
634 bool find_called2 = false;
635 storage()->FindRegistrationForPattern(
636 pattern2,
637 SaveFoundRegistration(
638 SERVICE_WORKER_ERROR_NOT_FOUND, &find_called2, &registration2));
640 base::RunLoop().RunUntilIdle();
641 ASSERT_TRUE(find_called1);
642 ASSERT_TRUE(find_called2);
643 EXPECT_EQ(scoped_refptr<ServiceWorkerRegistration>(), registration1);
644 EXPECT_EQ(scoped_refptr<ServiceWorkerRegistration>(), registration2);
647 TEST_F(ServiceWorkerJobTest, AbortAll_Unregister) {
648 GURL pattern1("http://www1.example.com/");
649 GURL pattern2("http://www2.example.com/");
651 bool unregistration_called1 = false;
652 scoped_refptr<ServiceWorkerRegistration> registration1;
653 job_coordinator()->Unregister(
654 pattern1,
655 SaveUnregistration(SERVICE_WORKER_ERROR_ABORT,
656 &unregistration_called1));
658 bool unregistration_called2 = false;
659 job_coordinator()->Unregister(
660 pattern2,
661 SaveUnregistration(SERVICE_WORKER_ERROR_ABORT,
662 &unregistration_called2));
664 ASSERT_FALSE(unregistration_called1);
665 ASSERT_FALSE(unregistration_called2);
666 job_coordinator()->AbortAll();
668 base::RunLoop().RunUntilIdle();
669 ASSERT_TRUE(unregistration_called1);
670 ASSERT_TRUE(unregistration_called2);
673 TEST_F(ServiceWorkerJobTest, AbortAll_RegUnreg) {
674 GURL pattern("http://www.example.com/");
675 GURL script_url("http://www.example.com/service_worker.js");
677 bool registration_called = false;
678 scoped_refptr<ServiceWorkerRegistration> registration;
679 job_coordinator()->Register(
680 pattern,
681 script_url,
682 render_process_id_,
683 SaveRegistration(SERVICE_WORKER_ERROR_ABORT,
684 &registration_called, &registration));
686 bool unregistration_called = false;
687 job_coordinator()->Unregister(
688 pattern,
689 SaveUnregistration(SERVICE_WORKER_ERROR_ABORT,
690 &unregistration_called));
692 ASSERT_FALSE(registration_called);
693 ASSERT_FALSE(unregistration_called);
694 job_coordinator()->AbortAll();
696 base::RunLoop().RunUntilIdle();
697 ASSERT_TRUE(registration_called);
698 ASSERT_TRUE(unregistration_called);
700 bool find_called = false;
701 storage()->FindRegistrationForPattern(
702 pattern,
703 SaveFoundRegistration(
704 SERVICE_WORKER_ERROR_NOT_FOUND, &find_called, &registration));
706 base::RunLoop().RunUntilIdle();
707 ASSERT_TRUE(find_called);
708 EXPECT_EQ(scoped_refptr<ServiceWorkerRegistration>(), registration);
711 // Tests that the waiting worker enters the 'redundant' state upon
712 // unregistration.
713 TEST_F(ServiceWorkerJobTest, UnregisterWaitingSetsRedundant) {
714 scoped_refptr<ServiceWorkerRegistration> registration;
715 bool called = false;
716 GURL script_url("http://www.example.com/service_worker.js");
717 job_coordinator()->Register(
718 GURL("http://www.example.com/"),
719 script_url,
720 render_process_id_,
721 SaveRegistration(SERVICE_WORKER_OK, &called, &registration));
722 base::RunLoop().RunUntilIdle();
723 ASSERT_TRUE(called);
724 ASSERT_TRUE(registration.get());
726 // Manually create the waiting worker since there is no way to become a
727 // waiting worker until Update is implemented.
728 scoped_refptr<ServiceWorkerVersion> version = new ServiceWorkerVersion(
729 registration.get(), script_url, 1L, helper_->context()->AsWeakPtr());
730 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
731 version->StartWorker(CreateReceiverOnCurrentThread(&status));
732 base::RunLoop().RunUntilIdle();
733 ASSERT_EQ(SERVICE_WORKER_OK, status);
735 version->SetStatus(ServiceWorkerVersion::INSTALLED);
736 registration->SetWaitingVersion(version.get());
737 EXPECT_EQ(ServiceWorkerVersion::RUNNING,
738 version->running_status());
739 EXPECT_EQ(ServiceWorkerVersion::INSTALLED, version->status());
741 called = false;
742 job_coordinator()->Unregister(GURL("http://www.example.com/"),
743 SaveUnregistration(SERVICE_WORKER_OK, &called));
744 base::RunLoop().RunUntilIdle();
745 ASSERT_TRUE(called);
747 // The version should be stopped since there is no controllee after
748 // unregistration.
749 EXPECT_EQ(ServiceWorkerVersion::STOPPED, version->running_status());
750 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, version->status());
753 // Tests that the active worker enters the 'redundant' state upon
754 // unregistration.
755 TEST_F(ServiceWorkerJobTest, UnregisterActiveSetsRedundant) {
756 scoped_refptr<ServiceWorkerRegistration> registration;
757 bool called = false;
758 job_coordinator()->Register(
759 GURL("http://www.example.com/"),
760 GURL("http://www.example.com/service_worker.js"),
761 render_process_id_,
762 SaveRegistration(SERVICE_WORKER_OK, &called, &registration));
763 base::RunLoop().RunUntilIdle();
764 ASSERT_TRUE(called);
765 ASSERT_TRUE(registration.get());
767 scoped_refptr<ServiceWorkerVersion> version = registration->active_version();
768 EXPECT_EQ(ServiceWorkerVersion::RUNNING, version->running_status());
769 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, version->status());
771 called = false;
772 job_coordinator()->Unregister(GURL("http://www.example.com/"),
773 SaveUnregistration(SERVICE_WORKER_OK, &called));
774 base::RunLoop().RunUntilIdle();
775 ASSERT_TRUE(called);
777 // The version should be stopped since there is no controllee after
778 // unregistration.
779 EXPECT_EQ(ServiceWorkerVersion::STOPPED, version->running_status());
780 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, version->status());
783 // Tests that the active worker enters the 'redundant' state upon
784 // unregistration.
785 TEST_F(ServiceWorkerJobTest,
786 UnregisterActiveSetsRedundant_WaitForNoControllee) {
787 scoped_refptr<ServiceWorkerRegistration> registration;
788 bool called = false;
789 job_coordinator()->Register(
790 GURL("http://www.example.com/"),
791 GURL("http://www.example.com/service_worker.js"),
792 render_process_id_,
793 SaveRegistration(SERVICE_WORKER_OK, &called, &registration));
794 base::RunLoop().RunUntilIdle();
795 ASSERT_TRUE(called);
796 ASSERT_TRUE(registration.get());
798 scoped_ptr<ServiceWorkerProviderHost> host(
799 new ServiceWorkerProviderHost(33 /* dummy render process id */,
800 1 /* dummy provider_id */,
801 context()->AsWeakPtr(),
802 NULL));
803 registration->active_version()->AddControllee(host.get());
805 scoped_refptr<ServiceWorkerVersion> version = registration->active_version();
806 EXPECT_EQ(ServiceWorkerVersion::RUNNING, version->running_status());
807 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, version->status());
809 called = false;
810 job_coordinator()->Unregister(GURL("http://www.example.com/"),
811 SaveUnregistration(SERVICE_WORKER_OK, &called));
812 base::RunLoop().RunUntilIdle();
813 ASSERT_TRUE(called);
815 // The version should be running since there is still a controllee.
816 EXPECT_EQ(ServiceWorkerVersion::RUNNING, version->running_status());
817 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, version->status());
819 registration->active_version()->RemoveControllee(host.get());
820 base::RunLoop().RunUntilIdle();
822 // The version should be stopped since there is no controllee.
823 EXPECT_EQ(ServiceWorkerVersion::STOPPED, version->running_status());
824 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, version->status());
827 namespace { // Helpers for the update job tests.
829 const GURL kNoChangeOrigin("http://nochange/");
830 const GURL kNewVersionOrigin("http://newversion/");
831 const std::string kScope("scope/");
832 const std::string kScript("script.js");
834 void RunNestedUntilIdle() {
835 base::MessageLoop::ScopedNestableTaskAllower allow(
836 base::MessageLoop::current());
837 base::MessageLoop::current()->RunUntilIdle();
840 void OnIOComplete(int* rv_out, int rv) {
841 *rv_out = rv;
844 void WriteResponse(
845 ServiceWorkerStorage* storage, int64 id,
846 const std::string& headers,
847 IOBuffer* body, int length) {
848 scoped_ptr<ServiceWorkerResponseWriter> writer =
849 storage->CreateResponseWriter(id);
851 scoped_ptr<net::HttpResponseInfo> info(new net::HttpResponseInfo);
852 info->request_time = base::Time::Now();
853 info->response_time = base::Time::Now();
854 info->was_cached = false;
855 info->headers = new net::HttpResponseHeaders(headers);
856 scoped_refptr<HttpResponseInfoIOBuffer> info_buffer =
857 new HttpResponseInfoIOBuffer(info.release());
859 int rv = -1234;
860 writer->WriteInfo(info_buffer.get(), base::Bind(&OnIOComplete, &rv));
861 RunNestedUntilIdle();
862 EXPECT_LT(0, rv);
864 rv = -1234;
865 writer->WriteData(body, length,
866 base::Bind(&OnIOComplete, &rv));
867 RunNestedUntilIdle();
868 EXPECT_EQ(length, rv);
871 void WriteStringResponse(
872 ServiceWorkerStorage* storage, int64 id,
873 const std::string& body) {
874 scoped_refptr<IOBuffer> body_buffer(new WrappedIOBuffer(body.data()));
875 const char kHttpHeaders[] = "HTTP/1.0 200 HONKYDORY\0\0";
876 std::string headers(kHttpHeaders, arraysize(kHttpHeaders));
877 WriteResponse(storage, id, headers, body_buffer.get(), body.length());
880 class UpdateJobTestHelper
881 : public EmbeddedWorkerTestHelper,
882 public ServiceWorkerRegistration::Listener,
883 public ServiceWorkerVersion::Listener {
884 public:
885 struct AttributeChangeLogEntry {
886 int64 registration_id;
887 ChangedVersionAttributesMask mask;
888 ServiceWorkerRegistrationInfo info;
891 struct StateChangeLogEntry {
892 int64 version_id;
893 ServiceWorkerVersion::Status status;
896 UpdateJobTestHelper(int mock_render_process_id)
897 : EmbeddedWorkerTestHelper(mock_render_process_id) {}
898 virtual ~UpdateJobTestHelper() {
899 if (registration_.get())
900 registration_->RemoveListener(this);
903 ServiceWorkerStorage* storage() { return context()->storage(); }
904 ServiceWorkerJobCoordinator* job_coordinator() {
905 return context()->job_coordinator();
908 scoped_refptr<ServiceWorkerRegistration> SetupInitialRegistration(
909 const GURL& test_origin) {
910 scoped_refptr<ServiceWorkerRegistration> registration;
911 bool called = false;
912 job_coordinator()->Register(
913 test_origin.Resolve(kScope),
914 test_origin.Resolve(kScript),
915 mock_render_process_id(),
916 SaveRegistration(SERVICE_WORKER_OK, &called, &registration));
917 base::RunLoop().RunUntilIdle();
918 EXPECT_TRUE(called);
919 EXPECT_TRUE(registration.get());
920 EXPECT_TRUE(registration->active_version());
921 EXPECT_FALSE(registration->installing_version());
922 EXPECT_FALSE(registration->waiting_version());
923 registration_ = registration;
924 return registration;
927 // EmbeddedWorkerTestHelper overrides
928 virtual void OnStartWorker(int embedded_worker_id,
929 int64 version_id,
930 const GURL& scope,
931 const GURL& script,
932 bool pause_after_download) OVERRIDE {
933 const std::string kMockScriptBody = "mock_script";
934 ServiceWorkerVersion* version = context()->GetLiveVersion(version_id);
935 ASSERT_TRUE(version);
936 version->AddListener(this);
938 if (!pause_after_download) {
939 // Spoof caching the script for the initial version.
940 int64 resource_id = storage()->NewResourceId();
941 version->script_cache_map()->NotifyStartedCaching(script, resource_id);
942 WriteStringResponse(storage(), resource_id, kMockScriptBody);
943 version->script_cache_map()->NotifyFinishedCaching(script, true);
944 } else {
945 // Spoof caching the script for the new version.
946 int64 resource_id = storage()->NewResourceId();
947 version->script_cache_map()->NotifyStartedCaching(script, resource_id);
948 if (script.GetOrigin() == kNoChangeOrigin)
949 WriteStringResponse(storage(), resource_id, kMockScriptBody);
950 else
951 WriteStringResponse(storage(), resource_id, "mock_different_script");
952 version->script_cache_map()->NotifyFinishedCaching(script, true);
954 EmbeddedWorkerTestHelper::OnStartWorker(
955 embedded_worker_id, version_id, scope, script, pause_after_download);
958 // ServiceWorkerRegistration::Listener overrides
959 virtual void OnVersionAttributesChanged(
960 ServiceWorkerRegistration* registration,
961 ChangedVersionAttributesMask changed_mask,
962 const ServiceWorkerRegistrationInfo& info) OVERRIDE {
963 AttributeChangeLogEntry entry;
964 entry.registration_id = registration->id();
965 entry.mask = changed_mask;
966 entry.info = info;
967 attribute_change_log_.push_back(entry);
970 virtual void OnRegistrationFailed(
971 ServiceWorkerRegistration* registration) OVERRIDE {
972 NOTREACHED();
975 // ServiceWorkerVersion::Listener overrides
976 virtual void OnVersionStateChanged(ServiceWorkerVersion* version) OVERRIDE {
977 StateChangeLogEntry entry;
978 entry.version_id = version->version_id();
979 entry.status = version->status();
980 state_change_log_.push_back(entry);
983 scoped_refptr<ServiceWorkerRegistration> registration_;
985 std::vector<AttributeChangeLogEntry> attribute_change_log_;
986 std::vector<StateChangeLogEntry> state_change_log_;
989 } // namespace
991 TEST_F(ServiceWorkerJobTest, Update_NoChange) {
992 UpdateJobTestHelper* update_helper =
993 new UpdateJobTestHelper(render_process_id_);
994 helper_.reset(update_helper);
995 scoped_refptr<ServiceWorkerRegistration> registration =
996 update_helper->SetupInitialRegistration(kNoChangeOrigin);
997 ASSERT_TRUE(registration.get());
998 ASSERT_EQ(4u, update_helper->state_change_log_.size());
999 EXPECT_EQ(ServiceWorkerVersion::INSTALLING,
1000 update_helper->state_change_log_[0].status);
1001 EXPECT_EQ(ServiceWorkerVersion::INSTALLED,
1002 update_helper->state_change_log_[1].status);
1003 EXPECT_EQ(ServiceWorkerVersion::ACTIVATING,
1004 update_helper->state_change_log_[2].status);
1005 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED,
1006 update_helper->state_change_log_[3].status);
1007 update_helper->state_change_log_.clear();
1009 // Run the update job.
1010 registration->AddListener(update_helper);
1011 scoped_refptr<ServiceWorkerVersion> first_version =
1012 registration->active_version();
1013 first_version->StartUpdate();
1014 base::RunLoop().RunUntilIdle();
1016 // Verify results.
1017 ASSERT_TRUE(registration->active_version());
1018 EXPECT_EQ(first_version.get(), registration->active_version());
1019 EXPECT_FALSE(registration->installing_version());
1020 EXPECT_FALSE(registration->waiting_version());
1021 EXPECT_TRUE(update_helper->attribute_change_log_.empty());
1022 ASSERT_EQ(1u, update_helper->state_change_log_.size());
1023 EXPECT_NE(registration->active_version()->version_id(),
1024 update_helper->state_change_log_[0].version_id);
1025 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT,
1026 update_helper->state_change_log_[0].status);
1029 TEST_F(ServiceWorkerJobTest, Update_NewVersion) {
1030 UpdateJobTestHelper* update_helper =
1031 new UpdateJobTestHelper(render_process_id_);
1032 helper_.reset(update_helper);
1033 scoped_refptr<ServiceWorkerRegistration> registration =
1034 update_helper->SetupInitialRegistration(kNewVersionOrigin);
1035 ASSERT_TRUE(registration.get());
1036 update_helper->state_change_log_.clear();
1038 // Run the update job.
1039 registration->AddListener(update_helper);
1040 scoped_refptr<ServiceWorkerVersion> first_version =
1041 registration->active_version();
1042 first_version->StartUpdate();
1043 base::RunLoop().RunUntilIdle();
1045 // Verify results.
1046 ASSERT_TRUE(registration->active_version());
1047 EXPECT_NE(first_version.get(), registration->active_version());
1048 EXPECT_FALSE(registration->installing_version());
1049 EXPECT_FALSE(registration->waiting_version());
1050 ASSERT_EQ(3u, update_helper->attribute_change_log_.size());
1052 UpdateJobTestHelper::AttributeChangeLogEntry entry;
1053 entry = update_helper->attribute_change_log_[0];
1054 EXPECT_TRUE(entry.mask.installing_changed());
1055 EXPECT_FALSE(entry.mask.waiting_changed());
1056 EXPECT_FALSE(entry.mask.active_changed());
1057 EXPECT_FALSE(entry.info.installing_version.is_null);
1058 EXPECT_TRUE(entry.info.waiting_version.is_null);
1059 EXPECT_FALSE(entry.info.active_version.is_null);
1061 entry = update_helper->attribute_change_log_[1];
1062 EXPECT_TRUE(entry.mask.installing_changed());
1063 EXPECT_TRUE(entry.mask.waiting_changed());
1064 EXPECT_FALSE(entry.mask.active_changed());
1065 EXPECT_TRUE(entry.info.installing_version.is_null);
1066 EXPECT_FALSE(entry.info.waiting_version.is_null);
1067 EXPECT_FALSE(entry.info.active_version.is_null);
1069 entry = update_helper->attribute_change_log_[2];
1070 EXPECT_FALSE(entry.mask.installing_changed());
1071 EXPECT_TRUE(entry.mask.waiting_changed());
1072 EXPECT_TRUE(entry.mask.active_changed());
1073 EXPECT_TRUE(entry.info.installing_version.is_null);
1074 EXPECT_TRUE(entry.info.waiting_version.is_null);
1075 EXPECT_FALSE(entry.info.active_version.is_null);
1077 // expected version state transitions:
1078 // new.installing, new.installed,
1079 // old.redundant,
1080 // new.activating, new.activated
1081 ASSERT_EQ(5u, update_helper->state_change_log_.size());
1083 EXPECT_EQ(registration->active_version()->version_id(),
1084 update_helper->state_change_log_[0].version_id);
1085 EXPECT_EQ(ServiceWorkerVersion::INSTALLING,
1086 update_helper->state_change_log_[0].status);
1088 EXPECT_EQ(registration->active_version()->version_id(),
1089 update_helper->state_change_log_[1].version_id);
1090 EXPECT_EQ(ServiceWorkerVersion::INSTALLED,
1091 update_helper->state_change_log_[1].status);
1093 EXPECT_EQ(first_version->version_id(),
1094 update_helper->state_change_log_[2].version_id);
1095 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT,
1096 update_helper->state_change_log_[2].status);
1098 EXPECT_EQ(registration->active_version()->version_id(),
1099 update_helper->state_change_log_[3].version_id);
1100 EXPECT_EQ(ServiceWorkerVersion::ACTIVATING,
1101 update_helper->state_change_log_[3].status);
1103 EXPECT_EQ(registration->active_version()->version_id(),
1104 update_helper->state_change_log_[4].version_id);
1105 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED,
1106 update_helper->state_change_log_[4].status);
1109 TEST_F(ServiceWorkerJobTest, Update_NewestVersionChanged) {
1110 bool called;
1111 scoped_refptr<ServiceWorkerRegistration> registration;
1112 job_coordinator()->Register(
1113 GURL("http://www.example.com/one/"),
1114 GURL("http://www.example.com/service_worker.js"),
1115 render_process_id_,
1116 SaveRegistration(SERVICE_WORKER_OK, &called, &registration));
1118 EXPECT_FALSE(called);
1119 base::RunLoop().RunUntilIdle();
1120 EXPECT_TRUE(called);
1121 ServiceWorkerVersion* active_version = registration->active_version();
1123 // Queue an Update, it should abort when it starts and sees the new version.
1124 job_coordinator()->Update(registration.get());
1126 // Add a waiting version with new script.
1127 scoped_refptr<ServiceWorkerVersion> version =
1128 new ServiceWorkerVersion(registration.get(),
1129 GURL("http://www.example.com/new_worker.js"),
1130 2L /* dummy version id */,
1131 helper_->context()->AsWeakPtr());
1132 registration->SetWaitingVersion(version.get());
1134 base::RunLoop().RunUntilIdle();
1136 // Verify the registration was not modified by the Update.
1137 EXPECT_EQ(active_version, registration->active_version());
1138 EXPECT_EQ(version.get(), registration->waiting_version());
1139 EXPECT_EQ(NULL, registration->installing_version());
1142 TEST_F(ServiceWorkerJobTest, Update_UninstallingRegistration) {
1143 bool called;
1144 scoped_refptr<ServiceWorkerRegistration> registration;
1145 job_coordinator()->Register(
1146 GURL("http://www.example.com/one/"),
1147 GURL("http://www.example.com/service_worker.js"),
1148 render_process_id_,
1149 SaveRegistration(SERVICE_WORKER_OK, &called, &registration));
1151 EXPECT_FALSE(called);
1152 base::RunLoop().RunUntilIdle();
1153 EXPECT_TRUE(called);
1155 // Add a controllee and queue an unregister to force the uninstalling state.
1156 scoped_ptr<ServiceWorkerProviderHost> host(
1157 new ServiceWorkerProviderHost(33 /* dummy render_process id */,
1158 1 /* dummy provider_id */,
1159 helper_->context()->AsWeakPtr(),
1160 NULL));
1161 ServiceWorkerVersion* active_version = registration->active_version();
1162 active_version->AddControllee(host.get());
1163 job_coordinator()->Unregister(GURL("http://www.example.com/one/"),
1164 SaveUnregistration(SERVICE_WORKER_OK, &called));
1166 // Update should abort after it starts and sees uninstalling.
1167 job_coordinator()->Update(registration.get());
1169 EXPECT_FALSE(called);
1170 base::RunLoop().RunUntilIdle();
1171 EXPECT_TRUE(called);
1173 // Verify the registration was not modified by the Update.
1174 EXPECT_TRUE(registration->is_uninstalling());
1175 EXPECT_EQ(active_version, registration->active_version());
1176 EXPECT_EQ(NULL, registration->waiting_version());
1177 EXPECT_EQ(NULL, registration->installing_version());
1180 } // namespace content