Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / content / browser / cache_storage / cache_storage_cache_unittest.cc
blob22175655d6fb581e89b01426d60d05a516063161
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/message_loop/message_loop_proxy.h"
10 #include "base/run_loop.h"
11 #include "content/browser/fileapi/chrome_blob_storage_context.h"
12 #include "content/browser/fileapi/mock_url_request_delegate.h"
13 #include "content/browser/quota/mock_quota_manager_proxy.h"
14 #include "content/common/cache_storage/cache_storage_types.h"
15 #include "content/common/service_worker/service_worker_types.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "content/public/common/referrer.h"
18 #include "content/public/test/test_browser_context.h"
19 #include "content/public/test/test_browser_thread_bundle.h"
20 #include "net/url_request/url_request_context.h"
21 #include "net/url_request/url_request_context_getter.h"
22 #include "net/url_request/url_request_job_factory_impl.h"
23 #include "storage/browser/blob/blob_data_builder.h"
24 #include "storage/browser/blob/blob_data_handle.h"
25 #include "storage/browser/blob/blob_data_snapshot.h"
26 #include "storage/browser/blob/blob_storage_context.h"
27 #include "storage/browser/blob/blob_url_request_job_factory.h"
28 #include "storage/browser/quota/quota_manager_proxy.h"
29 #include "testing/gtest/include/gtest/gtest.h"
31 namespace content {
33 namespace {
34 const char kTestData[] = "Hello World";
36 // Returns a BlobProtocolHandler that uses |blob_storage_context|. Caller owns
37 // the memory.
38 storage::BlobProtocolHandler* CreateMockBlobProtocolHandler(
39 storage::BlobStorageContext* blob_storage_context) {
40 // The FileSystemContext and MessageLoopProxy are not actually used but a
41 // MessageLoopProxy is needed to avoid a DCHECK in BlobURLRequestJob ctor.
42 return new storage::BlobProtocolHandler(
43 blob_storage_context, NULL, base::MessageLoopProxy::current().get());
46 // A disk_cache::Backend wrapper that can delay operations.
47 class DelayableBackend : public disk_cache::Backend {
48 public:
49 DelayableBackend(scoped_ptr<disk_cache::Backend> backend)
50 : backend_(backend.Pass()), delay_open_(false) {}
52 // disk_cache::Backend overrides
53 net::CacheType GetCacheType() const override {
54 return backend_->GetCacheType();
56 int32 GetEntryCount() const override { return backend_->GetEntryCount(); }
57 int OpenEntry(const std::string& key,
58 disk_cache::Entry** entry,
59 const CompletionCallback& callback) override {
60 if (delay_open_) {
61 open_entry_callback_ =
62 base::Bind(&DelayableBackend::OpenEntryDelayedImpl,
63 base::Unretained(this), key, entry, callback);
64 return net::ERR_IO_PENDING;
67 return backend_->OpenEntry(key, entry, callback);
69 int CreateEntry(const std::string& key,
70 disk_cache::Entry** entry,
71 const CompletionCallback& callback) override {
72 return backend_->CreateEntry(key, entry, callback);
74 int DoomEntry(const std::string& key,
75 const CompletionCallback& callback) override {
76 return backend_->DoomEntry(key, callback);
78 int DoomAllEntries(const CompletionCallback& callback) override {
79 return backend_->DoomAllEntries(callback);
81 int DoomEntriesBetween(base::Time initial_time,
82 base::Time end_time,
83 const CompletionCallback& callback) override {
84 return backend_->DoomEntriesBetween(initial_time, end_time, callback);
86 int DoomEntriesSince(base::Time initial_time,
87 const CompletionCallback& callback) override {
88 return backend_->DoomEntriesSince(initial_time, callback);
90 scoped_ptr<Iterator> CreateIterator() override {
91 return backend_->CreateIterator();
93 void GetStats(
94 std::vector<std::pair<std::string, std::string>>* stats) override {
95 return backend_->GetStats(stats);
97 void OnExternalCacheHit(const std::string& key) override {
98 return backend_->OnExternalCacheHit(key);
101 // Call to continue a delayed open.
102 void OpenEntryContinue() {
103 EXPECT_FALSE(open_entry_callback_.is_null());
104 open_entry_callback_.Run();
107 void set_delay_open(bool value) { delay_open_ = value; }
109 private:
110 void OpenEntryDelayedImpl(const std::string& key,
111 disk_cache::Entry** entry,
112 const CompletionCallback& callback) {
113 int rv = backend_->OpenEntry(key, entry, callback);
114 if (rv != net::ERR_IO_PENDING)
115 callback.Run(rv);
118 scoped_ptr<disk_cache::Backend> backend_;
119 bool delay_open_;
120 base::Closure open_entry_callback_;
123 } // namespace
125 // A CacheStorageCache that can optionally delay during backend creation.
126 class TestCacheStorageCache : public CacheStorageCache {
127 public:
128 TestCacheStorageCache(
129 const GURL& origin,
130 const base::FilePath& path,
131 net::URLRequestContext* request_context,
132 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
133 base::WeakPtr<storage::BlobStorageContext> blob_context)
134 : CacheStorageCache(origin,
135 path,
136 request_context,
137 quota_manager_proxy,
138 blob_context),
139 delay_backend_creation_(false) {}
141 void CreateBackend(const ErrorCallback& callback) override {
142 backend_creation_callback_ = callback;
143 if (delay_backend_creation_)
144 return;
145 ContinueCreateBackend();
148 void ContinueCreateBackend() {
149 CacheStorageCache::CreateBackend(backend_creation_callback_);
152 void set_delay_backend_creation(bool delay) {
153 delay_backend_creation_ = delay;
156 // Swap the existing backend with a delayable one. The backend must have been
157 // created before calling this.
158 DelayableBackend* UseDelayableBackend() {
159 EXPECT_TRUE(backend_);
160 DelayableBackend* delayable_backend = new DelayableBackend(backend_.Pass());
161 backend_.reset(delayable_backend);
162 return delayable_backend;
165 private:
166 ~TestCacheStorageCache() override {}
168 bool delay_backend_creation_;
169 ErrorCallback backend_creation_callback_;
171 DISALLOW_COPY_AND_ASSIGN(TestCacheStorageCache);
174 class CacheStorageCacheTest : public testing::Test {
175 public:
176 CacheStorageCacheTest()
177 : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
178 callback_error_(CacheStorageCache::ERROR_TYPE_OK),
179 callback_closed_(false) {}
181 void SetUp() override {
182 ChromeBlobStorageContext* blob_storage_context =
183 ChromeBlobStorageContext::GetFor(&browser_context_);
184 // Wait for chrome_blob_storage_context to finish initializing.
185 base::RunLoop().RunUntilIdle();
186 blob_storage_context_ = blob_storage_context->context();
188 quota_manager_proxy_ = new MockQuotaManagerProxy(
189 nullptr, base::MessageLoopProxy::current().get());
191 url_request_job_factory_.reset(new net::URLRequestJobFactoryImpl);
192 url_request_job_factory_->SetProtocolHandler(
193 "blob", CreateMockBlobProtocolHandler(blob_storage_context->context()));
195 net::URLRequestContext* url_request_context =
196 browser_context_.GetRequestContext()->GetURLRequestContext();
198 url_request_context->set_job_factory(url_request_job_factory_.get());
200 CreateRequests(blob_storage_context);
202 if (!MemoryOnly())
203 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
204 base::FilePath path = MemoryOnly() ? base::FilePath() : temp_dir_.path();
206 cache_ = make_scoped_refptr(new TestCacheStorageCache(
207 GURL("http://example.com"), path, url_request_context,
208 quota_manager_proxy_, blob_storage_context->context()->AsWeakPtr()));
211 void TearDown() override {
212 quota_manager_proxy_->SimulateQuotaManagerDestroyed();
213 base::RunLoop().RunUntilIdle();
216 void CreateRequests(ChromeBlobStorageContext* blob_storage_context) {
217 ServiceWorkerHeaderMap headers;
218 headers.insert(std::make_pair("a", "a"));
219 headers.insert(std::make_pair("b", "b"));
220 body_request_ =
221 ServiceWorkerFetchRequest(GURL("http://example.com/body.html"), "GET",
222 headers, Referrer(), false);
223 no_body_request_ =
224 ServiceWorkerFetchRequest(GURL("http://example.com/no_body.html"),
225 "GET", headers, Referrer(), false);
227 std::string expected_response;
228 for (int i = 0; i < 100; ++i)
229 expected_blob_data_ += kTestData;
231 scoped_ptr<storage::BlobDataBuilder> blob_data(
232 new storage::BlobDataBuilder("blob-id:myblob"));
233 blob_data->AppendData(expected_blob_data_);
235 blob_handle_ =
236 blob_storage_context->context()->AddFinishedBlob(blob_data.get());
238 body_response_ = ServiceWorkerResponse(
239 GURL("http://example.com/body.html"), 200, "OK",
240 blink::WebServiceWorkerResponseTypeDefault, headers,
241 blob_handle_->uuid(), expected_blob_data_.size(), GURL());
243 no_body_response_ = ServiceWorkerResponse(
244 GURL("http://example.com/no_body.html"), 200, "OK",
245 blink::WebServiceWorkerResponseTypeDefault, headers, "", 0, GURL());
248 scoped_ptr<ServiceWorkerFetchRequest> CopyFetchRequest(
249 const ServiceWorkerFetchRequest& request) {
250 return make_scoped_ptr(new ServiceWorkerFetchRequest(
251 request.url, request.method, request.headers, request.referrer,
252 request.is_reload));
255 scoped_ptr<ServiceWorkerResponse> CopyFetchResponse(
256 const ServiceWorkerResponse& response) {
257 scoped_ptr<ServiceWorkerResponse> sw_response(new ServiceWorkerResponse(
258 response.url, response.status_code, response.status_text,
259 response.response_type, response.headers, response.blob_uuid,
260 response.blob_size, response.stream_url));
261 return sw_response.Pass();
264 bool Put(const ServiceWorkerFetchRequest& request,
265 const ServiceWorkerResponse& response) {
266 scoped_ptr<base::RunLoop> loop(new base::RunLoop());
268 cache_->Put(
269 CopyFetchRequest(request), CopyFetchResponse(response),
270 base::Bind(&CacheStorageCacheTest::ResponseAndErrorCallback,
271 base::Unretained(this), base::Unretained(loop.get())));
272 // TODO(jkarlin): These functions should use base::RunLoop().RunUntilIdle()
273 // once the cache uses a passed in MessageLoopProxy instead of the CACHE
274 // thread.
275 loop->Run();
277 return callback_error_ == CacheStorageCache::ERROR_TYPE_OK;
280 bool Match(const ServiceWorkerFetchRequest& request) {
281 scoped_ptr<base::RunLoop> loop(new base::RunLoop());
283 cache_->Match(
284 CopyFetchRequest(request),
285 base::Bind(&CacheStorageCacheTest::ResponseAndErrorCallback,
286 base::Unretained(this), base::Unretained(loop.get())));
287 loop->Run();
289 return callback_error_ == CacheStorageCache::ERROR_TYPE_OK;
292 bool Delete(const ServiceWorkerFetchRequest& request) {
293 scoped_ptr<base::RunLoop> loop(new base::RunLoop());
295 cache_->Delete(
296 CopyFetchRequest(request),
297 base::Bind(&CacheStorageCacheTest::ErrorTypeCallback,
298 base::Unretained(this), base::Unretained(loop.get())));
299 loop->Run();
301 return callback_error_ == CacheStorageCache::ERROR_TYPE_OK;
304 bool Keys() {
305 scoped_ptr<base::RunLoop> loop(new base::RunLoop());
307 cache_->Keys(base::Bind(&CacheStorageCacheTest::RequestsCallback,
308 base::Unretained(this),
309 base::Unretained(loop.get())));
310 loop->Run();
312 return callback_error_ == CacheStorageCache::ERROR_TYPE_OK;
315 bool Close() {
316 scoped_ptr<base::RunLoop> loop(new base::RunLoop());
318 cache_->Close(base::Bind(&CacheStorageCacheTest::CloseCallback,
319 base::Unretained(this),
320 base::Unretained(loop.get())));
321 loop->Run();
322 return callback_closed_;
325 void RequestsCallback(base::RunLoop* run_loop,
326 CacheStorageCache::ErrorType error,
327 scoped_ptr<CacheStorageCache::Requests> requests) {
328 callback_error_ = error;
329 callback_strings_.clear();
330 if (requests) {
331 for (size_t i = 0u; i < requests->size(); ++i)
332 callback_strings_.push_back(requests->at(i).url.spec());
334 if (run_loop)
335 run_loop->Quit();
338 void ErrorTypeCallback(base::RunLoop* run_loop,
339 CacheStorageCache::ErrorType error) {
340 callback_error_ = error;
341 if (run_loop)
342 run_loop->Quit();
345 void ResponseAndErrorCallback(
346 base::RunLoop* run_loop,
347 CacheStorageCache::ErrorType error,
348 scoped_ptr<ServiceWorkerResponse> response,
349 scoped_ptr<storage::BlobDataHandle> body_handle) {
350 callback_error_ = error;
351 callback_response_ = response.Pass();
352 callback_response_data_.reset();
353 if (error == CacheStorageCache::ERROR_TYPE_OK &&
354 !callback_response_->blob_uuid.empty()) {
355 callback_response_data_ = body_handle.Pass();
358 if (run_loop)
359 run_loop->Quit();
362 void CloseCallback(base::RunLoop* run_loop) {
363 EXPECT_FALSE(callback_closed_);
364 callback_closed_ = true;
365 if (run_loop)
366 run_loop->Quit();
369 void CopyBody(storage::BlobDataHandle* blob_handle, std::string* output) {
370 scoped_ptr<storage::BlobDataSnapshot> data = blob_handle->CreateSnapshot();
371 const auto& items = data->items();
372 for (const auto& item : items) {
373 output->append(item->bytes(), item->length());
377 bool VerifyKeys(const std::vector<std::string>& expected_keys) {
378 if (expected_keys.size() != callback_strings_.size())
379 return false;
381 std::set<std::string> found_set;
382 for (int i = 0, max = callback_strings_.size(); i < max; ++i)
383 found_set.insert(callback_strings_[i]);
385 for (int i = 0, max = expected_keys.size(); i < max; ++i) {
386 if (found_set.find(expected_keys[i]) == found_set.end())
387 return false;
389 return true;
392 bool TestResponseType(blink::WebServiceWorkerResponseType response_type) {
393 body_response_.response_type = response_type;
394 EXPECT_TRUE(Put(body_request_, body_response_));
395 EXPECT_TRUE(Match(body_request_));
396 EXPECT_TRUE(Delete(body_request_));
397 return response_type == callback_response_->response_type;
400 void VerifyAllOpsFail() {
401 EXPECT_FALSE(Put(no_body_request_, no_body_response_));
402 EXPECT_FALSE(Match(no_body_request_));
403 EXPECT_FALSE(Delete(body_request_));
404 EXPECT_FALSE(Keys());
407 virtual bool MemoryOnly() { return false; }
409 protected:
410 TestBrowserContext browser_context_;
411 TestBrowserThreadBundle browser_thread_bundle_;
412 scoped_ptr<net::URLRequestJobFactoryImpl> url_request_job_factory_;
413 scoped_refptr<MockQuotaManagerProxy> quota_manager_proxy_;
414 storage::BlobStorageContext* blob_storage_context_;
416 base::ScopedTempDir temp_dir_;
417 scoped_refptr<TestCacheStorageCache> cache_;
419 ServiceWorkerFetchRequest body_request_;
420 ServiceWorkerResponse body_response_;
421 ServiceWorkerFetchRequest no_body_request_;
422 ServiceWorkerResponse no_body_response_;
423 scoped_ptr<storage::BlobDataHandle> blob_handle_;
424 std::string expected_blob_data_;
426 CacheStorageCache::ErrorType callback_error_;
427 scoped_ptr<ServiceWorkerResponse> callback_response_;
428 scoped_ptr<storage::BlobDataHandle> callback_response_data_;
429 std::vector<std::string> callback_strings_;
430 bool callback_closed_;
433 class CacheStorageCacheTestP : public CacheStorageCacheTest,
434 public testing::WithParamInterface<bool> {
435 bool MemoryOnly() override { return !GetParam(); }
438 class CacheStorageCacheMemoryOnlyTest
439 : public CacheStorageCacheTest,
440 public testing::WithParamInterface<bool> {
441 bool MemoryOnly() override { return true; }
444 TEST_P(CacheStorageCacheTestP, PutNoBody) {
445 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
446 EXPECT_TRUE(callback_response_);
447 EXPECT_STREQ(no_body_response_.url.spec().c_str(),
448 callback_response_->url.spec().c_str());
449 EXPECT_FALSE(callback_response_data_);
450 EXPECT_STREQ("", callback_response_->blob_uuid.c_str());
451 EXPECT_EQ(0u, callback_response_->blob_size);
454 TEST_P(CacheStorageCacheTestP, PutBody) {
455 EXPECT_TRUE(Put(body_request_, body_response_));
456 EXPECT_TRUE(callback_response_);
457 EXPECT_STREQ(body_response_.url.spec().c_str(),
458 callback_response_->url.spec().c_str());
459 EXPECT_TRUE(callback_response_data_);
460 EXPECT_STRNE("", callback_response_->blob_uuid.c_str());
461 EXPECT_EQ(expected_blob_data_.size(), callback_response_->blob_size);
463 std::string response_body;
464 CopyBody(callback_response_data_.get(), &response_body);
465 EXPECT_STREQ(expected_blob_data_.c_str(), response_body.c_str());
468 TEST_P(CacheStorageCacheTestP, ResponseURLDiffersFromRequestURL) {
469 no_body_response_.url = GURL("http://example.com/foobar");
470 EXPECT_STRNE("http://example.com/foobar",
471 no_body_request_.url.spec().c_str());
472 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
473 EXPECT_TRUE(Match(no_body_request_));
474 EXPECT_STREQ("http://example.com/foobar",
475 callback_response_->url.spec().c_str());
478 TEST_P(CacheStorageCacheTestP, ResponseURLEmpty) {
479 no_body_response_.url = GURL();
480 EXPECT_STRNE("", no_body_request_.url.spec().c_str());
481 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
482 EXPECT_TRUE(Match(no_body_request_));
483 EXPECT_STREQ("", callback_response_->url.spec().c_str());
486 TEST_F(CacheStorageCacheTest, PutBodyDropBlobRef) {
487 scoped_ptr<base::RunLoop> loop(new base::RunLoop());
488 cache_->Put(CopyFetchRequest(body_request_),
489 CopyFetchResponse(body_response_),
490 base::Bind(&CacheStorageCacheTestP::ResponseAndErrorCallback,
491 base::Unretained(this), base::Unretained(loop.get())));
492 // The handle should be held by the cache now so the deref here should be
493 // okay.
494 blob_handle_.reset();
495 loop->Run();
497 EXPECT_EQ(CacheStorageCache::ERROR_TYPE_OK, callback_error_);
500 TEST_P(CacheStorageCacheTestP, PutReplace) {
501 EXPECT_TRUE(Put(body_request_, no_body_response_));
502 EXPECT_TRUE(Match(body_request_));
503 EXPECT_FALSE(callback_response_data_);
505 EXPECT_TRUE(Put(body_request_, body_response_));
506 EXPECT_TRUE(Match(body_request_));
507 EXPECT_TRUE(callback_response_data_);
509 EXPECT_TRUE(Put(body_request_, no_body_response_));
510 EXPECT_TRUE(Match(body_request_));
511 EXPECT_FALSE(callback_response_data_);
514 TEST_P(CacheStorageCacheTestP, MatchNoBody) {
515 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
516 EXPECT_TRUE(Match(no_body_request_));
517 EXPECT_EQ(200, callback_response_->status_code);
518 EXPECT_STREQ("OK", callback_response_->status_text.c_str());
519 EXPECT_STREQ("http://example.com/no_body.html",
520 callback_response_->url.spec().c_str());
521 EXPECT_STREQ("", callback_response_->blob_uuid.c_str());
522 EXPECT_EQ(0u, callback_response_->blob_size);
525 TEST_P(CacheStorageCacheTestP, MatchBody) {
526 EXPECT_TRUE(Put(body_request_, body_response_));
527 EXPECT_TRUE(Match(body_request_));
528 EXPECT_EQ(200, callback_response_->status_code);
529 EXPECT_STREQ("OK", callback_response_->status_text.c_str());
530 EXPECT_STREQ("http://example.com/body.html",
531 callback_response_->url.spec().c_str());
532 EXPECT_STRNE("", callback_response_->blob_uuid.c_str());
533 EXPECT_EQ(expected_blob_data_.size(), callback_response_->blob_size);
535 std::string response_body;
536 CopyBody(callback_response_data_.get(), &response_body);
537 EXPECT_STREQ(expected_blob_data_.c_str(), response_body.c_str());
540 TEST_P(CacheStorageCacheTestP, Vary) {
541 body_request_.headers["vary_foo"] = "foo";
542 body_response_.headers["vary"] = "vary_foo";
543 EXPECT_TRUE(Put(body_request_, body_response_));
544 EXPECT_TRUE(Match(body_request_));
546 body_request_.headers["vary_foo"] = "bar";
547 EXPECT_FALSE(Match(body_request_));
549 body_request_.headers.erase("vary_foo");
550 EXPECT_FALSE(Match(body_request_));
553 TEST_P(CacheStorageCacheTestP, EmptyVary) {
554 body_response_.headers["vary"] = "";
555 EXPECT_TRUE(Put(body_request_, body_response_));
556 EXPECT_TRUE(Match(body_request_));
558 body_request_.headers["zoo"] = "zoo";
559 EXPECT_TRUE(Match(body_request_));
562 TEST_P(CacheStorageCacheTestP, NoVaryButDiffHeaders) {
563 EXPECT_TRUE(Put(body_request_, body_response_));
564 EXPECT_TRUE(Match(body_request_));
566 body_request_.headers["zoo"] = "zoo";
567 EXPECT_TRUE(Match(body_request_));
570 TEST_P(CacheStorageCacheTestP, VaryMultiple) {
571 body_request_.headers["vary_foo"] = "foo";
572 body_request_.headers["vary_bar"] = "bar";
573 body_response_.headers["vary"] = " vary_foo , vary_bar";
574 EXPECT_TRUE(Put(body_request_, body_response_));
575 EXPECT_TRUE(Match(body_request_));
577 body_request_.headers["vary_bar"] = "foo";
578 EXPECT_FALSE(Match(body_request_));
580 body_request_.headers.erase("vary_bar");
581 EXPECT_FALSE(Match(body_request_));
584 TEST_P(CacheStorageCacheTestP, VaryNewHeader) {
585 body_request_.headers["vary_foo"] = "foo";
586 body_response_.headers["vary"] = " vary_foo, vary_bar";
587 EXPECT_TRUE(Put(body_request_, body_response_));
588 EXPECT_TRUE(Match(body_request_));
590 body_request_.headers["vary_bar"] = "bar";
591 EXPECT_FALSE(Match(body_request_));
594 TEST_P(CacheStorageCacheTestP, VaryStar) {
595 body_response_.headers["vary"] = "*";
596 EXPECT_TRUE(Put(body_request_, body_response_));
597 EXPECT_FALSE(Match(body_request_));
600 TEST_P(CacheStorageCacheTestP, EmptyKeys) {
601 EXPECT_TRUE(Keys());
602 EXPECT_EQ(0u, callback_strings_.size());
605 TEST_P(CacheStorageCacheTestP, TwoKeys) {
606 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
607 EXPECT_TRUE(Put(body_request_, body_response_));
608 EXPECT_TRUE(Keys());
609 EXPECT_EQ(2u, callback_strings_.size());
610 std::vector<std::string> expected_keys;
611 expected_keys.push_back(no_body_request_.url.spec());
612 expected_keys.push_back(body_request_.url.spec());
613 EXPECT_TRUE(VerifyKeys(expected_keys));
616 TEST_P(CacheStorageCacheTestP, TwoKeysThenOne) {
617 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
618 EXPECT_TRUE(Put(body_request_, body_response_));
619 EXPECT_TRUE(Keys());
620 EXPECT_EQ(2u, callback_strings_.size());
621 std::vector<std::string> expected_keys;
622 expected_keys.push_back(no_body_request_.url.spec());
623 expected_keys.push_back(body_request_.url.spec());
624 EXPECT_TRUE(VerifyKeys(expected_keys));
626 EXPECT_TRUE(Delete(body_request_));
627 EXPECT_TRUE(Keys());
628 EXPECT_EQ(1u, callback_strings_.size());
629 std::vector<std::string> expected_key;
630 expected_key.push_back(no_body_request_.url.spec());
631 EXPECT_TRUE(VerifyKeys(expected_key));
634 TEST_P(CacheStorageCacheTestP, DeleteNoBody) {
635 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
636 EXPECT_TRUE(Match(no_body_request_));
637 EXPECT_TRUE(Delete(no_body_request_));
638 EXPECT_FALSE(Match(no_body_request_));
639 EXPECT_FALSE(Delete(no_body_request_));
640 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
641 EXPECT_TRUE(Match(no_body_request_));
642 EXPECT_TRUE(Delete(no_body_request_));
645 TEST_P(CacheStorageCacheTestP, DeleteBody) {
646 EXPECT_TRUE(Put(body_request_, body_response_));
647 EXPECT_TRUE(Match(body_request_));
648 EXPECT_TRUE(Delete(body_request_));
649 EXPECT_FALSE(Match(body_request_));
650 EXPECT_FALSE(Delete(body_request_));
651 EXPECT_TRUE(Put(body_request_, body_response_));
652 EXPECT_TRUE(Match(body_request_));
653 EXPECT_TRUE(Delete(body_request_));
656 TEST_P(CacheStorageCacheTestP, QuickStressNoBody) {
657 for (int i = 0; i < 100; ++i) {
658 EXPECT_FALSE(Match(no_body_request_));
659 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
660 EXPECT_TRUE(Match(no_body_request_));
661 EXPECT_TRUE(Delete(no_body_request_));
665 TEST_P(CacheStorageCacheTestP, QuickStressBody) {
666 for (int i = 0; i < 100; ++i) {
667 ASSERT_FALSE(Match(body_request_));
668 ASSERT_TRUE(Put(body_request_, body_response_));
669 ASSERT_TRUE(Match(body_request_));
670 ASSERT_TRUE(Delete(body_request_));
674 TEST_P(CacheStorageCacheTestP, PutResponseType) {
675 EXPECT_TRUE(TestResponseType(blink::WebServiceWorkerResponseTypeBasic));
676 EXPECT_TRUE(TestResponseType(blink::WebServiceWorkerResponseTypeCORS));
677 EXPECT_TRUE(TestResponseType(blink::WebServiceWorkerResponseTypeDefault));
678 EXPECT_TRUE(TestResponseType(blink::WebServiceWorkerResponseTypeError));
679 EXPECT_TRUE(TestResponseType(blink::WebServiceWorkerResponseTypeOpaque));
682 TEST_F(CacheStorageCacheTest, CaselessServiceWorkerResponseHeaders) {
683 // CacheStorageCache depends on ServiceWorkerResponse having caseless
684 // headers so that it can quickly lookup vary headers.
685 ServiceWorkerResponse response(GURL("http://www.example.com"), 200, "OK",
686 blink::WebServiceWorkerResponseTypeDefault,
687 ServiceWorkerHeaderMap(), "", 0, GURL());
688 response.headers["content-type"] = "foo";
689 response.headers["Content-Type"] = "bar";
690 EXPECT_EQ("bar", response.headers["content-type"]);
693 TEST_F(CacheStorageCacheTest, CaselessServiceWorkerFetchRequestHeaders) {
694 // CacheStorageCache depends on ServiceWorkerFetchRequest having caseless
695 // headers so that it can quickly lookup vary headers.
696 ServiceWorkerFetchRequest request(GURL("http://www.example.com"), "GET",
697 ServiceWorkerHeaderMap(), Referrer(),
698 false);
699 request.headers["content-type"] = "foo";
700 request.headers["Content-Type"] = "bar";
701 EXPECT_EQ("bar", request.headers["content-type"]);
704 TEST_P(CacheStorageCacheTestP, QuotaManagerModified) {
705 EXPECT_EQ(0, quota_manager_proxy_->notify_storage_modified_count());
707 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
708 EXPECT_EQ(1, quota_manager_proxy_->notify_storage_modified_count());
709 EXPECT_LT(0, quota_manager_proxy_->last_notified_delta());
710 int64 sum_delta = quota_manager_proxy_->last_notified_delta();
712 EXPECT_TRUE(Put(body_request_, body_response_));
713 EXPECT_EQ(2, quota_manager_proxy_->notify_storage_modified_count());
714 EXPECT_LT(sum_delta, quota_manager_proxy_->last_notified_delta());
715 sum_delta += quota_manager_proxy_->last_notified_delta();
717 EXPECT_TRUE(Delete(body_request_));
718 EXPECT_EQ(3, quota_manager_proxy_->notify_storage_modified_count());
719 sum_delta += quota_manager_proxy_->last_notified_delta();
721 EXPECT_TRUE(Delete(no_body_request_));
722 EXPECT_EQ(4, quota_manager_proxy_->notify_storage_modified_count());
723 sum_delta += quota_manager_proxy_->last_notified_delta();
725 EXPECT_EQ(0, sum_delta);
728 TEST_F(CacheStorageCacheMemoryOnlyTest, MemoryBackedSize) {
729 EXPECT_EQ(0, cache_->MemoryBackedSize());
730 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
731 EXPECT_LT(0, cache_->MemoryBackedSize());
732 int64 no_body_size = cache_->MemoryBackedSize();
734 EXPECT_TRUE(Delete(no_body_request_));
735 EXPECT_EQ(0, cache_->MemoryBackedSize());
737 EXPECT_TRUE(Put(body_request_, body_response_));
738 EXPECT_LT(no_body_size, cache_->MemoryBackedSize());
740 EXPECT_TRUE(Delete(body_request_));
741 EXPECT_EQ(0, cache_->MemoryBackedSize());
744 TEST_F(CacheStorageCacheTest, MemoryBackedSizePersistent) {
745 EXPECT_EQ(0, cache_->MemoryBackedSize());
746 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
747 EXPECT_EQ(0, cache_->MemoryBackedSize());
750 TEST_P(CacheStorageCacheTestP, OpsFailOnClosedBackendNeverCreated) {
751 cache_->set_delay_backend_creation(
752 true); // Will hang the test if a backend is created.
753 EXPECT_TRUE(Close());
754 VerifyAllOpsFail();
757 TEST_P(CacheStorageCacheTestP, OpsFailOnClosedBackend) {
758 // Create the backend and put something in it.
759 EXPECT_TRUE(Put(body_request_, body_response_));
760 EXPECT_TRUE(Close());
761 VerifyAllOpsFail();
764 TEST_P(CacheStorageCacheTestP, VerifySerialScheduling) {
765 // Start two operations, the first one is delayed but the second isn't. The
766 // second should wait for the first.
767 EXPECT_TRUE(Keys()); // Opens the backend.
768 DelayableBackend* delayable_backend = cache_->UseDelayableBackend();
769 delayable_backend->set_delay_open(true);
771 scoped_ptr<ServiceWorkerResponse> response1 =
772 CopyFetchResponse(body_response_);
773 response1->status_code = 1;
775 scoped_ptr<base::RunLoop> close_loop1(new base::RunLoop());
776 cache_->Put(CopyFetchRequest(body_request_), response1.Pass(),
777 base::Bind(&CacheStorageCacheTest::ResponseAndErrorCallback,
778 base::Unretained(this), close_loop1.get()));
780 // Blocks on opening the cache entry.
781 base::RunLoop().RunUntilIdle();
783 delayable_backend->set_delay_open(false);
784 scoped_ptr<ServiceWorkerResponse> response2 =
785 CopyFetchResponse(body_response_);
786 response2->status_code = 2;
787 scoped_ptr<base::RunLoop> close_loop2(new base::RunLoop());
788 cache_->Put(CopyFetchRequest(body_request_), response2.Pass(),
789 base::Bind(&CacheStorageCacheTest::ResponseAndErrorCallback,
790 base::Unretained(this), close_loop2.get()));
792 // The second put operation should wait for the first to complete.
793 base::RunLoop().RunUntilIdle();
794 EXPECT_FALSE(callback_response_);
796 delayable_backend->OpenEntryContinue();
797 close_loop1->Run();
798 EXPECT_EQ(1, callback_response_->status_code);
799 close_loop2->Run();
800 EXPECT_EQ(2, callback_response_->status_code);
803 INSTANTIATE_TEST_CASE_P(CacheStorageCacheTest,
804 CacheStorageCacheTestP,
805 ::testing::Values(false, true));
807 } // namespace content