[refactor] More post-NSS WebCrypto cleanups (utility functions).
[chromium-blink-merge.git] / content / browser / cache_storage / cache_storage_cache_unittest.cc
blob88363a7c4d910dc55512b8ad02fd2a51723b6de4
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/cache_storage/cache_storage_cache.h"
7 #include "base/files/file_path.h"
8 #include "base/files/scoped_temp_dir.h"
9 #include "base/memory/ref_counted.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/run_loop.h"
12 #include "base/strings/string_split.h"
13 #include "base/thread_task_runner_handle.h"
14 #include "content/browser/fileapi/chrome_blob_storage_context.h"
15 #include "content/browser/fileapi/mock_url_request_delegate.h"
16 #include "content/browser/quota/mock_quota_manager_proxy.h"
17 #include "content/common/cache_storage/cache_storage_types.h"
18 #include "content/common/service_worker/service_worker_types.h"
19 #include "content/public/browser/browser_thread.h"
20 #include "content/public/common/referrer.h"
21 #include "content/public/test/test_browser_context.h"
22 #include "content/public/test/test_browser_thread_bundle.h"
23 #include "net/base/test_completion_callback.h"
24 #include "net/url_request/url_request_context.h"
25 #include "net/url_request/url_request_context_getter.h"
26 #include "net/url_request/url_request_job_factory_impl.h"
27 #include "storage/browser/blob/blob_data_builder.h"
28 #include "storage/browser/blob/blob_data_handle.h"
29 #include "storage/browser/blob/blob_data_snapshot.h"
30 #include "storage/browser/blob/blob_storage_context.h"
31 #include "storage/browser/blob/blob_url_request_job_factory.h"
32 #include "storage/browser/quota/quota_manager_proxy.h"
33 #include "testing/gtest/include/gtest/gtest.h"
35 namespace content {
37 namespace {
38 const char kTestData[] = "Hello World";
40 // Returns a BlobProtocolHandler that uses |blob_storage_context|. Caller owns
41 // the memory.
42 scoped_ptr<storage::BlobProtocolHandler> CreateMockBlobProtocolHandler(
43 storage::BlobStorageContext* blob_storage_context) {
44 // The FileSystemContext and thread task runner are not actually used but a
45 // task runner is needed to avoid a DCHECK in BlobURLRequestJob ctor.
46 return make_scoped_ptr(new storage::BlobProtocolHandler(
47 blob_storage_context, NULL, base::ThreadTaskRunnerHandle::Get().get()));
50 // A disk_cache::Backend wrapper that can delay operations.
51 class DelayableBackend : public disk_cache::Backend {
52 public:
53 DelayableBackend(scoped_ptr<disk_cache::Backend> backend)
54 : backend_(backend.Pass()), delay_open_(false) {}
56 // disk_cache::Backend overrides
57 net::CacheType GetCacheType() const override {
58 return backend_->GetCacheType();
60 int32 GetEntryCount() const override { return backend_->GetEntryCount(); }
61 int OpenEntry(const std::string& key,
62 disk_cache::Entry** entry,
63 const CompletionCallback& callback) override {
64 if (delay_open_) {
65 open_entry_callback_ =
66 base::Bind(&DelayableBackend::OpenEntryDelayedImpl,
67 base::Unretained(this), key, entry, callback);
68 return net::ERR_IO_PENDING;
71 return backend_->OpenEntry(key, entry, callback);
73 int CreateEntry(const std::string& key,
74 disk_cache::Entry** entry,
75 const CompletionCallback& callback) override {
76 return backend_->CreateEntry(key, entry, callback);
78 int DoomEntry(const std::string& key,
79 const CompletionCallback& callback) override {
80 return backend_->DoomEntry(key, callback);
82 int DoomAllEntries(const CompletionCallback& callback) override {
83 return backend_->DoomAllEntries(callback);
85 int DoomEntriesBetween(base::Time initial_time,
86 base::Time end_time,
87 const CompletionCallback& callback) override {
88 return backend_->DoomEntriesBetween(initial_time, end_time, callback);
90 int DoomEntriesSince(base::Time initial_time,
91 const CompletionCallback& callback) override {
92 return backend_->DoomEntriesSince(initial_time, callback);
94 scoped_ptr<Iterator> CreateIterator() override {
95 return backend_->CreateIterator();
97 void GetStats(base::StringPairs* stats) override {
98 return backend_->GetStats(stats);
100 void OnExternalCacheHit(const std::string& key) override {
101 return backend_->OnExternalCacheHit(key);
104 // Call to continue a delayed open.
105 void OpenEntryContinue() {
106 EXPECT_FALSE(open_entry_callback_.is_null());
107 open_entry_callback_.Run();
110 void set_delay_open(bool value) { delay_open_ = value; }
112 private:
113 void OpenEntryDelayedImpl(const std::string& key,
114 disk_cache::Entry** entry,
115 const CompletionCallback& callback) {
116 int rv = backend_->OpenEntry(key, entry, callback);
117 if (rv != net::ERR_IO_PENDING)
118 callback.Run(rv);
121 scoped_ptr<disk_cache::Backend> backend_;
122 bool delay_open_;
123 base::Closure open_entry_callback_;
126 void CopyBody(const storage::BlobDataHandle& blob_handle, std::string* output) {
127 *output = std::string();
128 scoped_ptr<storage::BlobDataSnapshot> data = blob_handle.CreateSnapshot();
129 const auto& items = data->items();
130 for (const auto& item : items) {
131 switch (item->type()) {
132 case storage::DataElement::TYPE_BYTES: {
133 output->append(item->bytes(), item->length());
134 break;
136 case storage::DataElement::TYPE_DISK_CACHE_ENTRY: {
137 disk_cache::Entry* entry = item->disk_cache_entry();
138 int32 body_size = entry->GetDataSize(item->disk_cache_stream_index());
140 scoped_refptr<net::IOBuffer> io_buffer = new net::IOBuffer(body_size);
141 net::TestCompletionCallback callback;
142 int rv =
143 entry->ReadData(item->disk_cache_stream_index(), 0, io_buffer.get(),
144 body_size, callback.callback());
145 if (rv == net::ERR_IO_PENDING)
146 rv = callback.WaitForResult();
147 EXPECT_EQ(body_size, rv);
148 if (rv > 0)
149 output->append(io_buffer->data(), rv);
150 break;
152 default: { ADD_FAILURE() << "invalid response blob type"; } break;
157 bool ResponseMetadataEqual(const ServiceWorkerResponse& expected,
158 const ServiceWorkerResponse& actual) {
159 EXPECT_EQ(expected.status_code, actual.status_code);
160 if (expected.status_code != actual.status_code)
161 return false;
162 EXPECT_EQ(expected.status_text, actual.status_text);
163 if (expected.status_text != actual.status_text)
164 return false;
165 EXPECT_EQ(expected.url, actual.url);
166 if (expected.url != actual.url)
167 return false;
168 EXPECT_EQ(expected.blob_size, actual.blob_size);
169 if (expected.blob_size != actual.blob_size)
170 return false;
172 if (expected.blob_size == 0) {
173 EXPECT_STREQ("", actual.blob_uuid.c_str());
174 if (!actual.blob_uuid.empty())
175 return false;
176 } else {
177 EXPECT_STRNE("", actual.blob_uuid.c_str());
178 if (actual.blob_uuid.empty())
179 return false;
182 return true;
185 bool ResponseBodiesEqual(const std::string& expected_body,
186 const storage::BlobDataHandle& actual_body_handle) {
187 std::string actual_body;
188 CopyBody(actual_body_handle, &actual_body);
189 return expected_body == actual_body;
192 } // namespace
194 // A CacheStorageCache that can optionally delay during backend creation.
195 class TestCacheStorageCache : public CacheStorageCache {
196 public:
197 TestCacheStorageCache(
198 const GURL& origin,
199 const base::FilePath& path,
200 const scoped_refptr<net::URLRequestContextGetter>& request_context_getter,
201 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
202 base::WeakPtr<storage::BlobStorageContext> blob_context)
203 : CacheStorageCache(origin,
204 path,
205 request_context_getter,
206 quota_manager_proxy,
207 blob_context),
208 delay_backend_creation_(false) {}
210 void CreateBackend(const ErrorCallback& callback) override {
211 backend_creation_callback_ = callback;
212 if (delay_backend_creation_)
213 return;
214 ContinueCreateBackend();
217 void ContinueCreateBackend() {
218 CacheStorageCache::CreateBackend(backend_creation_callback_);
221 void set_delay_backend_creation(bool delay) {
222 delay_backend_creation_ = delay;
225 // Swap the existing backend with a delayable one. The backend must have been
226 // created before calling this.
227 DelayableBackend* UseDelayableBackend() {
228 EXPECT_TRUE(backend_);
229 DelayableBackend* delayable_backend = new DelayableBackend(backend_.Pass());
230 backend_.reset(delayable_backend);
231 return delayable_backend;
234 private:
235 ~TestCacheStorageCache() override {}
237 bool delay_backend_creation_;
238 ErrorCallback backend_creation_callback_;
240 DISALLOW_COPY_AND_ASSIGN(TestCacheStorageCache);
243 class CacheStorageCacheTest : public testing::Test {
244 public:
245 CacheStorageCacheTest()
246 : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
247 callback_error_(CACHE_STORAGE_OK),
248 callback_closed_(false) {}
250 void SetUp() override {
251 ChromeBlobStorageContext* blob_storage_context =
252 ChromeBlobStorageContext::GetFor(&browser_context_);
253 // Wait for chrome_blob_storage_context to finish initializing.
254 base::RunLoop().RunUntilIdle();
255 blob_storage_context_ = blob_storage_context->context();
257 quota_manager_proxy_ = new MockQuotaManagerProxy(
258 nullptr, base::ThreadTaskRunnerHandle::Get().get());
260 url_request_job_factory_.reset(new net::URLRequestJobFactoryImpl);
261 url_request_job_factory_->SetProtocolHandler(
262 "blob", CreateMockBlobProtocolHandler(blob_storage_context->context()));
264 net::URLRequestContext* url_request_context =
265 browser_context_.GetRequestContext()->GetURLRequestContext();
267 url_request_context->set_job_factory(url_request_job_factory_.get());
269 CreateRequests(blob_storage_context);
271 if (!MemoryOnly())
272 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
273 base::FilePath path = MemoryOnly() ? base::FilePath() : temp_dir_.path();
275 cache_ = make_scoped_refptr(new TestCacheStorageCache(
276 GURL("http://example.com"), path, browser_context_.GetRequestContext(),
277 quota_manager_proxy_, blob_storage_context->context()->AsWeakPtr()));
280 void TearDown() override {
281 quota_manager_proxy_->SimulateQuotaManagerDestroyed();
282 base::RunLoop().RunUntilIdle();
285 void CreateRequests(ChromeBlobStorageContext* blob_storage_context) {
286 ServiceWorkerHeaderMap headers;
287 headers.insert(std::make_pair("a", "a"));
288 headers.insert(std::make_pair("b", "b"));
289 body_request_ =
290 ServiceWorkerFetchRequest(GURL("http://example.com/body.html"), "GET",
291 headers, Referrer(), false);
292 no_body_request_ =
293 ServiceWorkerFetchRequest(GURL("http://example.com/no_body.html"),
294 "GET", headers, Referrer(), false);
296 std::string expected_response;
297 for (int i = 0; i < 100; ++i)
298 expected_blob_data_ += kTestData;
300 scoped_ptr<storage::BlobDataBuilder> blob_data(
301 new storage::BlobDataBuilder("blob-id:myblob"));
302 blob_data->AppendData(expected_blob_data_);
304 blob_handle_ =
305 blob_storage_context->context()->AddFinishedBlob(blob_data.get());
307 body_response_ = ServiceWorkerResponse(
308 GURL("http://example.com/body.html"), 200, "OK",
309 blink::WebServiceWorkerResponseTypeDefault, headers,
310 blob_handle_->uuid(), expected_blob_data_.size(), GURL(),
311 blink::WebServiceWorkerResponseErrorUnknown);
313 no_body_response_ = ServiceWorkerResponse(
314 GURL("http://example.com/no_body.html"), 200, "OK",
315 blink::WebServiceWorkerResponseTypeDefault, headers, "", 0, GURL(),
316 blink::WebServiceWorkerResponseErrorUnknown);
319 scoped_ptr<ServiceWorkerFetchRequest> CopyFetchRequest(
320 const ServiceWorkerFetchRequest& request) {
321 return make_scoped_ptr(new ServiceWorkerFetchRequest(
322 request.url, request.method, request.headers, request.referrer,
323 request.is_reload));
326 CacheStorageError BatchOperation(
327 const std::vector<CacheStorageBatchOperation>& operations) {
328 scoped_ptr<base::RunLoop> loop(new base::RunLoop());
330 cache_->BatchOperation(
331 operations,
332 base::Bind(&CacheStorageCacheTest::ErrorTypeCallback,
333 base::Unretained(this), base::Unretained(loop.get())));
334 // TODO(jkarlin): These functions should use base::RunLoop().RunUntilIdle()
335 // once the cache uses a passed in task runner instead of the CACHE thread.
336 loop->Run();
338 return callback_error_;
341 bool Put(const ServiceWorkerFetchRequest& request,
342 const ServiceWorkerResponse& response) {
343 CacheStorageBatchOperation operation;
344 operation.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT;
345 operation.request = request;
346 operation.response = response;
348 CacheStorageError error =
349 BatchOperation(std::vector<CacheStorageBatchOperation>(1, operation));
350 return error == CACHE_STORAGE_OK;
353 bool Match(const ServiceWorkerFetchRequest& request) {
354 scoped_ptr<base::RunLoop> loop(new base::RunLoop());
356 cache_->Match(
357 CopyFetchRequest(request),
358 base::Bind(&CacheStorageCacheTest::ResponseAndErrorCallback,
359 base::Unretained(this), base::Unretained(loop.get())));
360 loop->Run();
362 return callback_error_ == CACHE_STORAGE_OK;
365 bool MatchAll(scoped_ptr<CacheStorageCache::Responses>* responses,
366 scoped_ptr<CacheStorageCache::BlobDataHandles>* body_handles) {
367 base::RunLoop loop;
368 cache_->MatchAll(base::Bind(
369 &CacheStorageCacheTest::ResponsesAndErrorCallback,
370 base::Unretained(this), loop.QuitClosure(), responses, body_handles));
371 loop.Run();
372 return callback_error_ == CACHE_STORAGE_OK;
375 bool Delete(const ServiceWorkerFetchRequest& request) {
376 CacheStorageBatchOperation operation;
377 operation.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_DELETE;
378 operation.request = request;
380 CacheStorageError error =
381 BatchOperation(std::vector<CacheStorageBatchOperation>(1, operation));
382 return error == CACHE_STORAGE_OK;
385 bool Keys() {
386 scoped_ptr<base::RunLoop> loop(new base::RunLoop());
388 cache_->Keys(base::Bind(&CacheStorageCacheTest::RequestsCallback,
389 base::Unretained(this),
390 base::Unretained(loop.get())));
391 loop->Run();
393 return callback_error_ == CACHE_STORAGE_OK;
396 bool Close() {
397 scoped_ptr<base::RunLoop> loop(new base::RunLoop());
399 cache_->Close(base::Bind(&CacheStorageCacheTest::CloseCallback,
400 base::Unretained(this),
401 base::Unretained(loop.get())));
402 loop->Run();
403 return callback_closed_;
406 void RequestsCallback(base::RunLoop* run_loop,
407 CacheStorageError error,
408 scoped_ptr<CacheStorageCache::Requests> requests) {
409 callback_error_ = error;
410 callback_strings_.clear();
411 if (requests) {
412 for (size_t i = 0u; i < requests->size(); ++i)
413 callback_strings_.push_back(requests->at(i).url.spec());
415 if (run_loop)
416 run_loop->Quit();
419 void ErrorTypeCallback(base::RunLoop* run_loop, CacheStorageError error) {
420 callback_error_ = error;
421 if (run_loop)
422 run_loop->Quit();
425 void SequenceCallback(int sequence,
426 int* sequence_out,
427 base::RunLoop* run_loop,
428 CacheStorageError error) {
429 *sequence_out = sequence;
430 callback_error_ = error;
431 if (run_loop)
432 run_loop->Quit();
435 void ResponseAndErrorCallback(
436 base::RunLoop* run_loop,
437 CacheStorageError error,
438 scoped_ptr<ServiceWorkerResponse> response,
439 scoped_ptr<storage::BlobDataHandle> body_handle) {
440 callback_error_ = error;
441 callback_response_ = response.Pass();
442 callback_response_data_.reset();
443 if (error == CACHE_STORAGE_OK && !callback_response_->blob_uuid.empty())
444 callback_response_data_ = body_handle.Pass();
446 if (run_loop)
447 run_loop->Quit();
450 void ResponsesAndErrorCallback(
451 const base::Closure& quit_closure,
452 scoped_ptr<CacheStorageCache::Responses>* responses_out,
453 scoped_ptr<CacheStorageCache::BlobDataHandles>* body_handles_out,
454 CacheStorageError error,
455 scoped_ptr<CacheStorageCache::Responses> responses,
456 scoped_ptr<CacheStorageCache::BlobDataHandles> body_handles) {
457 callback_error_ = error;
458 responses_out->swap(responses);
459 body_handles_out->swap(body_handles);
460 quit_closure.Run();
463 void CloseCallback(base::RunLoop* run_loop) {
464 EXPECT_FALSE(callback_closed_);
465 callback_closed_ = true;
466 if (run_loop)
467 run_loop->Quit();
470 bool VerifyKeys(const std::vector<std::string>& expected_keys) {
471 if (expected_keys.size() != callback_strings_.size())
472 return false;
474 std::set<std::string> found_set;
475 for (int i = 0, max = callback_strings_.size(); i < max; ++i)
476 found_set.insert(callback_strings_[i]);
478 for (int i = 0, max = expected_keys.size(); i < max; ++i) {
479 if (found_set.find(expected_keys[i]) == found_set.end())
480 return false;
482 return true;
485 bool TestResponseType(blink::WebServiceWorkerResponseType response_type) {
486 body_response_.response_type = response_type;
487 EXPECT_TRUE(Put(body_request_, body_response_));
488 EXPECT_TRUE(Match(body_request_));
489 EXPECT_TRUE(Delete(body_request_));
490 return response_type == callback_response_->response_type;
493 void VerifyAllOpsFail() {
494 EXPECT_FALSE(Put(no_body_request_, no_body_response_));
495 EXPECT_FALSE(Match(no_body_request_));
496 EXPECT_FALSE(Delete(body_request_));
497 EXPECT_FALSE(Keys());
500 virtual bool MemoryOnly() { return false; }
502 protected:
503 TestBrowserContext browser_context_;
504 TestBrowserThreadBundle browser_thread_bundle_;
505 scoped_ptr<net::URLRequestJobFactoryImpl> url_request_job_factory_;
506 scoped_refptr<MockQuotaManagerProxy> quota_manager_proxy_;
507 storage::BlobStorageContext* blob_storage_context_;
509 base::ScopedTempDir temp_dir_;
510 scoped_refptr<TestCacheStorageCache> cache_;
512 ServiceWorkerFetchRequest body_request_;
513 ServiceWorkerResponse body_response_;
514 ServiceWorkerFetchRequest no_body_request_;
515 ServiceWorkerResponse no_body_response_;
516 scoped_ptr<storage::BlobDataHandle> blob_handle_;
517 std::string expected_blob_data_;
519 CacheStorageError callback_error_;
520 scoped_ptr<ServiceWorkerResponse> callback_response_;
521 scoped_ptr<storage::BlobDataHandle> callback_response_data_;
522 std::vector<std::string> callback_strings_;
523 bool callback_closed_;
526 class CacheStorageCacheTestP : public CacheStorageCacheTest,
527 public testing::WithParamInterface<bool> {
528 bool MemoryOnly() override { return !GetParam(); }
531 class CacheStorageCacheMemoryOnlyTest
532 : public CacheStorageCacheTest,
533 public testing::WithParamInterface<bool> {
534 bool MemoryOnly() override { return true; }
537 TEST_P(CacheStorageCacheTestP, PutNoBody) {
538 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
541 TEST_P(CacheStorageCacheTestP, PutBody) {
542 EXPECT_TRUE(Put(body_request_, body_response_));
545 TEST_P(CacheStorageCacheTestP, PutBody_Multiple) {
546 CacheStorageBatchOperation operation1;
547 operation1.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT;
548 operation1.request = body_request_;
549 operation1.request.url = GURL("http://example.com/1");
550 operation1.response = body_response_;
551 operation1.response.url = GURL("http://example.com/1");
553 CacheStorageBatchOperation operation2;
554 operation2.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT;
555 operation2.request = body_request_;
556 operation2.request.url = GURL("http://example.com/2");
557 operation2.response = body_response_;
558 operation2.response.url = GURL("http://example.com/2");
560 CacheStorageBatchOperation operation3;
561 operation3.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT;
562 operation3.request = body_request_;
563 operation3.request.url = GURL("http://example.com/3");
564 operation3.response = body_response_;
565 operation3.response.url = GURL("http://example.com/3");
567 std::vector<CacheStorageBatchOperation> operations;
568 operations.push_back(operation1);
569 operations.push_back(operation2);
570 operations.push_back(operation3);
572 EXPECT_EQ(CACHE_STORAGE_OK, BatchOperation(operations));
573 EXPECT_TRUE(Match(operation1.request));
574 EXPECT_TRUE(Match(operation2.request));
575 EXPECT_TRUE(Match(operation3.request));
578 // TODO(nhiroki): Add a test for the case where one of PUT operations fails.
579 // Currently there is no handy way to fail only one operation in a batch.
580 // This could be easily achieved after adding some security checks in the
581 // browser side (http://crbug.com/425505).
583 TEST_P(CacheStorageCacheTestP, ResponseURLDiffersFromRequestURL) {
584 no_body_response_.url = GURL("http://example.com/foobar");
585 EXPECT_STRNE("http://example.com/foobar",
586 no_body_request_.url.spec().c_str());
587 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
588 EXPECT_TRUE(Match(no_body_request_));
589 EXPECT_STREQ("http://example.com/foobar",
590 callback_response_->url.spec().c_str());
593 TEST_P(CacheStorageCacheTestP, ResponseURLEmpty) {
594 no_body_response_.url = GURL();
595 EXPECT_STRNE("", no_body_request_.url.spec().c_str());
596 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
597 EXPECT_TRUE(Match(no_body_request_));
598 EXPECT_STREQ("", callback_response_->url.spec().c_str());
601 TEST_F(CacheStorageCacheTest, PutBodyDropBlobRef) {
602 CacheStorageBatchOperation operation;
603 operation.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT;
604 operation.request = body_request_;
605 operation.response = body_response_;
607 scoped_ptr<base::RunLoop> loop(new base::RunLoop());
608 cache_->BatchOperation(
609 std::vector<CacheStorageBatchOperation>(1, operation),
610 base::Bind(&CacheStorageCacheTestP::ErrorTypeCallback,
611 base::Unretained(this), base::Unretained(loop.get())));
612 // The handle should be held by the cache now so the deref here should be
613 // okay.
614 blob_handle_.reset();
615 loop->Run();
617 EXPECT_EQ(CACHE_STORAGE_OK, callback_error_);
620 TEST_P(CacheStorageCacheTestP, PutReplace) {
621 EXPECT_TRUE(Put(body_request_, no_body_response_));
622 EXPECT_TRUE(Match(body_request_));
623 EXPECT_FALSE(callback_response_data_);
625 EXPECT_TRUE(Put(body_request_, body_response_));
626 EXPECT_TRUE(Match(body_request_));
627 EXPECT_TRUE(callback_response_data_);
629 EXPECT_TRUE(Put(body_request_, no_body_response_));
630 EXPECT_TRUE(Match(body_request_));
631 EXPECT_FALSE(callback_response_data_);
634 TEST_P(CacheStorageCacheTestP, PutReplcaceInBatch) {
635 CacheStorageBatchOperation operation1;
636 operation1.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT;
637 operation1.request = body_request_;
638 operation1.response = no_body_response_;
640 CacheStorageBatchOperation operation2;
641 operation2.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT;
642 operation2.request = body_request_;
643 operation2.response = body_response_;
645 std::vector<CacheStorageBatchOperation> operations;
646 operations.push_back(operation1);
647 operations.push_back(operation2);
649 EXPECT_EQ(CACHE_STORAGE_OK, BatchOperation(operations));
651 // |operation2| should win.
652 EXPECT_TRUE(Match(operation2.request));
653 EXPECT_TRUE(callback_response_data_);
656 TEST_P(CacheStorageCacheTestP, MatchNoBody) {
657 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
658 EXPECT_TRUE(Match(no_body_request_));
659 EXPECT_TRUE(ResponseMetadataEqual(no_body_response_, *callback_response_));
660 EXPECT_FALSE(callback_response_data_);
663 TEST_P(CacheStorageCacheTestP, MatchBody) {
664 EXPECT_TRUE(Put(body_request_, body_response_));
665 EXPECT_TRUE(Match(body_request_));
666 EXPECT_TRUE(ResponseMetadataEqual(body_response_, *callback_response_));
667 EXPECT_TRUE(
668 ResponseBodiesEqual(expected_blob_data_, *callback_response_data_));
671 TEST_P(CacheStorageCacheTestP, MatchAll_Empty) {
672 scoped_ptr<CacheStorageCache::Responses> responses;
673 scoped_ptr<CacheStorageCache::BlobDataHandles> body_handles;
674 EXPECT_TRUE(MatchAll(&responses, &body_handles));
675 EXPECT_TRUE(responses->empty());
676 EXPECT_TRUE(body_handles->empty());
679 TEST_P(CacheStorageCacheTestP, MatchAll_NoBody) {
680 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
682 scoped_ptr<CacheStorageCache::Responses> responses;
683 scoped_ptr<CacheStorageCache::BlobDataHandles> body_handles;
684 EXPECT_TRUE(MatchAll(&responses, &body_handles));
686 ASSERT_EQ(1u, responses->size());
687 EXPECT_TRUE(ResponseMetadataEqual(no_body_response_, responses->at(0)));
688 EXPECT_TRUE(body_handles->empty());
691 TEST_P(CacheStorageCacheTestP, MatchAll_Body) {
692 EXPECT_TRUE(Put(body_request_, body_response_));
694 scoped_ptr<CacheStorageCache::Responses> responses;
695 scoped_ptr<CacheStorageCache::BlobDataHandles> body_handles;
696 EXPECT_TRUE(MatchAll(&responses, &body_handles));
698 ASSERT_EQ(1u, responses->size());
699 ASSERT_EQ(1u, body_handles->size());
700 EXPECT_TRUE(ResponseMetadataEqual(body_response_, responses->at(0)));
701 EXPECT_TRUE(ResponseBodiesEqual(expected_blob_data_, body_handles->at(0)));
704 TEST_P(CacheStorageCacheTestP, MatchAll_TwoResponsesThenOne) {
705 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
706 EXPECT_TRUE(Put(body_request_, body_response_));
708 scoped_ptr<CacheStorageCache::Responses> responses;
709 scoped_ptr<CacheStorageCache::BlobDataHandles> body_handles;
710 EXPECT_TRUE(MatchAll(&responses, &body_handles));
711 ASSERT_EQ(2u, responses->size());
712 ASSERT_EQ(1u, body_handles->size());
714 // Order of returned responses is not guaranteed.
715 std::set<std::string> matched_set;
716 for (const ServiceWorkerResponse& response : *responses) {
717 if (response.url.spec() == "http://example.com/no_body.html") {
718 EXPECT_TRUE(ResponseMetadataEqual(no_body_response_, response));
719 matched_set.insert(response.url.spec());
720 } else if (response.url.spec() == "http://example.com/body.html") {
721 EXPECT_TRUE(ResponseMetadataEqual(body_response_, response));
722 EXPECT_TRUE(
723 ResponseBodiesEqual(expected_blob_data_, body_handles->at(0)));
724 matched_set.insert(response.url.spec());
727 EXPECT_EQ(2u, matched_set.size());
729 responses->clear();
730 body_handles->clear();
732 EXPECT_TRUE(Delete(body_request_));
733 EXPECT_TRUE(MatchAll(&responses, &body_handles));
735 ASSERT_EQ(1u, responses->size());
736 EXPECT_TRUE(ResponseMetadataEqual(no_body_response_, responses->at(0)));
737 EXPECT_TRUE(body_handles->empty());
740 TEST_P(CacheStorageCacheTestP, Vary) {
741 body_request_.headers["vary_foo"] = "foo";
742 body_response_.headers["vary"] = "vary_foo";
743 EXPECT_TRUE(Put(body_request_, body_response_));
744 EXPECT_TRUE(Match(body_request_));
746 body_request_.headers["vary_foo"] = "bar";
747 EXPECT_FALSE(Match(body_request_));
749 body_request_.headers.erase("vary_foo");
750 EXPECT_FALSE(Match(body_request_));
753 TEST_P(CacheStorageCacheTestP, EmptyVary) {
754 body_response_.headers["vary"] = "";
755 EXPECT_TRUE(Put(body_request_, body_response_));
756 EXPECT_TRUE(Match(body_request_));
758 body_request_.headers["zoo"] = "zoo";
759 EXPECT_TRUE(Match(body_request_));
762 TEST_P(CacheStorageCacheTestP, NoVaryButDiffHeaders) {
763 EXPECT_TRUE(Put(body_request_, body_response_));
764 EXPECT_TRUE(Match(body_request_));
766 body_request_.headers["zoo"] = "zoo";
767 EXPECT_TRUE(Match(body_request_));
770 TEST_P(CacheStorageCacheTestP, VaryMultiple) {
771 body_request_.headers["vary_foo"] = "foo";
772 body_request_.headers["vary_bar"] = "bar";
773 body_response_.headers["vary"] = " vary_foo , vary_bar";
774 EXPECT_TRUE(Put(body_request_, body_response_));
775 EXPECT_TRUE(Match(body_request_));
777 body_request_.headers["vary_bar"] = "foo";
778 EXPECT_FALSE(Match(body_request_));
780 body_request_.headers.erase("vary_bar");
781 EXPECT_FALSE(Match(body_request_));
784 TEST_P(CacheStorageCacheTestP, VaryNewHeader) {
785 body_request_.headers["vary_foo"] = "foo";
786 body_response_.headers["vary"] = " vary_foo, vary_bar";
787 EXPECT_TRUE(Put(body_request_, body_response_));
788 EXPECT_TRUE(Match(body_request_));
790 body_request_.headers["vary_bar"] = "bar";
791 EXPECT_FALSE(Match(body_request_));
794 TEST_P(CacheStorageCacheTestP, VaryStar) {
795 body_response_.headers["vary"] = "*";
796 EXPECT_TRUE(Put(body_request_, body_response_));
797 EXPECT_FALSE(Match(body_request_));
800 TEST_P(CacheStorageCacheTestP, EmptyKeys) {
801 EXPECT_TRUE(Keys());
802 EXPECT_EQ(0u, callback_strings_.size());
805 TEST_P(CacheStorageCacheTestP, TwoKeys) {
806 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
807 EXPECT_TRUE(Put(body_request_, body_response_));
808 EXPECT_TRUE(Keys());
809 EXPECT_EQ(2u, callback_strings_.size());
810 std::vector<std::string> expected_keys;
811 expected_keys.push_back(no_body_request_.url.spec());
812 expected_keys.push_back(body_request_.url.spec());
813 EXPECT_TRUE(VerifyKeys(expected_keys));
816 TEST_P(CacheStorageCacheTestP, TwoKeysThenOne) {
817 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
818 EXPECT_TRUE(Put(body_request_, body_response_));
819 EXPECT_TRUE(Keys());
820 EXPECT_EQ(2u, callback_strings_.size());
821 std::vector<std::string> expected_keys;
822 expected_keys.push_back(no_body_request_.url.spec());
823 expected_keys.push_back(body_request_.url.spec());
824 EXPECT_TRUE(VerifyKeys(expected_keys));
826 EXPECT_TRUE(Delete(body_request_));
827 EXPECT_TRUE(Keys());
828 EXPECT_EQ(1u, callback_strings_.size());
829 std::vector<std::string> expected_key;
830 expected_key.push_back(no_body_request_.url.spec());
831 EXPECT_TRUE(VerifyKeys(expected_key));
834 TEST_P(CacheStorageCacheTestP, DeleteNoBody) {
835 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
836 EXPECT_TRUE(Match(no_body_request_));
837 EXPECT_TRUE(Delete(no_body_request_));
838 EXPECT_FALSE(Match(no_body_request_));
839 EXPECT_FALSE(Delete(no_body_request_));
840 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
841 EXPECT_TRUE(Match(no_body_request_));
842 EXPECT_TRUE(Delete(no_body_request_));
845 TEST_P(CacheStorageCacheTestP, DeleteBody) {
846 EXPECT_TRUE(Put(body_request_, body_response_));
847 EXPECT_TRUE(Match(body_request_));
848 EXPECT_TRUE(Delete(body_request_));
849 EXPECT_FALSE(Match(body_request_));
850 EXPECT_FALSE(Delete(body_request_));
851 EXPECT_TRUE(Put(body_request_, body_response_));
852 EXPECT_TRUE(Match(body_request_));
853 EXPECT_TRUE(Delete(body_request_));
856 TEST_P(CacheStorageCacheTestP, QuickStressNoBody) {
857 for (int i = 0; i < 100; ++i) {
858 EXPECT_FALSE(Match(no_body_request_));
859 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
860 EXPECT_TRUE(Match(no_body_request_));
861 EXPECT_TRUE(Delete(no_body_request_));
865 TEST_P(CacheStorageCacheTestP, QuickStressBody) {
866 for (int i = 0; i < 100; ++i) {
867 ASSERT_FALSE(Match(body_request_));
868 ASSERT_TRUE(Put(body_request_, body_response_));
869 ASSERT_TRUE(Match(body_request_));
870 ASSERT_TRUE(Delete(body_request_));
874 TEST_P(CacheStorageCacheTestP, PutResponseType) {
875 EXPECT_TRUE(TestResponseType(blink::WebServiceWorkerResponseTypeBasic));
876 EXPECT_TRUE(TestResponseType(blink::WebServiceWorkerResponseTypeCORS));
877 EXPECT_TRUE(TestResponseType(blink::WebServiceWorkerResponseTypeDefault));
878 EXPECT_TRUE(TestResponseType(blink::WebServiceWorkerResponseTypeError));
879 EXPECT_TRUE(TestResponseType(blink::WebServiceWorkerResponseTypeOpaque));
882 TEST_F(CacheStorageCacheTest, CaselessServiceWorkerResponseHeaders) {
883 // CacheStorageCache depends on ServiceWorkerResponse having caseless
884 // headers so that it can quickly lookup vary headers.
885 ServiceWorkerResponse response(GURL("http://www.example.com"), 200, "OK",
886 blink::WebServiceWorkerResponseTypeDefault,
887 ServiceWorkerHeaderMap(), "", 0, GURL(),
888 blink::WebServiceWorkerResponseErrorUnknown);
889 response.headers["content-type"] = "foo";
890 response.headers["Content-Type"] = "bar";
891 EXPECT_EQ("bar", response.headers["content-type"]);
894 TEST_F(CacheStorageCacheTest, CaselessServiceWorkerFetchRequestHeaders) {
895 // CacheStorageCache depends on ServiceWorkerFetchRequest having caseless
896 // headers so that it can quickly lookup vary headers.
897 ServiceWorkerFetchRequest request(GURL("http://www.example.com"), "GET",
898 ServiceWorkerHeaderMap(), Referrer(),
899 false);
900 request.headers["content-type"] = "foo";
901 request.headers["Content-Type"] = "bar";
902 EXPECT_EQ("bar", request.headers["content-type"]);
905 TEST_P(CacheStorageCacheTestP, QuotaManagerModified) {
906 EXPECT_EQ(0, quota_manager_proxy_->notify_storage_modified_count());
908 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
909 EXPECT_EQ(1, quota_manager_proxy_->notify_storage_modified_count());
910 EXPECT_LT(0, quota_manager_proxy_->last_notified_delta());
911 int64 sum_delta = quota_manager_proxy_->last_notified_delta();
913 EXPECT_TRUE(Put(body_request_, body_response_));
914 EXPECT_EQ(2, quota_manager_proxy_->notify_storage_modified_count());
915 EXPECT_LT(sum_delta, quota_manager_proxy_->last_notified_delta());
916 sum_delta += quota_manager_proxy_->last_notified_delta();
918 EXPECT_TRUE(Delete(body_request_));
919 EXPECT_EQ(3, quota_manager_proxy_->notify_storage_modified_count());
920 sum_delta += quota_manager_proxy_->last_notified_delta();
922 EXPECT_TRUE(Delete(no_body_request_));
923 EXPECT_EQ(4, quota_manager_proxy_->notify_storage_modified_count());
924 sum_delta += quota_manager_proxy_->last_notified_delta();
926 EXPECT_EQ(0, sum_delta);
929 TEST_F(CacheStorageCacheMemoryOnlyTest, MemoryBackedSize) {
930 EXPECT_EQ(0, cache_->MemoryBackedSize());
931 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
932 EXPECT_LT(0, cache_->MemoryBackedSize());
933 int64 no_body_size = cache_->MemoryBackedSize();
935 EXPECT_TRUE(Delete(no_body_request_));
936 EXPECT_EQ(0, cache_->MemoryBackedSize());
938 EXPECT_TRUE(Put(body_request_, body_response_));
939 EXPECT_LT(no_body_size, cache_->MemoryBackedSize());
941 EXPECT_TRUE(Delete(body_request_));
942 EXPECT_EQ(0, cache_->MemoryBackedSize());
945 TEST_F(CacheStorageCacheTest, MemoryBackedSizePersistent) {
946 EXPECT_EQ(0, cache_->MemoryBackedSize());
947 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
948 EXPECT_EQ(0, cache_->MemoryBackedSize());
951 TEST_P(CacheStorageCacheTestP, OpsFailOnClosedBackendNeverCreated) {
952 cache_->set_delay_backend_creation(
953 true); // Will hang the test if a backend is created.
954 EXPECT_TRUE(Close());
955 VerifyAllOpsFail();
958 TEST_P(CacheStorageCacheTestP, OpsFailOnClosedBackend) {
959 // Create the backend and put something in it.
960 EXPECT_TRUE(Put(body_request_, body_response_));
961 EXPECT_TRUE(Close());
962 VerifyAllOpsFail();
965 TEST_P(CacheStorageCacheTestP, VerifySerialScheduling) {
966 // Start two operations, the first one is delayed but the second isn't. The
967 // second should wait for the first.
968 EXPECT_TRUE(Keys()); // Opens the backend.
969 DelayableBackend* delayable_backend = cache_->UseDelayableBackend();
970 delayable_backend->set_delay_open(true);
972 int sequence_out = -1;
974 CacheStorageBatchOperation operation1;
975 operation1.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT;
976 operation1.request = body_request_;
977 operation1.response = body_response_;
979 scoped_ptr<base::RunLoop> close_loop1(new base::RunLoop());
980 cache_->BatchOperation(
981 std::vector<CacheStorageBatchOperation>(1, operation1),
982 base::Bind(&CacheStorageCacheTest::SequenceCallback,
983 base::Unretained(this), 1, &sequence_out, close_loop1.get()));
985 // Blocks on opening the cache entry.
986 base::RunLoop().RunUntilIdle();
988 CacheStorageBatchOperation operation2;
989 operation2.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT;
990 operation2.request = body_request_;
991 operation2.response = body_response_;
993 delayable_backend->set_delay_open(false);
994 scoped_ptr<base::RunLoop> close_loop2(new base::RunLoop());
995 cache_->BatchOperation(
996 std::vector<CacheStorageBatchOperation>(1, operation2),
997 base::Bind(&CacheStorageCacheTest::SequenceCallback,
998 base::Unretained(this), 2, &sequence_out, close_loop2.get()));
1000 // The second put operation should wait for the first to complete.
1001 base::RunLoop().RunUntilIdle();
1002 EXPECT_FALSE(callback_response_);
1004 delayable_backend->OpenEntryContinue();
1005 close_loop1->Run();
1006 EXPECT_EQ(1, sequence_out);
1007 close_loop2->Run();
1008 EXPECT_EQ(2, sequence_out);
1011 INSTANTIATE_TEST_CASE_P(CacheStorageCacheTest,
1012 CacheStorageCacheTestP,
1013 ::testing::Values(false, true));
1015 } // namespace content