OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 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. |
| 4 |
| 5 #include "content/browser/service_worker/service_worker_disk_cache_migrator.h" |
| 6 |
| 7 #include "base/files/scoped_temp_dir.h" |
| 8 #include "base/run_loop.h" |
| 9 #include "base/thread_task_runner_handle.h" |
| 10 #include "content/public/test/test_browser_thread_bundle.h" |
| 11 #include "net/base/io_buffer.h" |
| 12 #include "net/base/net_errors.h" |
| 13 #include "net/base/test_completion_callback.h" |
| 14 #include "net/http/http_response_headers.h" |
| 15 #include "testing/gtest/include/gtest/gtest.h" |
| 16 |
| 17 namespace content { |
| 18 |
| 19 namespace { |
| 20 |
| 21 const int kMaxDiskCacheSize = 250 * 1024 * 1024; |
| 22 |
| 23 struct ResponseData { |
| 24 int64 resource_id; |
| 25 std::string headers; |
| 26 std::string body; |
| 27 std::string metadata; |
| 28 |
| 29 ResponseData(int64 resource_id, |
| 30 const std::string& headers, |
| 31 const std::string& body, |
| 32 const std::string& metadata) |
| 33 : resource_id(resource_id), |
| 34 headers(headers), |
| 35 body(body), |
| 36 metadata(metadata) {} |
| 37 }; |
| 38 |
| 39 void OnDiskCacheMigrated(const base::Closure& callback, |
| 40 ServiceWorkerStatusCode status) { |
| 41 EXPECT_EQ(SERVICE_WORKER_OK, status); |
| 42 callback.Run(); |
| 43 } |
| 44 |
| 45 } // namespace |
| 46 |
| 47 class ServiceWorkerDiskCacheMigratorTest : public testing::Test { |
| 48 public: |
| 49 ServiceWorkerDiskCacheMigratorTest() |
| 50 : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {} |
| 51 |
| 52 void SetUp() override { |
| 53 ASSERT_TRUE(user_data_directory_.CreateUniqueTempDir()); |
| 54 const base::FilePath kSrcDiskCachePath = |
| 55 user_data_directory_.path().AppendASCII("SrcCache"); |
| 56 const base::FilePath kDestDiskCachePath = |
| 57 user_data_directory_.path().AppendASCII("DestCache"); |
| 58 |
| 59 // Initialize the src BlockFile diskcache. |
| 60 src_ = ServiceWorkerDiskCache::CreateWithBlockFileBackend(); |
| 61 net::TestCompletionCallback cb1; |
| 62 src_->InitWithDiskBackend( |
| 63 kSrcDiskCachePath, kMaxDiskCacheSize, false /* force */, |
| 64 base::ThreadTaskRunnerHandle::Get(), cb1.callback()); |
| 65 ASSERT_EQ(net::OK, cb1.WaitForResult()); |
| 66 |
| 67 // Initialize the dest Simple diskcache. |
| 68 dest_ = ServiceWorkerDiskCache::CreateWithSimpleBackend(); |
| 69 net::TestCompletionCallback cb2; |
| 70 dest_->InitWithDiskBackend( |
| 71 kDestDiskCachePath, kMaxDiskCacheSize, false /* force */, |
| 72 base::ThreadTaskRunnerHandle::Get(), cb2.callback()); |
| 73 ASSERT_EQ(net::OK, cb2.WaitForResult()); |
| 74 |
| 75 migrator_.reset( |
| 76 new ServiceWorkerDiskCacheMigrator(src_.get(), dest_.get())); |
| 77 } |
| 78 |
| 79 bool WriteResponse(ServiceWorkerDiskCache* disk_cache, |
| 80 const ResponseData& response) { |
| 81 scoped_ptr<ServiceWorkerResponseWriter> writer( |
| 82 new ServiceWorkerResponseWriter(response.resource_id, disk_cache)); |
| 83 |
| 84 // Write the response info. |
| 85 scoped_ptr<net::HttpResponseInfo> info(new net::HttpResponseInfo); |
| 86 info->request_time = base::Time() + base::TimeDelta::FromSeconds(10); |
| 87 info->response_time = info->request_time + base::TimeDelta::FromSeconds(10); |
| 88 info->was_cached = false; |
| 89 info->headers = new net::HttpResponseHeaders(response.headers); |
| 90 scoped_refptr<HttpResponseInfoIOBuffer> info_buffer = |
| 91 new HttpResponseInfoIOBuffer(info.release()); |
| 92 net::TestCompletionCallback cb1; |
| 93 writer->WriteInfo(info_buffer.get(), cb1.callback()); |
| 94 int rv = cb1.WaitForResult(); |
| 95 EXPECT_LT(0, rv); |
| 96 if (rv < 0) |
| 97 return false; |
| 98 |
| 99 // Write the response metadata. |
| 100 scoped_ptr<ServiceWorkerResponseMetadataWriter> metadata_writer( |
| 101 new ServiceWorkerResponseMetadataWriter(response.resource_id, |
| 102 disk_cache)); |
| 103 scoped_refptr<net::IOBuffer> metadata_buffer( |
| 104 new net::WrappedIOBuffer(response.metadata.data())); |
| 105 const int metadata_length = response.metadata.length(); |
| 106 net::TestCompletionCallback cb2; |
| 107 metadata_writer->WriteMetadata(metadata_buffer.get(), metadata_length, |
| 108 cb2.callback()); |
| 109 rv = cb2.WaitForResult(); |
| 110 EXPECT_EQ(metadata_length, rv); |
| 111 if (metadata_length != rv) |
| 112 return false; |
| 113 |
| 114 // Write the response body. |
| 115 scoped_refptr<net::IOBuffer> body_buffer( |
| 116 new net::WrappedIOBuffer(response.body.data())); |
| 117 const int body_length = response.body.length(); |
| 118 net::TestCompletionCallback cb3; |
| 119 writer->WriteData(body_buffer.get(), body_length, cb3.callback()); |
| 120 rv = cb3.WaitForResult(); |
| 121 EXPECT_EQ(body_length, rv); |
| 122 if (body_length != rv) |
| 123 return false; |
| 124 |
| 125 return true; |
| 126 } |
| 127 |
| 128 void VerifyResponse(ServiceWorkerDiskCache* disk_cache, |
| 129 const ResponseData& expected) { |
| 130 scoped_ptr<ServiceWorkerResponseReader> reader( |
| 131 new ServiceWorkerResponseReader(expected.resource_id, disk_cache)); |
| 132 |
| 133 // Verify the response info. |
| 134 scoped_refptr<HttpResponseInfoIOBuffer> info_buffer = |
| 135 new HttpResponseInfoIOBuffer; |
| 136 net::TestCompletionCallback cb1; |
| 137 reader->ReadInfo(info_buffer.get(), cb1.callback()); |
| 138 int rv = cb1.WaitForResult(); |
| 139 EXPECT_LT(0, rv); |
| 140 EXPECT_EQ("OK", info_buffer->http_info->headers->GetStatusText()); |
| 141 |
| 142 // Verify the response metadata. |
| 143 if (!expected.metadata.empty()) { |
| 144 ASSERT_TRUE(info_buffer->http_info->metadata); |
| 145 const int data_size = info_buffer->http_info->metadata->size(); |
| 146 ASSERT_EQ(static_cast<int>(expected.metadata.length()), data_size); |
| 147 EXPECT_EQ(0, memcmp(expected.metadata.data(), |
| 148 info_buffer->http_info->metadata->data(), |
| 149 expected.metadata.length())); |
| 150 } |
| 151 |
| 152 // Verify the response body. |
| 153 const int kBigEnough = 512; |
| 154 scoped_refptr<net::IOBuffer> body_buffer = new net::IOBuffer(kBigEnough); |
| 155 net::TestCompletionCallback cb2; |
| 156 reader->ReadData(body_buffer.get(), kBigEnough, cb2.callback()); |
| 157 rv = cb2.WaitForResult(); |
| 158 ASSERT_EQ(static_cast<int>(expected.body.length()), rv); |
| 159 EXPECT_EQ(0, memcmp(expected.body.data(), body_buffer->data(), rv)); |
| 160 } |
| 161 |
| 162 void Migrate() { |
| 163 base::RunLoop run_loop; |
| 164 migrator_->Start(base::Bind(&OnDiskCacheMigrated, run_loop.QuitClosure())); |
| 165 run_loop.Run(); |
| 166 } |
| 167 |
| 168 int32 GetEntryCount(ServiceWorkerDiskCache* disk_cache) { |
| 169 return disk_cache->disk_cache()->GetEntryCount(); |
| 170 } |
| 171 |
| 172 void SetMaxNumberOfInflightTasks(size_t max_number) { |
| 173 migrator_->set_max_number_of_inflight_tasks(max_number); |
| 174 } |
| 175 |
| 176 protected: |
| 177 TestBrowserThreadBundle browser_thread_bundle_; |
| 178 base::ScopedTempDir user_data_directory_; |
| 179 scoped_ptr<ServiceWorkerDiskCache> src_; |
| 180 scoped_ptr<ServiceWorkerDiskCache> dest_; |
| 181 scoped_ptr<ServiceWorkerDiskCacheMigrator> migrator_; |
| 182 }; |
| 183 |
| 184 TEST_F(ServiceWorkerDiskCacheMigratorTest, Basic) { |
| 185 std::vector<ResponseData> responses; |
| 186 responses.push_back(ResponseData(1, "HTTP/1.1 200 OK\0\0", "Hello", "")); |
| 187 responses.push_back(ResponseData(2, "HTTP/1.1 200 OK\0\0", "Service", "")); |
| 188 responses.push_back(ResponseData(5, "HTTP/1.1 200 OK\0\0", "Worker", "")); |
| 189 responses.push_back(ResponseData(3, "HTTP/1.1 200 OK\0\0", "World", "meta")); |
| 190 responses.push_back(ResponseData(10, "HTTP/1.1 200 OK\0\0", "", "meta")); |
| 191 responses.push_back(ResponseData(11, "HTTP/1.1 200 OK\0\0", "body", "")); |
| 192 responses.push_back(ResponseData(12, "HTTP/1.1 200 OK\0\0", "", "")); |
| 193 responses.push_back(ResponseData( |
| 194 20, "HTTP/1.1 200 OK\0\0", std::string(256, 'a'), std::string(128, 'b'))); |
| 195 |
| 196 // Populate initial data in the src diskcache. |
| 197 for (const ResponseData& response : responses) { |
| 198 ASSERT_TRUE(WriteResponse(src_.get(), response)); |
| 199 VerifyResponse(src_.get(), response); |
| 200 } |
| 201 ASSERT_EQ(static_cast<int>(responses.size()), GetEntryCount(src_.get())); |
| 202 |
| 203 Migrate(); |
| 204 |
| 205 // Verify the migrated contents in the dest diskcache. |
| 206 for (const ResponseData& response : responses) |
| 207 VerifyResponse(dest_.get(), response); |
| 208 EXPECT_EQ(static_cast<int>(responses.size()), GetEntryCount(dest_.get())); |
| 209 } |
| 210 |
| 211 TEST_F(ServiceWorkerDiskCacheMigratorTest, MigrateEmptyDiskCache) { |
| 212 ASSERT_EQ(0, GetEntryCount(src_.get())); |
| 213 Migrate(); |
| 214 EXPECT_EQ(0, GetEntryCount(dest_.get())); |
| 215 } |
| 216 |
| 217 TEST_F(ServiceWorkerDiskCacheMigratorTest, ThrottleInflightTasks) { |
| 218 std::vector<ResponseData> responses; |
| 219 for (int i = 0; i < 10; ++i) |
| 220 responses.push_back(ResponseData(i, "HTTP/1.1 200 OK\0\0", "foo", "bar")); |
| 221 |
| 222 // Populate initial data in the src diskcache. |
| 223 for (const ResponseData& response : responses) { |
| 224 ASSERT_TRUE(WriteResponse(src_.get(), response)); |
| 225 VerifyResponse(src_.get(), response); |
| 226 } |
| 227 ASSERT_EQ(static_cast<int>(responses.size()), GetEntryCount(src_.get())); |
| 228 |
| 229 // Tighten the max number of inflight tasks. |
| 230 SetMaxNumberOfInflightTasks(2); |
| 231 |
| 232 // Migration should hit the limit, but should successfully complete. |
| 233 Migrate(); |
| 234 |
| 235 // Verify the migrated contents in the dest diskcache. |
| 236 for (const ResponseData& response : responses) |
| 237 VerifyResponse(dest_.get(), response); |
| 238 EXPECT_EQ(static_cast<int>(responses.size()), GetEntryCount(dest_.get())); |
| 239 } |
| 240 |
| 241 } // namespace content |
OLD | NEW |