Battery Status API: add UMA logging for Linux.
[chromium-blink-merge.git] / content / browser / service_worker / service_worker_storage_unittest.cc
blobea615026ad3218db24f673c68f4f439a6c949195
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 OnIOComplete(int* rv_out, int rv) {
83 *rv_out = rv;
86 void OnCompareComplete(
87 ServiceWorkerStatusCode* status_out, bool* are_equal_out,
88 ServiceWorkerStatusCode status, bool are_equal) {
89 *status_out = status;
90 *are_equal_out = are_equal;
93 void WriteResponse(
94 ServiceWorkerStorage* storage, int64 id,
95 const std::string& headers,
96 IOBuffer* body, int length) {
97 scoped_ptr<ServiceWorkerResponseWriter> writer =
98 storage->CreateResponseWriter(id);
100 scoped_ptr<net::HttpResponseInfo> info(new net::HttpResponseInfo);
101 info->request_time = base::Time::Now();
102 info->response_time = base::Time::Now();
103 info->was_cached = false;
104 info->headers = new net::HttpResponseHeaders(headers);
105 scoped_refptr<HttpResponseInfoIOBuffer> info_buffer =
106 new HttpResponseInfoIOBuffer(info.release());
108 int rv = -1234;
109 writer->WriteInfo(info_buffer.get(), base::Bind(&OnIOComplete, &rv));
110 base::RunLoop().RunUntilIdle();
111 EXPECT_LT(0, rv);
113 rv = -1234;
114 writer->WriteData(body, length, base::Bind(&OnIOComplete, &rv));
115 base::RunLoop().RunUntilIdle();
116 EXPECT_EQ(length, rv);
119 void WriteStringResponse(
120 ServiceWorkerStorage* storage, int64 id,
121 const std::string& headers,
122 const std::string& body) {
123 scoped_refptr<IOBuffer> body_buffer(new WrappedIOBuffer(body.data()));
124 WriteResponse(storage, id, headers, body_buffer.get(), body.length());
127 void WriteBasicResponse(ServiceWorkerStorage* storage, int64 id) {
128 scoped_ptr<ServiceWorkerResponseWriter> writer =
129 storage->CreateResponseWriter(id);
131 const char kHttpHeaders[] = "HTTP/1.0 200 HONKYDORY\0Content-Length: 5\0\0";
132 const char kHttpBody[] = "Hello";
133 std::string headers(kHttpHeaders, arraysize(kHttpHeaders));
134 WriteStringResponse(storage, id, headers, std::string(kHttpBody));
137 bool VerifyBasicResponse(ServiceWorkerStorage* storage, int64 id,
138 bool expected_positive_result) {
139 const std::string kExpectedHttpBody("Hello");
140 scoped_ptr<ServiceWorkerResponseReader> reader =
141 storage->CreateResponseReader(id);
142 scoped_refptr<HttpResponseInfoIOBuffer> info_buffer =
143 new HttpResponseInfoIOBuffer();
145 TestCompletionCallback cb;
146 reader->ReadInfo(info_buffer.get(), cb.callback());
147 int rv = cb.WaitForResult();
148 if (expected_positive_result)
149 EXPECT_LT(0, rv);
150 if (rv <= 0)
151 return false;
154 std::string received_body;
156 const int kBigEnough = 512;
157 scoped_refptr<net::IOBuffer> buffer = new IOBuffer(kBigEnough);
158 TestCompletionCallback cb;
159 reader->ReadData(buffer.get(), kBigEnough, cb.callback());
160 int rv = cb.WaitForResult();
161 EXPECT_EQ(static_cast<int>(kExpectedHttpBody.size()), rv);
162 if (rv <= 0)
163 return false;
164 received_body.assign(buffer->data(), rv);
167 bool status_match =
168 std::string("HONKYDORY") ==
169 info_buffer->http_info->headers->GetStatusText();
170 bool data_match = kExpectedHttpBody == received_body;
172 EXPECT_TRUE(status_match);
173 EXPECT_TRUE(data_match);
174 return status_match && data_match;
177 void WriteResponseOfSize(ServiceWorkerStorage* storage, int64 id,
178 char val, int size) {
179 const char kHttpHeaders[] = "HTTP/1.0 200 HONKYDORY\00";
180 std::string headers(kHttpHeaders, arraysize(kHttpHeaders));
181 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(size);
182 memset(buffer->data(), val, size);
183 WriteResponse(storage, id, headers, buffer.get(), size);
186 } // namespace
188 class ServiceWorkerStorageTest : public testing::Test {
189 public:
190 ServiceWorkerStorageTest()
191 : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {
194 virtual void SetUp() OVERRIDE {
195 context_.reset(
196 new ServiceWorkerContextCore(GetUserDataDirectory(),
197 base::ThreadTaskRunnerHandle::Get(),
198 base::ThreadTaskRunnerHandle::Get(),
199 base::ThreadTaskRunnerHandle::Get(),
200 NULL,
201 NULL,
202 NULL));
203 context_ptr_ = context_->AsWeakPtr();
206 virtual void TearDown() OVERRIDE {
207 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 int64 kRegistrationId = 0;
331 const int64 kVersionId = 0;
332 const base::Time kToday = base::Time::Now();
333 const base::Time kYesterday = kToday - base::TimeDelta::FromDays(1);
335 scoped_refptr<ServiceWorkerRegistration> found_registration;
337 // We shouldn't find anything without having stored anything.
338 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
339 FindRegistrationForDocument(kDocumentUrl, &found_registration));
340 EXPECT_FALSE(found_registration.get());
342 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
343 FindRegistrationForPattern(kScope, &found_registration));
344 EXPECT_FALSE(found_registration.get());
346 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
347 FindRegistrationForId(
348 kRegistrationId, kScope.GetOrigin(), &found_registration));
349 EXPECT_FALSE(found_registration.get());
351 // Store something.
352 scoped_refptr<ServiceWorkerRegistration> live_registration =
353 new ServiceWorkerRegistration(
354 kScope, kRegistrationId, context_ptr_);
355 scoped_refptr<ServiceWorkerVersion> live_version =
356 new ServiceWorkerVersion(
357 live_registration.get(), kScript, kVersionId, context_ptr_);
358 live_version->SetStatus(ServiceWorkerVersion::INSTALLED);
359 live_registration->SetWaitingVersion(live_version.get());
360 live_registration->set_last_update_check(kYesterday);
361 EXPECT_EQ(SERVICE_WORKER_OK,
362 StoreRegistration(live_registration, live_version));
364 // Now we should find it and get the live ptr back immediately.
365 EXPECT_EQ(SERVICE_WORKER_OK,
366 FindRegistrationForDocument(kDocumentUrl, &found_registration));
367 EXPECT_EQ(live_registration, found_registration);
368 found_registration = NULL;
370 // But FindRegistrationForPattern is always async.
371 EXPECT_EQ(SERVICE_WORKER_OK,
372 FindRegistrationForPattern(kScope, &found_registration));
373 EXPECT_EQ(live_registration, found_registration);
374 found_registration = NULL;
376 // Can be found by id too.
377 EXPECT_EQ(SERVICE_WORKER_OK,
378 FindRegistrationForId(
379 kRegistrationId, kScope.GetOrigin(), &found_registration));
380 ASSERT_TRUE(found_registration.get());
381 EXPECT_EQ(kRegistrationId, found_registration->id());
382 EXPECT_EQ(live_registration, found_registration);
383 found_registration = NULL;
385 // Drop the live registration, but keep the version live.
386 live_registration = NULL;
388 // Now FindRegistrationForDocument should be async.
389 EXPECT_EQ(SERVICE_WORKER_OK,
390 FindRegistrationForDocument(kDocumentUrl, &found_registration));
391 ASSERT_TRUE(found_registration.get());
392 EXPECT_EQ(kRegistrationId, found_registration->id());
393 EXPECT_TRUE(found_registration->HasOneRef());
394 EXPECT_EQ(live_version.get(), found_registration->waiting_version());
395 found_registration = NULL;
397 // Drop the live version too.
398 live_version = NULL;
400 // And FindRegistrationForPattern is always async.
401 EXPECT_EQ(SERVICE_WORKER_OK,
402 FindRegistrationForPattern(kScope, &found_registration));
403 ASSERT_TRUE(found_registration.get());
404 EXPECT_EQ(kRegistrationId, found_registration->id());
405 EXPECT_TRUE(found_registration->HasOneRef());
406 EXPECT_FALSE(found_registration->active_version());
407 ASSERT_TRUE(found_registration->waiting_version());
408 EXPECT_EQ(kYesterday, found_registration->last_update_check());
409 EXPECT_EQ(ServiceWorkerVersion::INSTALLED,
410 found_registration->waiting_version()->status());
412 // Update to active and update the last check time.
413 scoped_refptr<ServiceWorkerVersion> temp_version =
414 found_registration->waiting_version();
415 temp_version->SetStatus(ServiceWorkerVersion::ACTIVATED);
416 found_registration->SetActiveVersion(temp_version.get());
417 temp_version = NULL;
418 EXPECT_EQ(SERVICE_WORKER_OK, UpdateToActiveState(found_registration));
419 found_registration->set_last_update_check(kToday);
420 UpdateLastUpdateCheckTime(found_registration.get());
422 found_registration = NULL;
424 // Trying to update a unstored registration to active should fail.
425 scoped_refptr<ServiceWorkerRegistration> unstored_registration =
426 new ServiceWorkerRegistration(
427 kScope, kRegistrationId + 1, context_ptr_);
428 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
429 UpdateToActiveState(unstored_registration));
430 unstored_registration = NULL;
432 // The Find methods should return a registration with an active version
433 // and the expected update time.
434 EXPECT_EQ(SERVICE_WORKER_OK,
435 FindRegistrationForDocument(kDocumentUrl, &found_registration));
436 ASSERT_TRUE(found_registration.get());
437 EXPECT_EQ(kRegistrationId, found_registration->id());
438 EXPECT_TRUE(found_registration->HasOneRef());
439 EXPECT_FALSE(found_registration->waiting_version());
440 ASSERT_TRUE(found_registration->active_version());
441 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED,
442 found_registration->active_version()->status());
443 EXPECT_EQ(kToday, found_registration->last_update_check());
445 // Delete from storage but with a instance still live.
446 EXPECT_TRUE(context_->GetLiveVersion(kRegistrationId));
447 EXPECT_EQ(SERVICE_WORKER_OK,
448 DeleteRegistration(kRegistrationId, kScope.GetOrigin()));
449 EXPECT_TRUE(context_->GetLiveVersion(kRegistrationId));
451 // Should no longer be found.
452 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
453 FindRegistrationForId(
454 kRegistrationId, kScope.GetOrigin(), &found_registration));
455 EXPECT_FALSE(found_registration.get());
457 // Deleting an unstored registration should succeed.
458 EXPECT_EQ(SERVICE_WORKER_OK,
459 DeleteRegistration(kRegistrationId + 1, kScope.GetOrigin()));
462 TEST_F(ServiceWorkerStorageTest, InstallingRegistrationsAreFindable) {
463 const GURL kScope("http://www.test.not/scope/");
464 const GURL kScript("http://www.test.not/script.js");
465 const GURL kDocumentUrl("http://www.test.not/scope/document.html");
466 const int64 kRegistrationId = 0;
467 const int64 kVersionId = 0;
469 scoped_refptr<ServiceWorkerRegistration> found_registration;
471 // Create an unstored registration.
472 scoped_refptr<ServiceWorkerRegistration> live_registration =
473 new ServiceWorkerRegistration(
474 kScope, kRegistrationId, context_ptr_);
475 scoped_refptr<ServiceWorkerVersion> live_version =
476 new ServiceWorkerVersion(
477 live_registration.get(), kScript, kVersionId, context_ptr_);
478 live_version->SetStatus(ServiceWorkerVersion::INSTALLING);
479 live_registration->SetWaitingVersion(live_version.get());
481 // Should not be findable, including by GetAllRegistrations.
482 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
483 FindRegistrationForId(
484 kRegistrationId, kScope.GetOrigin(), &found_registration));
485 EXPECT_FALSE(found_registration.get());
487 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
488 FindRegistrationForDocument(kDocumentUrl, &found_registration));
489 EXPECT_FALSE(found_registration.get());
491 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
492 FindRegistrationForPattern(kScope, &found_registration));
493 EXPECT_FALSE(found_registration.get());
495 std::vector<ServiceWorkerRegistrationInfo> all_registrations;
496 GetAllRegistrations(&all_registrations);
497 EXPECT_TRUE(all_registrations.empty());
499 // Notify storage of it being installed.
500 storage()->NotifyInstallingRegistration(live_registration.get());
502 // Now should be findable.
503 EXPECT_EQ(SERVICE_WORKER_OK,
504 FindRegistrationForId(
505 kRegistrationId, kScope.GetOrigin(), &found_registration));
506 EXPECT_EQ(live_registration, found_registration);
507 found_registration = NULL;
509 EXPECT_EQ(SERVICE_WORKER_OK,
510 FindRegistrationForDocument(kDocumentUrl, &found_registration));
511 EXPECT_EQ(live_registration, found_registration);
512 found_registration = NULL;
514 EXPECT_EQ(SERVICE_WORKER_OK,
515 FindRegistrationForPattern(kScope, &found_registration));
516 EXPECT_EQ(live_registration, found_registration);
517 found_registration = NULL;
519 GetAllRegistrations(&all_registrations);
520 EXPECT_EQ(1u, all_registrations.size());
521 all_registrations.clear();
523 // Notify storage of installation no longer happening.
524 storage()->NotifyDoneInstallingRegistration(
525 live_registration.get(), NULL, SERVICE_WORKER_OK);
527 // Once again, should not be findable.
528 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
529 FindRegistrationForId(
530 kRegistrationId, kScope.GetOrigin(), &found_registration));
531 EXPECT_FALSE(found_registration.get());
533 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
534 FindRegistrationForDocument(kDocumentUrl, &found_registration));
535 EXPECT_FALSE(found_registration.get());
537 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
538 FindRegistrationForPattern(kScope, &found_registration));
539 EXPECT_FALSE(found_registration.get());
541 GetAllRegistrations(&all_registrations);
542 EXPECT_TRUE(all_registrations.empty());
545 class ServiceWorkerResourceStorageTest : public ServiceWorkerStorageTest {
546 public:
547 virtual void SetUp() OVERRIDE {
548 ServiceWorkerStorageTest::SetUp();
550 storage()->LazyInitialize(base::Bind(&base::DoNothing));
551 base::RunLoop().RunUntilIdle();
552 scope_ = GURL("http://www.test.not/scope/");
553 script_ = GURL("http://www.test.not/script.js");
554 import_ = GURL("http://www.test.not/import.js");
555 document_url_ = GURL("http://www.test.not/scope/document.html");
556 registration_id_ = storage()->NewRegistrationId();
557 version_id_ = storage()->NewVersionId();
558 resource_id1_ = storage()->NewResourceId();
559 resource_id2_ = storage()->NewResourceId();
561 // Cons up a new registration+version with two script resources.
562 RegistrationData data;
563 data.registration_id = registration_id_;
564 data.scope = scope_;
565 data.script = script_;
566 data.version_id = version_id_;
567 data.is_active = false;
568 std::vector<ResourceRecord> resources;
569 resources.push_back(ResourceRecord(resource_id1_, script_));
570 resources.push_back(ResourceRecord(resource_id2_, import_));
571 registration_ = storage()->GetOrCreateRegistration(data, resources);
572 registration_->waiting_version()->SetStatus(ServiceWorkerVersion::NEW);
574 // Add the resources ids to the uncommitted list.
575 storage()->StoreUncommittedResponseId(resource_id1_);
576 storage()->StoreUncommittedResponseId(resource_id2_);
577 base::RunLoop().RunUntilIdle();
578 std::set<int64> verify_ids;
579 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
580 storage()->database_->GetUncommittedResourceIds(&verify_ids));
581 EXPECT_EQ(2u, verify_ids.size());
583 // And dump something in the disk cache for them.
584 WriteBasicResponse(storage(), resource_id1_);
585 WriteBasicResponse(storage(), resource_id2_);
586 EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, true));
587 EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id2_, true));
589 // Storing the registration/version should take the resources ids out
590 // of the uncommitted list.
591 EXPECT_EQ(
592 SERVICE_WORKER_OK,
593 StoreRegistration(registration_, registration_->waiting_version()));
594 verify_ids.clear();
595 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
596 storage()->database_->GetUncommittedResourceIds(&verify_ids));
597 EXPECT_TRUE(verify_ids.empty());
600 protected:
601 GURL scope_;
602 GURL script_;
603 GURL import_;
604 GURL document_url_;
605 int64 registration_id_;
606 int64 version_id_;
607 int64 resource_id1_;
608 int64 resource_id2_;
609 scoped_refptr<ServiceWorkerRegistration> registration_;
612 class ServiceWorkerResourceStorageDiskTest
613 : public ServiceWorkerResourceStorageTest {
614 public:
615 virtual void SetUp() OVERRIDE {
616 ASSERT_TRUE(user_data_directory_.CreateUniqueTempDir());
617 ServiceWorkerResourceStorageTest::SetUp();
620 virtual base::FilePath GetUserDataDirectory() OVERRIDE {
621 return user_data_directory_.path();
624 protected:
625 base::ScopedTempDir user_data_directory_;
628 TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_NoLiveVersion) {
629 bool was_called = false;
630 ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
631 std::set<int64> verify_ids;
633 registration_->SetWaitingVersion(NULL);
634 registration_ = NULL;
636 // Deleting the registration should result in the resources being added to the
637 // purgeable list and then doomed in the disk cache and removed from that
638 // list.
639 storage()->DeleteRegistration(
640 registration_id_,
641 scope_.GetOrigin(),
642 base::Bind(&VerifyPurgeableListStatusCallback,
643 base::Unretained(storage()->database_.get()),
644 &verify_ids,
645 &was_called,
646 &result));
647 base::RunLoop().RunUntilIdle();
648 ASSERT_TRUE(was_called);
649 EXPECT_EQ(SERVICE_WORKER_OK, result);
650 EXPECT_EQ(2u, verify_ids.size());
651 verify_ids.clear();
652 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
653 storage()->database_->GetPurgeableResourceIds(&verify_ids));
654 EXPECT_TRUE(verify_ids.empty());
656 EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id1_, false));
657 EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id2_, false));
660 TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_WaitingVersion) {
661 bool was_called = false;
662 ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
663 std::set<int64> verify_ids;
665 // Deleting the registration should result in the resources being added to the
666 // purgeable list and then doomed in the disk cache and removed from that
667 // list.
668 storage()->DeleteRegistration(
669 registration_->id(),
670 scope_.GetOrigin(),
671 base::Bind(&VerifyPurgeableListStatusCallback,
672 base::Unretained(storage()->database_.get()),
673 &verify_ids,
674 &was_called,
675 &result));
676 base::RunLoop().RunUntilIdle();
677 ASSERT_TRUE(was_called);
678 EXPECT_EQ(SERVICE_WORKER_OK, result);
679 EXPECT_EQ(2u, verify_ids.size());
680 verify_ids.clear();
681 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
682 storage()->database_->GetPurgeableResourceIds(&verify_ids));
683 EXPECT_EQ(2u, verify_ids.size());
685 EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, false));
686 EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id2_, false));
688 // Doom the version, now it happens.
689 registration_->waiting_version()->Doom();
690 base::RunLoop().RunUntilIdle();
691 EXPECT_EQ(SERVICE_WORKER_OK, result);
692 EXPECT_EQ(2u, verify_ids.size());
693 verify_ids.clear();
694 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
695 storage()->database_->GetPurgeableResourceIds(&verify_ids));
696 EXPECT_TRUE(verify_ids.empty());
698 EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id1_, false));
699 EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id2_, false));
702 TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_ActiveVersion) {
703 // Promote the worker to active and add a controllee.
704 registration_->SetActiveVersion(registration_->waiting_version());
705 storage()->UpdateToActiveState(
706 registration_.get(), base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
707 scoped_ptr<ServiceWorkerProviderHost> host(
708 new ServiceWorkerProviderHost(33 /* dummy render process id */,
709 1 /* dummy provider_id */,
710 context_->AsWeakPtr(),
711 NULL));
712 registration_->active_version()->AddControllee(host.get());
714 bool was_called = false;
715 ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
716 std::set<int64> verify_ids;
718 // Deleting the registration should move the resources to the purgeable list
719 // but keep them available.
720 storage()->DeleteRegistration(
721 registration_->id(),
722 scope_.GetOrigin(),
723 base::Bind(&VerifyPurgeableListStatusCallback,
724 base::Unretained(storage()->database_.get()),
725 &verify_ids,
726 &was_called,
727 &result));
728 registration_->active_version()->Doom();
729 base::RunLoop().RunUntilIdle();
730 ASSERT_TRUE(was_called);
731 EXPECT_EQ(SERVICE_WORKER_OK, result);
732 EXPECT_EQ(2u, verify_ids.size());
733 verify_ids.clear();
734 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
735 storage()->database_->GetPurgeableResourceIds(&verify_ids));
736 EXPECT_EQ(2u, verify_ids.size());
738 EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, true));
739 EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id2_, true));
741 // Removing the controllee should cause the resources to be deleted.
742 registration_->active_version()->RemoveControllee(host.get());
743 base::RunLoop().RunUntilIdle();
744 verify_ids.clear();
745 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
746 storage()->database_->GetPurgeableResourceIds(&verify_ids));
747 EXPECT_TRUE(verify_ids.empty());
749 EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id1_, false));
750 EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id2_, false));
753 // Android has flaky IO error: http://crbug.com/387045
754 #if defined(OS_ANDROID)
755 #define MAYBE_CleanupOnRestart DISABLED_CleanupOnRestart
756 #else
757 #define MAYBE_CleanupOnRestart CleanupOnRestart
758 #endif
759 TEST_F(ServiceWorkerResourceStorageDiskTest, MAYBE_CleanupOnRestart) {
760 // Promote the worker to active and add a controllee.
761 registration_->SetActiveVersion(registration_->waiting_version());
762 registration_->SetWaitingVersion(NULL);
763 storage()->UpdateToActiveState(
764 registration_.get(), base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
765 scoped_ptr<ServiceWorkerProviderHost> host(
766 new ServiceWorkerProviderHost(33 /* dummy render process id */,
767 1 /* dummy provider_id */,
768 context_->AsWeakPtr(),
769 NULL));
770 registration_->active_version()->AddControllee(host.get());
772 bool was_called = false;
773 ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
774 std::set<int64> verify_ids;
776 // Deleting the registration should move the resources to the purgeable list
777 // but keep them available.
778 storage()->DeleteRegistration(
779 registration_->id(),
780 scope_.GetOrigin(),
781 base::Bind(&VerifyPurgeableListStatusCallback,
782 base::Unretained(storage()->database_.get()),
783 &verify_ids,
784 &was_called,
785 &result));
786 base::RunLoop().RunUntilIdle();
787 ASSERT_TRUE(was_called);
788 EXPECT_EQ(SERVICE_WORKER_OK, result);
789 EXPECT_EQ(2u, verify_ids.size());
790 verify_ids.clear();
791 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
792 storage()->database_->GetPurgeableResourceIds(&verify_ids));
793 EXPECT_EQ(2u, verify_ids.size());
795 EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, true));
796 EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id2_, true));
798 // Also add an uncommitted resource.
799 int64 kStaleUncommittedResourceId = storage()->NewResourceId();
800 storage()->StoreUncommittedResponseId(kStaleUncommittedResourceId);
801 base::RunLoop().RunUntilIdle();
802 verify_ids.clear();
803 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
804 storage()->database_->GetUncommittedResourceIds(&verify_ids));
805 EXPECT_EQ(1u, verify_ids.size());
806 WriteBasicResponse(storage(), kStaleUncommittedResourceId);
807 EXPECT_TRUE(
808 VerifyBasicResponse(storage(), kStaleUncommittedResourceId, true));
810 // Simulate browser shutdown. The purgeable and uncommitted resources are now
811 // stale.
812 context_.reset();
813 context_.reset(
814 new ServiceWorkerContextCore(GetUserDataDirectory(),
815 base::ThreadTaskRunnerHandle::Get(),
816 base::ThreadTaskRunnerHandle::Get(),
817 base::ThreadTaskRunnerHandle::Get(),
818 NULL,
819 NULL,
820 NULL));
821 storage()->LazyInitialize(base::Bind(&base::DoNothing));
822 base::RunLoop().RunUntilIdle();
824 // Store a new uncommitted resource. This triggers stale resource cleanup.
825 int64 kNewResourceId = storage()->NewResourceId();
826 WriteBasicResponse(storage(), kNewResourceId);
827 storage()->StoreUncommittedResponseId(kNewResourceId);
828 base::RunLoop().RunUntilIdle();
830 // The stale resources should be purged, but the new resource should persist.
831 verify_ids.clear();
832 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
833 storage()->database_->GetUncommittedResourceIds(&verify_ids));
834 ASSERT_EQ(1u, verify_ids.size());
835 EXPECT_EQ(kNewResourceId, *verify_ids.begin());
837 verify_ids.clear();
838 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
839 storage()->database_->GetPurgeableResourceIds(&verify_ids));
840 EXPECT_TRUE(verify_ids.empty());
841 EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id1_, false));
842 EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id2_, false));
843 EXPECT_FALSE(
844 VerifyBasicResponse(storage(), kStaleUncommittedResourceId, false));
845 EXPECT_TRUE(VerifyBasicResponse(storage(), kNewResourceId, true));
848 TEST_F(ServiceWorkerResourceStorageTest, UpdateRegistration) {
849 // Promote the worker to active worker and add a controllee.
850 registration_->SetActiveVersion(registration_->waiting_version());
851 storage()->UpdateToActiveState(
852 registration_.get(), base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
853 scoped_ptr<ServiceWorkerProviderHost> host(
854 new ServiceWorkerProviderHost(33 /* dummy render process id */,
855 1 /* dummy provider_id */,
856 context_->AsWeakPtr(),
857 NULL));
858 registration_->active_version()->AddControllee(host.get());
860 bool was_called = false;
861 ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
862 std::set<int64> verify_ids;
864 // Make an updated registration.
865 scoped_refptr<ServiceWorkerVersion> live_version = new ServiceWorkerVersion(
866 registration_.get(), script_, storage()->NewVersionId(), context_ptr_);
867 live_version->SetStatus(ServiceWorkerVersion::NEW);
868 registration_->SetWaitingVersion(live_version.get());
870 // Writing the registration should move the old version's resources to the
871 // purgeable list but keep them available.
872 storage()->StoreRegistration(
873 registration_.get(),
874 registration_->waiting_version(),
875 base::Bind(&VerifyPurgeableListStatusCallback,
876 base::Unretained(storage()->database_.get()),
877 &verify_ids,
878 &was_called,
879 &result));
880 registration_->active_version()->Doom();
881 base::RunLoop().RunUntilIdle();
882 ASSERT_TRUE(was_called);
883 EXPECT_EQ(SERVICE_WORKER_OK, result);
884 EXPECT_EQ(2u, verify_ids.size());
885 verify_ids.clear();
886 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
887 storage()->database_->GetPurgeableResourceIds(&verify_ids));
888 EXPECT_EQ(2u, verify_ids.size());
890 EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, false));
891 EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id2_, false));
893 // Removing the controllee should cause the old version's resources to be
894 // deleted.
895 registration_->active_version()->RemoveControllee(host.get());
896 base::RunLoop().RunUntilIdle();
897 verify_ids.clear();
898 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
899 storage()->database_->GetPurgeableResourceIds(&verify_ids));
900 EXPECT_TRUE(verify_ids.empty());
902 EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id1_, false));
903 EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id2_, false));
906 TEST_F(ServiceWorkerStorageTest, FindRegistration_LongestScopeMatch) {
907 const GURL kDocumentUrl("http://www.example.com/scope/foo");
908 scoped_refptr<ServiceWorkerRegistration> found_registration;
910 // Registration for "/scope/".
911 const GURL kScope1("http://www.example.com/scope/");
912 const GURL kScript1("http://www.example.com/script1.js");
913 const int64 kRegistrationId1 = 1;
914 const int64 kVersionId1 = 1;
915 scoped_refptr<ServiceWorkerRegistration> live_registration1 =
916 new ServiceWorkerRegistration(
917 kScope1, kRegistrationId1, context_ptr_);
918 scoped_refptr<ServiceWorkerVersion> live_version1 =
919 new ServiceWorkerVersion(
920 live_registration1.get(), kScript1, kVersionId1, context_ptr_);
921 live_version1->SetStatus(ServiceWorkerVersion::INSTALLED);
922 live_registration1->SetWaitingVersion(live_version1.get());
924 // Registration for "/scope/foo".
925 const GURL kScope2("http://www.example.com/scope/foo");
926 const GURL kScript2("http://www.example.com/script2.js");
927 const int64 kRegistrationId2 = 2;
928 const int64 kVersionId2 = 2;
929 scoped_refptr<ServiceWorkerRegistration> live_registration2 =
930 new ServiceWorkerRegistration(
931 kScope2, kRegistrationId2, context_ptr_);
932 scoped_refptr<ServiceWorkerVersion> live_version2 =
933 new ServiceWorkerVersion(
934 live_registration2.get(), kScript2, kVersionId2, context_ptr_);
935 live_version2->SetStatus(ServiceWorkerVersion::INSTALLED);
936 live_registration2->SetWaitingVersion(live_version2.get());
938 // Registration for "/scope/foobar".
939 const GURL kScope3("http://www.example.com/scope/foobar");
940 const GURL kScript3("http://www.example.com/script3.js");
941 const int64 kRegistrationId3 = 3;
942 const int64 kVersionId3 = 3;
943 scoped_refptr<ServiceWorkerRegistration> live_registration3 =
944 new ServiceWorkerRegistration(
945 kScope3, kRegistrationId3, context_ptr_);
946 scoped_refptr<ServiceWorkerVersion> live_version3 =
947 new ServiceWorkerVersion(
948 live_registration3.get(), kScript3, kVersionId3, context_ptr_);
949 live_version3->SetStatus(ServiceWorkerVersion::INSTALLED);
950 live_registration3->SetWaitingVersion(live_version3.get());
952 // Notify storage of they being installed.
953 storage()->NotifyInstallingRegistration(live_registration1.get());
954 storage()->NotifyInstallingRegistration(live_registration2.get());
955 storage()->NotifyInstallingRegistration(live_registration3.get());
957 // Find a registration among installing ones.
958 EXPECT_EQ(SERVICE_WORKER_OK,
959 FindRegistrationForDocument(kDocumentUrl, &found_registration));
960 EXPECT_EQ(live_registration2, found_registration);
961 found_registration = NULL;
963 // Store registrations.
964 EXPECT_EQ(SERVICE_WORKER_OK,
965 StoreRegistration(live_registration1, live_version1));
966 EXPECT_EQ(SERVICE_WORKER_OK,
967 StoreRegistration(live_registration2, live_version2));
968 EXPECT_EQ(SERVICE_WORKER_OK,
969 StoreRegistration(live_registration3, live_version3));
971 // Notify storage of installations no longer happening.
972 storage()->NotifyDoneInstallingRegistration(
973 live_registration1.get(), NULL, SERVICE_WORKER_OK);
974 storage()->NotifyDoneInstallingRegistration(
975 live_registration2.get(), NULL, SERVICE_WORKER_OK);
976 storage()->NotifyDoneInstallingRegistration(
977 live_registration3.get(), NULL, SERVICE_WORKER_OK);
979 // Find a registration among installed ones.
980 EXPECT_EQ(SERVICE_WORKER_OK,
981 FindRegistrationForDocument(kDocumentUrl, &found_registration));
982 EXPECT_EQ(live_registration2, found_registration);
985 TEST_F(ServiceWorkerStorageTest, CompareResources) {
986 // Compare two small responses containing the same data.
987 WriteBasicResponse(storage(), 1);
988 WriteBasicResponse(storage(), 2);
989 ServiceWorkerStatusCode status = static_cast<ServiceWorkerStatusCode>(-1);
990 bool are_equal = false;
991 storage()->CompareScriptResources(
992 1, 2,
993 base::Bind(&OnCompareComplete, &status, &are_equal));
994 base::RunLoop().RunUntilIdle();
995 EXPECT_EQ(SERVICE_WORKER_OK, status);
996 EXPECT_TRUE(are_equal);
998 // Compare two small responses with different data.
999 const char kHttpHeaders[] = "HTTP/1.0 200 HONKYDORY\0\0";
1000 const char kHttpBody[] = "Goodbye";
1001 std::string headers(kHttpHeaders, arraysize(kHttpHeaders));
1002 WriteStringResponse(storage(), 3, headers, std::string(kHttpBody));
1003 status = static_cast<ServiceWorkerStatusCode>(-1);
1004 are_equal = true;
1005 storage()->CompareScriptResources(
1006 1, 3,
1007 base::Bind(&OnCompareComplete, &status, &are_equal));
1008 base::RunLoop().RunUntilIdle();
1009 EXPECT_EQ(SERVICE_WORKER_OK, status);
1010 EXPECT_FALSE(are_equal);
1012 // Compare two large responses with the same data.
1013 const int k32K = 32 * 1024;
1014 WriteResponseOfSize(storage(), 4, 'a', k32K);
1015 WriteResponseOfSize(storage(), 5, 'a', k32K);
1016 status = static_cast<ServiceWorkerStatusCode>(-1);
1017 are_equal = false;
1018 storage()->CompareScriptResources(
1019 4, 5,
1020 base::Bind(&OnCompareComplete, &status, &are_equal));
1021 base::RunLoop().RunUntilIdle();
1022 EXPECT_EQ(SERVICE_WORKER_OK, status);
1023 EXPECT_TRUE(are_equal);
1025 // Compare a large and small response.
1026 status = static_cast<ServiceWorkerStatusCode>(-1);
1027 are_equal = true;
1028 storage()->CompareScriptResources(
1029 1, 5,
1030 base::Bind(&OnCompareComplete, &status, &are_equal));
1031 base::RunLoop().RunUntilIdle();
1032 EXPECT_EQ(SERVICE_WORKER_OK, status);
1033 EXPECT_FALSE(are_equal);
1035 // Compare two large responses with different data.
1036 WriteResponseOfSize(storage(), 6, 'b', k32K);
1037 status = static_cast<ServiceWorkerStatusCode>(-1);
1038 are_equal = true;
1039 storage()->CompareScriptResources(
1040 5, 6,
1041 base::Bind(&OnCompareComplete, &status, &are_equal));
1042 base::RunLoop().RunUntilIdle();
1043 EXPECT_EQ(SERVICE_WORKER_OK, status);
1044 EXPECT_FALSE(are_equal);
1047 } // namespace content