OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/service_worker/service_worker_storage.h" | |
6 | |
7 #include "base/logging.h" | 5 #include "base/logging.h" |
8 #include "base/message_loop/message_loop.h" | 6 #include "base/message_loop/message_loop.h" |
9 #include "base/run_loop.h" | 7 #include "base/run_loop.h" |
10 #include "content/browser/browser_thread_impl.h" | 8 #include "content/browser/browser_thread_impl.h" |
11 #include "content/browser/service_worker/service_worker_context_core.h" | 9 #include "content/browser/service_worker/service_worker_context_core.h" |
10 #include "content/browser/service_worker/service_worker_disk_cache.h" | |
12 #include "content/browser/service_worker/service_worker_registration.h" | 11 #include "content/browser/service_worker/service_worker_registration.h" |
12 #include "content/browser/service_worker/service_worker_storage.h" | |
13 #include "content/browser/service_worker/service_worker_version.h" | 13 #include "content/browser/service_worker/service_worker_version.h" |
14 #include "content/public/test/test_browser_thread_bundle.h" | 14 #include "content/public/test/test_browser_thread_bundle.h" |
15 #include "net/base/io_buffer.h" | |
16 #include "net/base/net_errors.h" | |
17 #include "net/http/http_response_headers.h" | |
15 #include "testing/gtest/include/gtest/gtest.h" | 18 #include "testing/gtest/include/gtest/gtest.h" |
16 | 19 |
20 using net::IOBuffer; | |
21 using net::WrappedIOBuffer; | |
22 | |
17 namespace content { | 23 namespace content { |
18 | 24 |
19 namespace { | 25 namespace { |
20 | 26 |
27 typedef ServiceWorkerDatabase::RegistrationData RegistrationData; | |
28 typedef ServiceWorkerDatabase::ResourceRecord ResourceRecord; | |
29 | |
21 void StatusCallback(bool* was_called, | 30 void StatusCallback(bool* was_called, |
22 ServiceWorkerStatusCode* result, | 31 ServiceWorkerStatusCode* result, |
23 ServiceWorkerStatusCode status) { | 32 ServiceWorkerStatusCode status) { |
24 *was_called = true; | 33 *was_called = true; |
25 *result = status; | 34 *result = status; |
26 } | 35 } |
27 | 36 |
28 ServiceWorkerStorage::StatusCallback MakeStatusCallback( | 37 ServiceWorkerStorage::StatusCallback MakeStatusCallback( |
29 bool* was_called, | 38 bool* was_called, |
30 ServiceWorkerStatusCode* result) { | 39 ServiceWorkerStatusCode* result) { |
(...skipping 25 matching lines...) Expand all Loading... | |
56 *was_called = true; | 65 *was_called = true; |
57 *all_out = all; | 66 *all_out = all; |
58 } | 67 } |
59 | 68 |
60 ServiceWorkerStorage::GetAllRegistrationInfosCallback MakeGetAllCallback( | 69 ServiceWorkerStorage::GetAllRegistrationInfosCallback MakeGetAllCallback( |
61 bool* was_called, | 70 bool* was_called, |
62 std::vector<ServiceWorkerRegistrationInfo>* all) { | 71 std::vector<ServiceWorkerRegistrationInfo>* all) { |
63 return base::Bind(&GetAllCallback, was_called, all); | 72 return base::Bind(&GetAllCallback, was_called, all); |
64 } | 73 } |
65 | 74 |
75 void NoopCallback() { | |
nhiroki
2014/05/22 01:20:13
You may want to use DoNothing() in bind_helpers.h.
michaeln
2014/05/22 02:02:37
Done, ty!
| |
76 } | |
77 | |
78 void OnIOComplete(int* rv_out, int rv) { | |
79 *rv_out = rv; | |
80 } | |
81 | |
82 void WriteBasicResponse(ServiceWorkerStorage* storage, int64 id) { | |
83 scoped_ptr<ServiceWorkerResponseWriter> writer = | |
84 storage->CreateResponseWriter(id); | |
85 | |
86 const char kHttpHeaders[] = | |
87 "HTTP/1.0 200 HONKYDORY\0Content-Length: 6\0\0"; | |
88 const char kHttpBody[] = "Hello\0"; | |
89 scoped_refptr<IOBuffer> body(new WrappedIOBuffer(kHttpBody)); | |
90 std::string raw_headers(kHttpHeaders, arraysize(kHttpHeaders)); | |
91 scoped_ptr<net::HttpResponseInfo> info(new net::HttpResponseInfo); | |
92 info->request_time = base::Time::Now(); | |
93 info->response_time = base::Time::Now(); | |
94 info->was_cached = false; | |
95 info->headers = new net::HttpResponseHeaders(raw_headers); | |
96 scoped_refptr<HttpResponseInfoIOBuffer> info_buffer = | |
97 new HttpResponseInfoIOBuffer(info.release()); | |
98 | |
99 int rv = -1234; | |
100 writer->WriteInfo(info_buffer, base::Bind(&OnIOComplete, &rv)); | |
101 base::RunLoop().RunUntilIdle(); | |
102 EXPECT_LT(0, rv); | |
103 | |
104 rv = -1234; | |
105 writer->WriteData(body, arraysize(kHttpBody), | |
106 base::Bind(&OnIOComplete, &rv)); | |
nhiroki
2014/05/22 01:20:13
indent-nit.
michaeln
2014/05/22 02:02:37
Done.
| |
107 base::RunLoop().RunUntilIdle(); | |
108 EXPECT_EQ(arraysize(kHttpBody), rv); | |
109 } | |
110 | |
111 bool VerifyBasicResponse(ServiceWorkerStorage* storage, int64 id, | |
112 bool expected_positive_result) { | |
113 const char kExpectedHttpBody[] = "Hello\0"; | |
114 scoped_ptr<ServiceWorkerResponseReader> reader = | |
115 storage->CreateResponseReader(id); | |
116 scoped_refptr<HttpResponseInfoIOBuffer> info_buffer = | |
117 new HttpResponseInfoIOBuffer(); | |
118 int rv = -1234; | |
119 reader->ReadInfo(info_buffer, base::Bind(&OnIOComplete, &rv)); | |
120 base::RunLoop().RunUntilIdle(); | |
121 if (expected_positive_result) { | |
122 EXPECT_LT(0, rv); | |
123 } | |
nhiroki
2014/05/22 01:20:13
nit: you can remove "{}"
michaeln
2014/05/22 02:02:37
Done. (mysterious macro w/o brackets spooks me tho
nhiroki
2014/05/22 03:15:34
Ah... sorry, I unthoughtfully commented this after
| |
124 if (rv <= 0) | |
125 return false; | |
126 | |
127 const int kBigEnough = 512; | |
128 scoped_refptr<net::IOBuffer> buffer = new IOBuffer(kBigEnough); | |
129 rv = -1234; | |
130 reader->ReadData(buffer, kBigEnough, base::Bind(&OnIOComplete, &rv)); | |
131 base::RunLoop().RunUntilIdle(); | |
132 EXPECT_EQ(arraysize(kExpectedHttpBody), rv); | |
133 if (rv <= 0) | |
134 return false; | |
135 | |
136 bool status_match = | |
137 std::string("HONKYDORY") == | |
138 info_buffer->http_info->headers->GetStatusText(); | |
139 bool data_match = | |
140 std::string(kExpectedHttpBody) == std::string(buffer->data()); | |
141 | |
142 EXPECT_TRUE(status_match); | |
143 EXPECT_TRUE(data_match); | |
144 return status_match && data_match; | |
145 } | |
146 | |
66 } // namespace | 147 } // namespace |
67 | 148 |
68 class ServiceWorkerStorageTest : public testing::Test { | 149 class ServiceWorkerStorageTest : public testing::Test { |
69 public: | 150 public: |
70 ServiceWorkerStorageTest() | 151 ServiceWorkerStorageTest() |
71 : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) { | 152 : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) { |
72 } | 153 } |
73 | 154 |
74 virtual void SetUp() OVERRIDE { | 155 virtual void SetUp() OVERRIDE { |
75 context_.reset(new ServiceWorkerContextCore( | 156 context_.reset(new ServiceWorkerContextCore( |
76 base::FilePath(), | 157 base::FilePath(), |
77 base::MessageLoopProxy::current(), | 158 base::MessageLoopProxy::current(), |
78 base::MessageLoopProxy::current(), | 159 base::MessageLoopProxy::current(), |
79 NULL, | 160 NULL, |
80 NULL, | 161 NULL, |
81 scoped_ptr<ServiceWorkerProcessManager>())); | 162 scoped_ptr<ServiceWorkerProcessManager>())); |
82 context_ptr_ = context_->AsWeakPtr(); | 163 context_ptr_ = context_->AsWeakPtr(); |
83 } | 164 } |
84 | 165 |
85 virtual void TearDown() OVERRIDE { | 166 virtual void TearDown() OVERRIDE { |
86 context_.reset(); | 167 context_.reset(); |
87 } | 168 } |
88 | 169 |
89 ServiceWorkerStorage* storage() { return context_->storage(); } | 170 ServiceWorkerStorage* storage() { return context_->storage(); } |
90 | 171 |
172 // A static class method for friendliness. | |
173 static void VerifyPurgeableListStatusCallback( | |
174 ServiceWorkerDatabase* database, | |
175 std::set<int64> *purgeable_ids, | |
176 bool* was_called, | |
177 ServiceWorkerStatusCode* result, | |
178 ServiceWorkerStatusCode status) { | |
179 *was_called = true; | |
180 *result = status; | |
181 database->GetPurgeableResourceIds(purgeable_ids); | |
nhiroki
2014/05/22 01:20:13
Can you check a status code of GetPurgeableResourc
michaeln
2014/05/22 02:02:37
Done.
| |
182 } | |
183 | |
91 protected: | 184 protected: |
92 scoped_ptr<ServiceWorkerContextCore> context_; | 185 scoped_ptr<ServiceWorkerContextCore> context_; |
93 base::WeakPtr<ServiceWorkerContextCore> context_ptr_; | 186 base::WeakPtr<ServiceWorkerContextCore> context_ptr_; |
94 TestBrowserThreadBundle browser_thread_bundle_; | 187 TestBrowserThreadBundle browser_thread_bundle_; |
95 }; | 188 }; |
96 | 189 |
97 TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) { | 190 TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) { |
98 const GURL kScope("http://www.test.com/scope/*"); | 191 const GURL kScope("http://www.test.com/scope/*"); |
99 const GURL kScript("http://www.test.com/script.js"); | 192 const GURL kScript("http://www.test.com/script.js"); |
100 const GURL kDocumentUrl("http://www.test.com/scope/document.html"); | 193 const GURL kDocumentUrl("http://www.test.com/scope/document.html"); |
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
435 was_called = false; | 528 was_called = false; |
436 | 529 |
437 storage()->GetAllRegistrations( | 530 storage()->GetAllRegistrations( |
438 MakeGetAllCallback(&was_called, &all_registrations)); | 531 MakeGetAllCallback(&was_called, &all_registrations)); |
439 base::RunLoop().RunUntilIdle(); | 532 base::RunLoop().RunUntilIdle(); |
440 ASSERT_TRUE(was_called); | 533 ASSERT_TRUE(was_called); |
441 EXPECT_TRUE(all_registrations.empty()); | 534 EXPECT_TRUE(all_registrations.empty()); |
442 was_called = false; | 535 was_called = false; |
443 } | 536 } |
444 | 537 |
538 TEST_F(ServiceWorkerStorageTest, ResourceIdsAreStoredAndPurged) { | |
539 storage()->LazyInitialize(base::Bind(&NoopCallback)); | |
540 base::RunLoop().RunUntilIdle(); | |
541 const GURL kScope("http://www.test.com/scope/*"); | |
nhiroki
2014/05/22 01:20:13
"www.test.com" seems to be a domain for an actual
michaeln
2014/05/22 02:02:37
does it matter? no network traffic is generated by
nhiroki
2014/05/22 03:15:34
Yes, this doesn't generate any traffic.
Probably
| |
542 const GURL kScript("http://www.test.com/script.js"); | |
543 const GURL kImport("http://www.test.com/import.js"); | |
544 const GURL kDocumentUrl("http://www.test.com/scope/document.html"); | |
545 const int64 kRegistrationId = storage()->NewRegistrationId(); | |
546 const int64 kVersionId = storage()->NewVersionId(); | |
547 const int64 kResourceId1 = storage()->NewResourceId(); | |
548 const int64 kResourceId2 = storage()->NewResourceId(); | |
549 | |
550 // Cons up a new registration+version with two script resources. | |
551 RegistrationData data; | |
552 data.registration_id = kRegistrationId; | |
553 data.scope = kScope; | |
554 data.script = kScript; | |
555 data.version_id = kVersionId; | |
556 data.is_active = false; | |
557 std::vector<ResourceRecord> resources; | |
558 resources.push_back(ResourceRecord(kResourceId1, kScript)); | |
559 resources.push_back(ResourceRecord(kResourceId2, kImport)); | |
560 scoped_refptr<ServiceWorkerRegistration> registration = | |
561 storage()->GetOrCreateRegistration(data, resources); | |
562 registration->pending_version()->SetStatus(ServiceWorkerVersion::NEW); | |
563 | |
564 // Add the resources ids to the uncommitted list. | |
565 std::set<int64> resource_ids; | |
566 resource_ids.insert(kResourceId1); | |
567 resource_ids.insert(kResourceId2); | |
568 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, | |
569 storage()->database_->WriteUncommittedResourceIds(resource_ids)); | |
570 | |
571 // And dump something in the disk cache for them. | |
572 WriteBasicResponse(storage(), kResourceId1); | |
573 WriteBasicResponse(storage(), kResourceId2); | |
574 EXPECT_TRUE(VerifyBasicResponse(storage(), kResourceId1, true)); | |
575 EXPECT_TRUE(VerifyBasicResponse(storage(), kResourceId2, true)); | |
576 | |
577 // Storing the registration/version should take the resources ids out | |
578 // of the uncommitted list. | |
579 bool was_called = false; | |
580 ServiceWorkerStatusCode result = | |
581 ServiceWorkerStatusCode::SERVICE_WORKER_ERROR_FAILED; | |
582 storage()->StoreRegistration(registration, registration->pending_version(), | |
583 MakeStatusCallback(&was_called, &result)); | |
584 base::RunLoop().RunUntilIdle(); | |
585 ASSERT_TRUE(was_called); | |
586 EXPECT_EQ(ServiceWorkerStatusCode::SERVICE_WORKER_OK, result); | |
587 std::set<int64> verify_ids; | |
588 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, | |
589 storage()->database_->GetUncommittedResourceIds(&verify_ids)); | |
590 EXPECT_TRUE(verify_ids.empty()); | |
591 | |
592 // Deleting it should result in the resources being added to the | |
593 // purgable list and then doomed in the disk cache and removed from | |
nhiroki
2014/05/22 01:20:13
nit: s/purgable/purgeable/
michaeln
2014/05/22 02:02:37
Done.
| |
594 // that list. | |
595 was_called = false; | |
596 verify_ids.clear(); | |
597 storage()->DeleteRegistration( | |
598 registration->id(), kScope.GetOrigin(), | |
599 base::Bind(&VerifyPurgeableListStatusCallback, | |
600 base::Unretained(storage()->database_.get()), | |
601 &verify_ids, | |
602 &was_called, &result)); | |
nhiroki
2014/05/22 01:20:13
indent-nit.
michaeln
2014/05/22 02:02:37
Done.
| |
603 base::RunLoop().RunUntilIdle(); | |
604 ASSERT_TRUE(was_called); | |
605 EXPECT_EQ(ServiceWorkerStatusCode::SERVICE_WORKER_OK, result); | |
606 EXPECT_EQ(2u, verify_ids.size()); | |
607 verify_ids.clear(); | |
608 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, | |
609 storage()->database_->GetPurgeableResourceIds(&verify_ids)); | |
610 EXPECT_TRUE(verify_ids.empty()); | |
611 | |
612 EXPECT_FALSE(VerifyBasicResponse(storage(), kResourceId1, false)); | |
613 EXPECT_FALSE(VerifyBasicResponse(storage(), kResourceId2, false)); | |
614 } | |
615 | |
445 } // namespace content | 616 } // namespace content |
OLD | NEW |