Blink roll 25b6bd3a7a131ffe68d809546ad1a20707915cdc:3a503f41ae42e5b79cfcd2ff10e65afde...
[chromium-blink-merge.git] / content / browser / service_worker / service_worker_storage_unittest.cc
blobe98b83dbc6cba51609499d239bf9d8c79f19e2b2
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
3 // found in the LICENSE file.
5 #include <string>
7 #include "base/files/scoped_temp_dir.h"
8 #include "base/logging.h"
9 #include "base/run_loop.h"
10 #include "base/thread_task_runner_handle.h"
11 #include "content/browser/browser_thread_impl.h"
12 #include "content/browser/service_worker/service_worker_context_core.h"
13 #include "content/browser/service_worker/service_worker_disk_cache.h"
14 #include "content/browser/service_worker/service_worker_registration.h"
15 #include "content/browser/service_worker/service_worker_storage.h"
16 #include "content/browser/service_worker/service_worker_utils.h"
17 #include "content/browser/service_worker/service_worker_version.h"
18 #include "content/common/service_worker/service_worker_status_code.h"
19 #include "content/public/test/test_browser_thread_bundle.h"
20 #include "net/base/io_buffer.h"
21 #include "net/base/net_errors.h"
22 #include "net/base/test_completion_callback.h"
23 #include "net/http/http_response_headers.h"
24 #include "testing/gtest/include/gtest/gtest.h"
26 using net::IOBuffer;
27 using net::TestCompletionCallback;
28 using net::WrappedIOBuffer;
30 namespace content {
32 namespace {
34 typedef ServiceWorkerDatabase::RegistrationData RegistrationData;
35 typedef ServiceWorkerDatabase::ResourceRecord ResourceRecord;
37 void StatusCallback(bool* was_called,
38 ServiceWorkerStatusCode* result,
39 ServiceWorkerStatusCode status) {
40 *was_called = true;
41 *result = status;
44 ServiceWorkerStorage::StatusCallback MakeStatusCallback(
45 bool* was_called,
46 ServiceWorkerStatusCode* result) {
47 return base::Bind(&StatusCallback, was_called, result);
50 void FindCallback(
51 bool* was_called,
52 ServiceWorkerStatusCode* result,
53 scoped_refptr<ServiceWorkerRegistration>* found,
54 ServiceWorkerStatusCode status,
55 const scoped_refptr<ServiceWorkerRegistration>& registration) {
56 *was_called = true;
57 *result = status;
58 *found = registration;
61 ServiceWorkerStorage::FindRegistrationCallback MakeFindCallback(
62 bool* was_called,
63 ServiceWorkerStatusCode* result,
64 scoped_refptr<ServiceWorkerRegistration>* found) {
65 return base::Bind(&FindCallback, was_called, result, found);
68 void GetAllCallback(
69 bool* was_called,
70 std::vector<ServiceWorkerRegistrationInfo>* all_out,
71 const std::vector<ServiceWorkerRegistrationInfo>& all) {
72 *was_called = true;
73 *all_out = all;
76 ServiceWorkerStorage::GetAllRegistrationInfosCallback MakeGetAllCallback(
77 bool* was_called,
78 std::vector<ServiceWorkerRegistrationInfo>* all) {
79 return base::Bind(&GetAllCallback, was_called, all);
82 void OnCompareComplete(
83 ServiceWorkerStatusCode* status_out, bool* are_equal_out,
84 ServiceWorkerStatusCode status, bool are_equal) {
85 *status_out = status;
86 *are_equal_out = are_equal;
89 void WriteResponse(
90 ServiceWorkerStorage* storage, int64 id,
91 const std::string& headers,
92 IOBuffer* body, int length) {
93 scoped_ptr<ServiceWorkerResponseWriter> writer =
94 storage->CreateResponseWriter(id);
96 scoped_ptr<net::HttpResponseInfo> info(new net::HttpResponseInfo);
97 info->request_time = base::Time::Now();
98 info->response_time = base::Time::Now();
99 info->was_cached = false;
100 info->headers = new net::HttpResponseHeaders(headers);
101 scoped_refptr<HttpResponseInfoIOBuffer> info_buffer =
102 new HttpResponseInfoIOBuffer(info.release());
104 TestCompletionCallback cb;
105 writer->WriteInfo(info_buffer.get(), cb.callback());
106 int rv = cb.WaitForResult();
107 EXPECT_LT(0, rv);
110 TestCompletionCallback cb;
111 writer->WriteData(body, length, cb.callback());
112 int rv = cb.WaitForResult();
113 EXPECT_EQ(length, rv);
117 void WriteStringResponse(
118 ServiceWorkerStorage* storage, int64 id,
119 const std::string& headers,
120 const std::string& body) {
121 scoped_refptr<IOBuffer> body_buffer(new WrappedIOBuffer(body.data()));
122 WriteResponse(storage, id, headers, body_buffer.get(), body.length());
125 void WriteBasicResponse(ServiceWorkerStorage* storage, int64 id) {
126 scoped_ptr<ServiceWorkerResponseWriter> writer =
127 storage->CreateResponseWriter(id);
129 const char kHttpHeaders[] = "HTTP/1.0 200 HONKYDORY\0Content-Length: 5\0\0";
130 const char kHttpBody[] = "Hello";
131 std::string headers(kHttpHeaders, arraysize(kHttpHeaders));
132 WriteStringResponse(storage, id, headers, std::string(kHttpBody));
135 bool VerifyBasicResponse(ServiceWorkerStorage* storage, int64 id,
136 bool expected_positive_result) {
137 const std::string kExpectedHttpBody("Hello");
138 scoped_ptr<ServiceWorkerResponseReader> reader =
139 storage->CreateResponseReader(id);
140 scoped_refptr<HttpResponseInfoIOBuffer> info_buffer =
141 new HttpResponseInfoIOBuffer();
143 TestCompletionCallback cb;
144 reader->ReadInfo(info_buffer.get(), cb.callback());
145 int rv = cb.WaitForResult();
146 if (expected_positive_result)
147 EXPECT_LT(0, rv);
148 if (rv <= 0)
149 return false;
152 std::string received_body;
154 const int kBigEnough = 512;
155 scoped_refptr<net::IOBuffer> buffer = new IOBuffer(kBigEnough);
156 TestCompletionCallback cb;
157 reader->ReadData(buffer.get(), kBigEnough, cb.callback());
158 int rv = cb.WaitForResult();
159 EXPECT_EQ(static_cast<int>(kExpectedHttpBody.size()), rv);
160 if (rv <= 0)
161 return false;
162 received_body.assign(buffer->data(), rv);
165 bool status_match =
166 std::string("HONKYDORY") ==
167 info_buffer->http_info->headers->GetStatusText();
168 bool data_match = kExpectedHttpBody == received_body;
170 EXPECT_TRUE(status_match);
171 EXPECT_TRUE(data_match);
172 return status_match && data_match;
175 void WriteResponseOfSize(ServiceWorkerStorage* storage, int64 id,
176 char val, int size) {
177 const char kHttpHeaders[] = "HTTP/1.0 200 HONKYDORY\00";
178 std::string headers(kHttpHeaders, arraysize(kHttpHeaders));
179 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(size);
180 memset(buffer->data(), val, size);
181 WriteResponse(storage, id, headers, buffer.get(), size);
184 } // namespace
186 class ServiceWorkerStorageTest : public testing::Test {
187 public:
188 ServiceWorkerStorageTest()
189 : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {
192 void SetUp() override {
193 scoped_ptr<ServiceWorkerDatabaseTaskManager> database_task_manager(
194 new MockServiceWorkerDatabaseTaskManager(
195 base::ThreadTaskRunnerHandle::Get()));
196 context_.reset(
197 new ServiceWorkerContextCore(GetUserDataDirectory(),
198 base::ThreadTaskRunnerHandle::Get(),
199 database_task_manager.Pass(),
200 base::ThreadTaskRunnerHandle::Get(),
201 NULL,
202 NULL,
203 NULL,
204 NULL));
205 context_ptr_ = context_->AsWeakPtr();
208 void TearDown() override { context_.reset(); }
210 virtual base::FilePath GetUserDataDirectory() { return base::FilePath(); }
212 ServiceWorkerStorage* storage() { return context_->storage(); }
214 // A static class method for friendliness.
215 static void VerifyPurgeableListStatusCallback(
216 ServiceWorkerDatabase* database,
217 std::set<int64> *purgeable_ids,
218 bool* was_called,
219 ServiceWorkerStatusCode* result,
220 ServiceWorkerStatusCode status) {
221 *was_called = true;
222 *result = status;
223 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
224 database->GetPurgeableResourceIds(purgeable_ids));
227 protected:
228 ServiceWorkerStatusCode StoreRegistration(
229 scoped_refptr<ServiceWorkerRegistration> registration,
230 scoped_refptr<ServiceWorkerVersion> version) {
231 bool was_called = false;
232 ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
233 storage()->StoreRegistration(registration.get(),
234 version.get(),
235 MakeStatusCallback(&was_called, &result));
236 EXPECT_FALSE(was_called); // always async
237 base::RunLoop().RunUntilIdle();
238 EXPECT_TRUE(was_called);
239 return result;
242 ServiceWorkerStatusCode DeleteRegistration(
243 int64 registration_id,
244 const GURL& origin) {
245 bool was_called = false;
246 ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
247 storage()->DeleteRegistration(
248 registration_id, origin, MakeStatusCallback(&was_called, &result));
249 EXPECT_FALSE(was_called); // always async
250 base::RunLoop().RunUntilIdle();
251 EXPECT_TRUE(was_called);
252 return result;
255 void GetAllRegistrations(
256 std::vector<ServiceWorkerRegistrationInfo>* registrations) {
257 bool was_called = false;
258 storage()->GetAllRegistrations(
259 MakeGetAllCallback(&was_called, registrations));
260 EXPECT_FALSE(was_called); // always async
261 base::RunLoop().RunUntilIdle();
262 EXPECT_TRUE(was_called);
265 ServiceWorkerStatusCode UpdateToActiveState(
266 scoped_refptr<ServiceWorkerRegistration> registration) {
267 bool was_called = false;
268 ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
269 storage()->UpdateToActiveState(registration.get(),
270 MakeStatusCallback(&was_called, &result));
271 EXPECT_FALSE(was_called); // always async
272 base::RunLoop().RunUntilIdle();
273 EXPECT_TRUE(was_called);
274 return result;
277 void UpdateLastUpdateCheckTime(ServiceWorkerRegistration* registration) {
278 storage()->UpdateLastUpdateCheckTime(registration);
279 base::RunLoop().RunUntilIdle();
282 ServiceWorkerStatusCode FindRegistrationForDocument(
283 const GURL& document_url,
284 scoped_refptr<ServiceWorkerRegistration>* registration) {
285 bool was_called = false;
286 ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
287 storage()->FindRegistrationForDocument(
288 document_url, MakeFindCallback(&was_called, &result, registration));
289 base::RunLoop().RunUntilIdle();
290 EXPECT_TRUE(was_called);
291 return result;
294 ServiceWorkerStatusCode FindRegistrationForPattern(
295 const GURL& scope,
296 scoped_refptr<ServiceWorkerRegistration>* registration) {
297 bool was_called = false;
298 ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
299 storage()->FindRegistrationForPattern(
300 scope, MakeFindCallback(&was_called, &result, registration));
301 EXPECT_FALSE(was_called); // always async
302 base::RunLoop().RunUntilIdle();
303 EXPECT_TRUE(was_called);
304 return result;
307 ServiceWorkerStatusCode FindRegistrationForId(
308 int64 registration_id,
309 const GURL& origin,
310 scoped_refptr<ServiceWorkerRegistration>* registration) {
311 bool was_called = false;
312 ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
313 storage()->FindRegistrationForId(
314 registration_id, origin,
315 MakeFindCallback(&was_called, &result, registration));
316 base::RunLoop().RunUntilIdle();
317 EXPECT_TRUE(was_called);
318 return result;
321 scoped_ptr<ServiceWorkerContextCore> context_;
322 base::WeakPtr<ServiceWorkerContextCore> context_ptr_;
323 TestBrowserThreadBundle browser_thread_bundle_;
326 TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) {
327 const GURL kScope("http://www.test.not/scope/");
328 const GURL kScript("http://www.test.not/script.js");
329 const GURL kDocumentUrl("http://www.test.not/scope/document.html");
330 const GURL kResource1("http://www.test.not/scope/resource1.js");
331 const int64 kResource1Size = 1591234;
332 const GURL kResource2("http://www.test.not/scope/resource2.js");
333 const int64 kResource2Size = 51;
334 const int64 kRegistrationId = 0;
335 const int64 kVersionId = 0;
336 const base::Time kToday = base::Time::Now();
337 const base::Time kYesterday = kToday - base::TimeDelta::FromDays(1);
339 scoped_refptr<ServiceWorkerRegistration> found_registration;
341 // We shouldn't find anything without having stored anything.
342 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
343 FindRegistrationForDocument(kDocumentUrl, &found_registration));
344 EXPECT_FALSE(found_registration.get());
346 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
347 FindRegistrationForPattern(kScope, &found_registration));
348 EXPECT_FALSE(found_registration.get());
350 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
351 FindRegistrationForId(
352 kRegistrationId, kScope.GetOrigin(), &found_registration));
353 EXPECT_FALSE(found_registration.get());
355 std::vector<ServiceWorkerDatabase::ResourceRecord> resources;
356 resources.push_back(
357 ServiceWorkerDatabase::ResourceRecord(1, kResource1, kResource1Size));
358 resources.push_back(
359 ServiceWorkerDatabase::ResourceRecord(2, kResource2, kResource2Size));
361 // Store something.
362 scoped_refptr<ServiceWorkerRegistration> live_registration =
363 new ServiceWorkerRegistration(
364 kScope, kRegistrationId, context_ptr_);
365 scoped_refptr<ServiceWorkerVersion> live_version =
366 new ServiceWorkerVersion(
367 live_registration.get(), kScript, kVersionId, context_ptr_);
368 live_version->SetStatus(ServiceWorkerVersion::INSTALLED);
369 live_version->script_cache_map()->SetResources(resources);
370 live_registration->SetWaitingVersion(live_version.get());
371 live_registration->set_last_update_check(kYesterday);
372 EXPECT_EQ(SERVICE_WORKER_OK,
373 StoreRegistration(live_registration, live_version));
375 // Now we should find it and get the live ptr back immediately.
376 EXPECT_EQ(SERVICE_WORKER_OK,
377 FindRegistrationForDocument(kDocumentUrl, &found_registration));
378 EXPECT_EQ(live_registration, found_registration);
379 EXPECT_EQ(kResource1Size + kResource2Size,
380 live_registration->resources_total_size_bytes());
381 EXPECT_EQ(kResource1Size + kResource2Size,
382 found_registration->resources_total_size_bytes());
383 found_registration = NULL;
385 // But FindRegistrationForPattern is always async.
386 EXPECT_EQ(SERVICE_WORKER_OK,
387 FindRegistrationForPattern(kScope, &found_registration));
388 EXPECT_EQ(live_registration, found_registration);
389 found_registration = NULL;
391 // Can be found by id too.
392 EXPECT_EQ(SERVICE_WORKER_OK,
393 FindRegistrationForId(
394 kRegistrationId, kScope.GetOrigin(), &found_registration));
395 ASSERT_TRUE(found_registration.get());
396 EXPECT_EQ(kRegistrationId, found_registration->id());
397 EXPECT_EQ(live_registration, found_registration);
398 found_registration = NULL;
400 // Drop the live registration, but keep the version live.
401 live_registration = NULL;
403 // Now FindRegistrationForDocument should be async.
404 EXPECT_EQ(SERVICE_WORKER_OK,
405 FindRegistrationForDocument(kDocumentUrl, &found_registration));
406 ASSERT_TRUE(found_registration.get());
407 EXPECT_EQ(kRegistrationId, found_registration->id());
408 EXPECT_TRUE(found_registration->HasOneRef());
410 // Check that sizes are populated correctly
411 EXPECT_EQ(live_version.get(), found_registration->waiting_version());
412 EXPECT_EQ(kResource1Size + kResource2Size,
413 found_registration->resources_total_size_bytes());
414 std::vector<ServiceWorkerRegistrationInfo> all_registrations;
415 GetAllRegistrations(&all_registrations);
416 EXPECT_EQ(1u, all_registrations.size());
417 ServiceWorkerRegistrationInfo info = all_registrations[0];
418 EXPECT_EQ(kResource1Size + kResource2Size, info.stored_version_size_bytes);
419 all_registrations.clear();
421 found_registration = NULL;
423 // Drop the live version too.
424 live_version = NULL;
426 // And FindRegistrationForPattern is always async.
427 EXPECT_EQ(SERVICE_WORKER_OK,
428 FindRegistrationForPattern(kScope, &found_registration));
429 ASSERT_TRUE(found_registration.get());
430 EXPECT_EQ(kRegistrationId, found_registration->id());
431 EXPECT_TRUE(found_registration->HasOneRef());
432 EXPECT_FALSE(found_registration->active_version());
433 ASSERT_TRUE(found_registration->waiting_version());
434 EXPECT_EQ(kYesterday, found_registration->last_update_check());
435 EXPECT_EQ(ServiceWorkerVersion::INSTALLED,
436 found_registration->waiting_version()->status());
438 // Update to active and update the last check time.
439 scoped_refptr<ServiceWorkerVersion> temp_version =
440 found_registration->waiting_version();
441 temp_version->SetStatus(ServiceWorkerVersion::ACTIVATED);
442 found_registration->SetActiveVersion(temp_version.get());
443 temp_version = NULL;
444 EXPECT_EQ(SERVICE_WORKER_OK, UpdateToActiveState(found_registration));
445 found_registration->set_last_update_check(kToday);
446 UpdateLastUpdateCheckTime(found_registration.get());
448 found_registration = NULL;
450 // Trying to update a unstored registration to active should fail.
451 scoped_refptr<ServiceWorkerRegistration> unstored_registration =
452 new ServiceWorkerRegistration(
453 kScope, kRegistrationId + 1, context_ptr_);
454 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
455 UpdateToActiveState(unstored_registration));
456 unstored_registration = NULL;
458 // The Find methods should return a registration with an active version
459 // and the expected update time.
460 EXPECT_EQ(SERVICE_WORKER_OK,
461 FindRegistrationForDocument(kDocumentUrl, &found_registration));
462 ASSERT_TRUE(found_registration.get());
463 EXPECT_EQ(kRegistrationId, found_registration->id());
464 EXPECT_TRUE(found_registration->HasOneRef());
465 EXPECT_FALSE(found_registration->waiting_version());
466 ASSERT_TRUE(found_registration->active_version());
467 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED,
468 found_registration->active_version()->status());
469 EXPECT_EQ(kToday, found_registration->last_update_check());
471 // Delete from storage but with a instance still live.
472 EXPECT_TRUE(context_->GetLiveVersion(kRegistrationId));
473 EXPECT_EQ(SERVICE_WORKER_OK,
474 DeleteRegistration(kRegistrationId, kScope.GetOrigin()));
475 EXPECT_TRUE(context_->GetLiveVersion(kRegistrationId));
477 // Should no longer be found.
478 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
479 FindRegistrationForId(
480 kRegistrationId, kScope.GetOrigin(), &found_registration));
481 EXPECT_FALSE(found_registration.get());
483 // Deleting an unstored registration should succeed.
484 EXPECT_EQ(SERVICE_WORKER_OK,
485 DeleteRegistration(kRegistrationId + 1, kScope.GetOrigin()));
488 TEST_F(ServiceWorkerStorageTest, InstallingRegistrationsAreFindable) {
489 const GURL kScope("http://www.test.not/scope/");
490 const GURL kScript("http://www.test.not/script.js");
491 const GURL kDocumentUrl("http://www.test.not/scope/document.html");
492 const int64 kRegistrationId = 0;
493 const int64 kVersionId = 0;
495 scoped_refptr<ServiceWorkerRegistration> found_registration;
497 // Create an unstored registration.
498 scoped_refptr<ServiceWorkerRegistration> live_registration =
499 new ServiceWorkerRegistration(
500 kScope, kRegistrationId, context_ptr_);
501 scoped_refptr<ServiceWorkerVersion> live_version =
502 new ServiceWorkerVersion(
503 live_registration.get(), kScript, kVersionId, context_ptr_);
504 live_version->SetStatus(ServiceWorkerVersion::INSTALLING);
505 live_registration->SetWaitingVersion(live_version.get());
507 // Should not be findable, including by GetAllRegistrations.
508 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
509 FindRegistrationForId(
510 kRegistrationId, kScope.GetOrigin(), &found_registration));
511 EXPECT_FALSE(found_registration.get());
513 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
514 FindRegistrationForDocument(kDocumentUrl, &found_registration));
515 EXPECT_FALSE(found_registration.get());
517 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
518 FindRegistrationForPattern(kScope, &found_registration));
519 EXPECT_FALSE(found_registration.get());
521 std::vector<ServiceWorkerRegistrationInfo> all_registrations;
522 GetAllRegistrations(&all_registrations);
523 EXPECT_TRUE(all_registrations.empty());
525 // Notify storage of it being installed.
526 storage()->NotifyInstallingRegistration(live_registration.get());
528 // Now should be findable.
529 EXPECT_EQ(SERVICE_WORKER_OK,
530 FindRegistrationForId(
531 kRegistrationId, kScope.GetOrigin(), &found_registration));
532 EXPECT_EQ(live_registration, found_registration);
533 found_registration = NULL;
535 EXPECT_EQ(SERVICE_WORKER_OK,
536 FindRegistrationForDocument(kDocumentUrl, &found_registration));
537 EXPECT_EQ(live_registration, found_registration);
538 found_registration = NULL;
540 EXPECT_EQ(SERVICE_WORKER_OK,
541 FindRegistrationForPattern(kScope, &found_registration));
542 EXPECT_EQ(live_registration, found_registration);
543 found_registration = NULL;
545 GetAllRegistrations(&all_registrations);
546 EXPECT_EQ(1u, all_registrations.size());
547 all_registrations.clear();
549 // Notify storage of installation no longer happening.
550 storage()->NotifyDoneInstallingRegistration(
551 live_registration.get(), NULL, SERVICE_WORKER_OK);
553 // Once again, should not be findable.
554 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
555 FindRegistrationForId(
556 kRegistrationId, kScope.GetOrigin(), &found_registration));
557 EXPECT_FALSE(found_registration.get());
559 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
560 FindRegistrationForDocument(kDocumentUrl, &found_registration));
561 EXPECT_FALSE(found_registration.get());
563 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
564 FindRegistrationForPattern(kScope, &found_registration));
565 EXPECT_FALSE(found_registration.get());
567 GetAllRegistrations(&all_registrations);
568 EXPECT_TRUE(all_registrations.empty());
571 class ServiceWorkerResourceStorageTest : public ServiceWorkerStorageTest {
572 public:
573 void SetUp() override {
574 ServiceWorkerStorageTest::SetUp();
576 storage()->LazyInitialize(base::Bind(&base::DoNothing));
577 base::RunLoop().RunUntilIdle();
578 scope_ = GURL("http://www.test.not/scope/");
579 script_ = GURL("http://www.test.not/script.js");
580 import_ = GURL("http://www.test.not/import.js");
581 document_url_ = GURL("http://www.test.not/scope/document.html");
582 registration_id_ = storage()->NewRegistrationId();
583 version_id_ = storage()->NewVersionId();
584 resource_id1_ = storage()->NewResourceId();
585 resource_id2_ = storage()->NewResourceId();
586 resource_id1_size_ = 239193;
587 resource_id2_size_ = 59923;
589 // Cons up a new registration+version with two script resources.
590 RegistrationData data;
591 data.registration_id = registration_id_;
592 data.scope = scope_;
593 data.script = script_;
594 data.version_id = version_id_;
595 data.is_active = false;
596 std::vector<ResourceRecord> resources;
597 resources.push_back(
598 ResourceRecord(resource_id1_, script_, resource_id1_size_));
599 resources.push_back(
600 ResourceRecord(resource_id2_, import_, resource_id2_size_));
601 registration_ = storage()->GetOrCreateRegistration(data, resources);
602 registration_->waiting_version()->SetStatus(ServiceWorkerVersion::NEW);
604 // Add the resources ids to the uncommitted list.
605 storage()->StoreUncommittedResponseId(resource_id1_);
606 storage()->StoreUncommittedResponseId(resource_id2_);
607 base::RunLoop().RunUntilIdle();
608 std::set<int64> verify_ids;
609 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
610 storage()->database_->GetUncommittedResourceIds(&verify_ids));
611 EXPECT_EQ(2u, verify_ids.size());
613 // And dump something in the disk cache for them.
614 WriteBasicResponse(storage(), resource_id1_);
615 WriteBasicResponse(storage(), resource_id2_);
616 EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, true));
617 EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id2_, true));
619 // Storing the registration/version should take the resources ids out
620 // of the uncommitted list.
621 EXPECT_EQ(
622 SERVICE_WORKER_OK,
623 StoreRegistration(registration_, registration_->waiting_version()));
624 verify_ids.clear();
625 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
626 storage()->database_->GetUncommittedResourceIds(&verify_ids));
627 EXPECT_TRUE(verify_ids.empty());
630 protected:
631 GURL scope_;
632 GURL script_;
633 GURL import_;
634 GURL document_url_;
635 int64 registration_id_;
636 int64 version_id_;
637 int64 resource_id1_;
638 uint64 resource_id1_size_;
639 int64 resource_id2_;
640 uint64 resource_id2_size_;
641 scoped_refptr<ServiceWorkerRegistration> registration_;
644 class ServiceWorkerResourceStorageDiskTest
645 : public ServiceWorkerResourceStorageTest {
646 public:
647 void SetUp() override {
648 ASSERT_TRUE(user_data_directory_.CreateUniqueTempDir());
649 ServiceWorkerResourceStorageTest::SetUp();
652 base::FilePath GetUserDataDirectory() override {
653 return user_data_directory_.path();
656 protected:
657 base::ScopedTempDir user_data_directory_;
660 TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_NoLiveVersion) {
661 bool was_called = false;
662 ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
663 std::set<int64> verify_ids;
665 registration_->SetWaitingVersion(NULL);
666 registration_ = NULL;
668 // Deleting the registration should result in the resources being added to the
669 // purgeable list and then doomed in the disk cache and removed from that
670 // list.
671 storage()->DeleteRegistration(
672 registration_id_,
673 scope_.GetOrigin(),
674 base::Bind(&VerifyPurgeableListStatusCallback,
675 base::Unretained(storage()->database_.get()),
676 &verify_ids,
677 &was_called,
678 &result));
679 base::RunLoop().RunUntilIdle();
680 ASSERT_TRUE(was_called);
681 EXPECT_EQ(SERVICE_WORKER_OK, result);
682 EXPECT_EQ(2u, verify_ids.size());
683 verify_ids.clear();
684 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
685 storage()->database_->GetPurgeableResourceIds(&verify_ids));
686 EXPECT_TRUE(verify_ids.empty());
688 EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id1_, false));
689 EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id2_, false));
692 TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_WaitingVersion) {
693 bool was_called = false;
694 ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
695 std::set<int64> verify_ids;
697 // Deleting the registration should result in the resources being added to the
698 // purgeable list and then doomed in the disk cache and removed from that
699 // list.
700 storage()->DeleteRegistration(
701 registration_->id(),
702 scope_.GetOrigin(),
703 base::Bind(&VerifyPurgeableListStatusCallback,
704 base::Unretained(storage()->database_.get()),
705 &verify_ids,
706 &was_called,
707 &result));
708 base::RunLoop().RunUntilIdle();
709 ASSERT_TRUE(was_called);
710 EXPECT_EQ(SERVICE_WORKER_OK, result);
711 EXPECT_EQ(2u, verify_ids.size());
712 verify_ids.clear();
713 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
714 storage()->database_->GetPurgeableResourceIds(&verify_ids));
715 EXPECT_EQ(2u, verify_ids.size());
717 EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, false));
718 EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id2_, false));
720 // Doom the version, now it happens.
721 registration_->waiting_version()->Doom();
722 base::RunLoop().RunUntilIdle();
723 EXPECT_EQ(SERVICE_WORKER_OK, result);
724 EXPECT_EQ(2u, verify_ids.size());
725 verify_ids.clear();
726 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
727 storage()->database_->GetPurgeableResourceIds(&verify_ids));
728 EXPECT_TRUE(verify_ids.empty());
730 EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id1_, false));
731 EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id2_, false));
734 TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_ActiveVersion) {
735 // Promote the worker to active and add a controllee.
736 registration_->SetActiveVersion(registration_->waiting_version());
737 storage()->UpdateToActiveState(
738 registration_.get(), base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
739 scoped_ptr<ServiceWorkerProviderHost> host(
740 new ServiceWorkerProviderHost(33 /* dummy render process id */,
741 1 /* dummy provider_id */,
742 context_->AsWeakPtr(),
743 NULL));
744 registration_->active_version()->AddControllee(host.get());
746 bool was_called = false;
747 ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
748 std::set<int64> verify_ids;
750 // Deleting the registration should move the resources to the purgeable list
751 // but keep them available.
752 storage()->DeleteRegistration(
753 registration_->id(),
754 scope_.GetOrigin(),
755 base::Bind(&VerifyPurgeableListStatusCallback,
756 base::Unretained(storage()->database_.get()),
757 &verify_ids,
758 &was_called,
759 &result));
760 registration_->active_version()->Doom();
761 base::RunLoop().RunUntilIdle();
762 ASSERT_TRUE(was_called);
763 EXPECT_EQ(SERVICE_WORKER_OK, result);
764 EXPECT_EQ(2u, verify_ids.size());
765 verify_ids.clear();
766 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
767 storage()->database_->GetPurgeableResourceIds(&verify_ids));
768 EXPECT_EQ(2u, verify_ids.size());
770 EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, true));
771 EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id2_, true));
773 // Removing the controllee should cause the resources to be deleted.
774 registration_->active_version()->RemoveControllee(host.get());
775 base::RunLoop().RunUntilIdle();
776 verify_ids.clear();
777 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
778 storage()->database_->GetPurgeableResourceIds(&verify_ids));
779 EXPECT_TRUE(verify_ids.empty());
781 EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id1_, false));
782 EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id2_, false));
785 TEST_F(ServiceWorkerResourceStorageDiskTest, CleanupOnRestart) {
786 // Promote the worker to active and add a controllee.
787 registration_->SetActiveVersion(registration_->waiting_version());
788 registration_->SetWaitingVersion(NULL);
789 storage()->UpdateToActiveState(
790 registration_.get(), base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
791 scoped_ptr<ServiceWorkerProviderHost> host(
792 new ServiceWorkerProviderHost(33 /* dummy render process id */,
793 1 /* dummy provider_id */,
794 context_->AsWeakPtr(),
795 NULL));
796 registration_->active_version()->AddControllee(host.get());
798 bool was_called = false;
799 ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
800 std::set<int64> verify_ids;
802 // Deleting the registration should move the resources to the purgeable list
803 // but keep them available.
804 storage()->DeleteRegistration(
805 registration_->id(),
806 scope_.GetOrigin(),
807 base::Bind(&VerifyPurgeableListStatusCallback,
808 base::Unretained(storage()->database_.get()),
809 &verify_ids,
810 &was_called,
811 &result));
812 base::RunLoop().RunUntilIdle();
813 ASSERT_TRUE(was_called);
814 EXPECT_EQ(SERVICE_WORKER_OK, result);
815 EXPECT_EQ(2u, verify_ids.size());
816 verify_ids.clear();
817 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
818 storage()->database_->GetPurgeableResourceIds(&verify_ids));
819 EXPECT_EQ(2u, verify_ids.size());
821 EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, true));
822 EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id2_, true));
824 // Also add an uncommitted resource.
825 int64 kStaleUncommittedResourceId = storage()->NewResourceId();
826 storage()->StoreUncommittedResponseId(kStaleUncommittedResourceId);
827 base::RunLoop().RunUntilIdle();
828 verify_ids.clear();
829 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
830 storage()->database_->GetUncommittedResourceIds(&verify_ids));
831 EXPECT_EQ(1u, verify_ids.size());
832 WriteBasicResponse(storage(), kStaleUncommittedResourceId);
833 EXPECT_TRUE(
834 VerifyBasicResponse(storage(), kStaleUncommittedResourceId, true));
836 // Simulate browser shutdown. The purgeable and uncommitted resources are now
837 // stale.
838 context_.reset();
839 scoped_ptr<ServiceWorkerDatabaseTaskManager> database_task_manager(
840 new MockServiceWorkerDatabaseTaskManager(
841 base::ThreadTaskRunnerHandle::Get()));
842 context_.reset(
843 new ServiceWorkerContextCore(GetUserDataDirectory(),
844 base::ThreadTaskRunnerHandle::Get(),
845 database_task_manager.Pass(),
846 base::ThreadTaskRunnerHandle::Get(),
847 NULL,
848 NULL,
849 NULL,
850 NULL));
851 storage()->LazyInitialize(base::Bind(&base::DoNothing));
852 base::RunLoop().RunUntilIdle();
854 // Store a new uncommitted resource. This triggers stale resource cleanup.
855 int64 kNewResourceId = storage()->NewResourceId();
856 WriteBasicResponse(storage(), kNewResourceId);
857 storage()->StoreUncommittedResponseId(kNewResourceId);
858 base::RunLoop().RunUntilIdle();
860 // The stale resources should be purged, but the new resource should persist.
861 verify_ids.clear();
862 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
863 storage()->database_->GetUncommittedResourceIds(&verify_ids));
864 ASSERT_EQ(1u, verify_ids.size());
865 EXPECT_EQ(kNewResourceId, *verify_ids.begin());
867 // Purging resources needs interactions with SimpleCache's worker thread,
868 // so single RunUntilIdle() call may not be sufficient.
869 while (storage()->is_purge_pending_)
870 base::RunLoop().RunUntilIdle();
872 verify_ids.clear();
873 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
874 storage()->database_->GetPurgeableResourceIds(&verify_ids));
875 EXPECT_TRUE(verify_ids.empty());
876 EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id1_, false));
877 EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id2_, false));
878 EXPECT_FALSE(
879 VerifyBasicResponse(storage(), kStaleUncommittedResourceId, false));
880 EXPECT_TRUE(VerifyBasicResponse(storage(), kNewResourceId, true));
883 TEST_F(ServiceWorkerResourceStorageTest, UpdateRegistration) {
884 // Promote the worker to active worker and add a controllee.
885 registration_->SetActiveVersion(registration_->waiting_version());
886 storage()->UpdateToActiveState(
887 registration_.get(), base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
888 scoped_ptr<ServiceWorkerProviderHost> host(
889 new ServiceWorkerProviderHost(33 /* dummy render process id */,
890 1 /* dummy provider_id */,
891 context_->AsWeakPtr(),
892 NULL));
893 registration_->active_version()->AddControllee(host.get());
895 bool was_called = false;
896 ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
897 std::set<int64> verify_ids;
899 // Make an updated registration.
900 scoped_refptr<ServiceWorkerVersion> live_version = new ServiceWorkerVersion(
901 registration_.get(), script_, storage()->NewVersionId(), context_ptr_);
902 live_version->SetStatus(ServiceWorkerVersion::NEW);
903 registration_->SetWaitingVersion(live_version.get());
905 // Writing the registration should move the old version's resources to the
906 // purgeable list but keep them available.
907 storage()->StoreRegistration(
908 registration_.get(),
909 registration_->waiting_version(),
910 base::Bind(&VerifyPurgeableListStatusCallback,
911 base::Unretained(storage()->database_.get()),
912 &verify_ids,
913 &was_called,
914 &result));
915 registration_->active_version()->Doom();
916 base::RunLoop().RunUntilIdle();
917 ASSERT_TRUE(was_called);
918 EXPECT_EQ(SERVICE_WORKER_OK, result);
919 EXPECT_EQ(2u, verify_ids.size());
920 verify_ids.clear();
921 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
922 storage()->database_->GetPurgeableResourceIds(&verify_ids));
923 EXPECT_EQ(2u, verify_ids.size());
925 EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, false));
926 EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id2_, false));
928 // Removing the controllee should cause the old version's resources to be
929 // deleted.
930 registration_->active_version()->RemoveControllee(host.get());
931 base::RunLoop().RunUntilIdle();
932 verify_ids.clear();
933 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
934 storage()->database_->GetPurgeableResourceIds(&verify_ids));
935 EXPECT_TRUE(verify_ids.empty());
937 EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id1_, false));
938 EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id2_, false));
941 TEST_F(ServiceWorkerStorageTest, FindRegistration_LongestScopeMatch) {
942 const GURL kDocumentUrl("http://www.example.com/scope/foo");
943 scoped_refptr<ServiceWorkerRegistration> found_registration;
945 // Registration for "/scope/".
946 const GURL kScope1("http://www.example.com/scope/");
947 const GURL kScript1("http://www.example.com/script1.js");
948 const int64 kRegistrationId1 = 1;
949 const int64 kVersionId1 = 1;
950 scoped_refptr<ServiceWorkerRegistration> live_registration1 =
951 new ServiceWorkerRegistration(
952 kScope1, kRegistrationId1, context_ptr_);
953 scoped_refptr<ServiceWorkerVersion> live_version1 =
954 new ServiceWorkerVersion(
955 live_registration1.get(), kScript1, kVersionId1, context_ptr_);
956 live_version1->SetStatus(ServiceWorkerVersion::INSTALLED);
957 live_registration1->SetWaitingVersion(live_version1.get());
959 // Registration for "/scope/foo".
960 const GURL kScope2("http://www.example.com/scope/foo");
961 const GURL kScript2("http://www.example.com/script2.js");
962 const int64 kRegistrationId2 = 2;
963 const int64 kVersionId2 = 2;
964 scoped_refptr<ServiceWorkerRegistration> live_registration2 =
965 new ServiceWorkerRegistration(
966 kScope2, kRegistrationId2, context_ptr_);
967 scoped_refptr<ServiceWorkerVersion> live_version2 =
968 new ServiceWorkerVersion(
969 live_registration2.get(), kScript2, kVersionId2, context_ptr_);
970 live_version2->SetStatus(ServiceWorkerVersion::INSTALLED);
971 live_registration2->SetWaitingVersion(live_version2.get());
973 // Registration for "/scope/foobar".
974 const GURL kScope3("http://www.example.com/scope/foobar");
975 const GURL kScript3("http://www.example.com/script3.js");
976 const int64 kRegistrationId3 = 3;
977 const int64 kVersionId3 = 3;
978 scoped_refptr<ServiceWorkerRegistration> live_registration3 =
979 new ServiceWorkerRegistration(
980 kScope3, kRegistrationId3, context_ptr_);
981 scoped_refptr<ServiceWorkerVersion> live_version3 =
982 new ServiceWorkerVersion(
983 live_registration3.get(), kScript3, kVersionId3, context_ptr_);
984 live_version3->SetStatus(ServiceWorkerVersion::INSTALLED);
985 live_registration3->SetWaitingVersion(live_version3.get());
987 // Notify storage of they being installed.
988 storage()->NotifyInstallingRegistration(live_registration1.get());
989 storage()->NotifyInstallingRegistration(live_registration2.get());
990 storage()->NotifyInstallingRegistration(live_registration3.get());
992 // Find a registration among installing ones.
993 EXPECT_EQ(SERVICE_WORKER_OK,
994 FindRegistrationForDocument(kDocumentUrl, &found_registration));
995 EXPECT_EQ(live_registration2, found_registration);
996 found_registration = NULL;
998 // Store registrations.
999 EXPECT_EQ(SERVICE_WORKER_OK,
1000 StoreRegistration(live_registration1, live_version1));
1001 EXPECT_EQ(SERVICE_WORKER_OK,
1002 StoreRegistration(live_registration2, live_version2));
1003 EXPECT_EQ(SERVICE_WORKER_OK,
1004 StoreRegistration(live_registration3, live_version3));
1006 // Notify storage of installations no longer happening.
1007 storage()->NotifyDoneInstallingRegistration(
1008 live_registration1.get(), NULL, SERVICE_WORKER_OK);
1009 storage()->NotifyDoneInstallingRegistration(
1010 live_registration2.get(), NULL, SERVICE_WORKER_OK);
1011 storage()->NotifyDoneInstallingRegistration(
1012 live_registration3.get(), NULL, SERVICE_WORKER_OK);
1014 // Find a registration among installed ones.
1015 EXPECT_EQ(SERVICE_WORKER_OK,
1016 FindRegistrationForDocument(kDocumentUrl, &found_registration));
1017 EXPECT_EQ(live_registration2, found_registration);
1020 TEST_F(ServiceWorkerStorageTest, CompareResources) {
1021 // Compare two small responses containing the same data.
1022 WriteBasicResponse(storage(), 1);
1023 WriteBasicResponse(storage(), 2);
1024 ServiceWorkerStatusCode status = static_cast<ServiceWorkerStatusCode>(-1);
1025 bool are_equal = false;
1026 storage()->CompareScriptResources(
1027 1, 2,
1028 base::Bind(&OnCompareComplete, &status, &are_equal));
1029 base::RunLoop().RunUntilIdle();
1030 EXPECT_EQ(SERVICE_WORKER_OK, status);
1031 EXPECT_TRUE(are_equal);
1033 // Compare two small responses with different data.
1034 const char kHttpHeaders[] = "HTTP/1.0 200 HONKYDORY\0\0";
1035 const char kHttpBody[] = "Goodbye";
1036 std::string headers(kHttpHeaders, arraysize(kHttpHeaders));
1037 WriteStringResponse(storage(), 3, headers, std::string(kHttpBody));
1038 status = static_cast<ServiceWorkerStatusCode>(-1);
1039 are_equal = true;
1040 storage()->CompareScriptResources(
1041 1, 3,
1042 base::Bind(&OnCompareComplete, &status, &are_equal));
1043 base::RunLoop().RunUntilIdle();
1044 EXPECT_EQ(SERVICE_WORKER_OK, status);
1045 EXPECT_FALSE(are_equal);
1047 // Compare two large responses with the same data.
1048 const int k32K = 32 * 1024;
1049 WriteResponseOfSize(storage(), 4, 'a', k32K);
1050 WriteResponseOfSize(storage(), 5, 'a', k32K);
1051 status = static_cast<ServiceWorkerStatusCode>(-1);
1052 are_equal = false;
1053 storage()->CompareScriptResources(
1054 4, 5,
1055 base::Bind(&OnCompareComplete, &status, &are_equal));
1056 base::RunLoop().RunUntilIdle();
1057 EXPECT_EQ(SERVICE_WORKER_OK, status);
1058 EXPECT_TRUE(are_equal);
1060 // Compare a large and small response.
1061 status = static_cast<ServiceWorkerStatusCode>(-1);
1062 are_equal = true;
1063 storage()->CompareScriptResources(
1064 1, 5,
1065 base::Bind(&OnCompareComplete, &status, &are_equal));
1066 base::RunLoop().RunUntilIdle();
1067 EXPECT_EQ(SERVICE_WORKER_OK, status);
1068 EXPECT_FALSE(are_equal);
1070 // Compare two large responses with different data.
1071 WriteResponseOfSize(storage(), 6, 'b', k32K);
1072 status = static_cast<ServiceWorkerStatusCode>(-1);
1073 are_equal = true;
1074 storage()->CompareScriptResources(
1075 5, 6,
1076 base::Bind(&OnCompareComplete, &status, &are_equal));
1077 base::RunLoop().RunUntilIdle();
1078 EXPECT_EQ(SERVICE_WORKER_OK, status);
1079 EXPECT_FALSE(are_equal);
1082 } // namespace content