Add long running gmail memory benchmark for background tab.
[chromium-blink-merge.git] / content / browser / cache_storage / cache_storage_cache_unittest.cc
blobec4208b2a1d4c0977b0d83a1269dab89d5912977
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/run_loop.h"
11 #include "base/strings/string_split.h"
12 #include "base/thread_task_runner_handle.h"
13 #include "content/browser/fileapi/chrome_blob_storage_context.h"
14 #include "content/browser/fileapi/mock_url_request_delegate.h"
15 #include "content/browser/quota/mock_quota_manager_proxy.h"
16 #include "content/common/cache_storage/cache_storage_types.h"
17 #include "content/common/service_worker/service_worker_types.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "content/public/common/referrer.h"
20 #include "content/public/test/test_browser_context.h"
21 #include "content/public/test/test_browser_thread_bundle.h"
22 #include "net/base/test_completion_callback.h"
23 #include "net/url_request/url_request_context.h"
24 #include "net/url_request/url_request_context_getter.h"
25 #include "net/url_request/url_request_job_factory_impl.h"
26 #include "storage/browser/blob/blob_data_builder.h"
27 #include "storage/browser/blob/blob_data_handle.h"
28 #include "storage/browser/blob/blob_data_snapshot.h"
29 #include "storage/browser/blob/blob_storage_context.h"
30 #include "storage/browser/blob/blob_url_request_job_factory.h"
31 #include "storage/browser/quota/quota_manager_proxy.h"
32 #include "testing/gtest/include/gtest/gtest.h"
34 namespace content {
36 namespace {
37 const char kTestData[] = "Hello World";
39 // Returns a BlobProtocolHandler that uses |blob_storage_context|. Caller owns
40 // the memory.
41 storage::BlobProtocolHandler* CreateMockBlobProtocolHandler(
42 storage::BlobStorageContext* blob_storage_context) {
43 // The FileSystemContext and thread task runner are not actually used but a
44 // task runner is needed to avoid a DCHECK in BlobURLRequestJob ctor.
45 return new storage::BlobProtocolHandler(
46 blob_storage_context, NULL, base::ThreadTaskRunnerHandle::Get().get());
49 // A disk_cache::Backend wrapper that can delay operations.
50 class DelayableBackend : public disk_cache::Backend {
51 public:
52 DelayableBackend(scoped_ptr<disk_cache::Backend> backend)
53 : backend_(backend.Pass()), delay_open_(false) {}
55 // disk_cache::Backend overrides
56 net::CacheType GetCacheType() const override {
57 return backend_->GetCacheType();
59 int32 GetEntryCount() const override { return backend_->GetEntryCount(); }
60 int OpenEntry(const std::string& key,
61 disk_cache::Entry** entry,
62 const CompletionCallback& callback) override {
63 if (delay_open_) {
64 open_entry_callback_ =
65 base::Bind(&DelayableBackend::OpenEntryDelayedImpl,
66 base::Unretained(this), key, entry, callback);
67 return net::ERR_IO_PENDING;
70 return backend_->OpenEntry(key, entry, callback);
72 int CreateEntry(const std::string& key,
73 disk_cache::Entry** entry,
74 const CompletionCallback& callback) override {
75 return backend_->CreateEntry(key, entry, callback);
77 int DoomEntry(const std::string& key,
78 const CompletionCallback& callback) override {
79 return backend_->DoomEntry(key, callback);
81 int DoomAllEntries(const CompletionCallback& callback) override {
82 return backend_->DoomAllEntries(callback);
84 int DoomEntriesBetween(base::Time initial_time,
85 base::Time end_time,
86 const CompletionCallback& callback) override {
87 return backend_->DoomEntriesBetween(initial_time, end_time, callback);
89 int DoomEntriesSince(base::Time initial_time,
90 const CompletionCallback& callback) override {
91 return backend_->DoomEntriesSince(initial_time, callback);
93 scoped_ptr<Iterator> CreateIterator() override {
94 return backend_->CreateIterator();
96 void GetStats(base::StringPairs* stats) override {
97 return backend_->GetStats(stats);
99 void OnExternalCacheHit(const std::string& key) override {
100 return backend_->OnExternalCacheHit(key);
103 // Call to continue a delayed open.
104 void OpenEntryContinue() {
105 EXPECT_FALSE(open_entry_callback_.is_null());
106 open_entry_callback_.Run();
109 void set_delay_open(bool value) { delay_open_ = value; }
111 private:
112 void OpenEntryDelayedImpl(const std::string& key,
113 disk_cache::Entry** entry,
114 const CompletionCallback& callback) {
115 int rv = backend_->OpenEntry(key, entry, callback);
116 if (rv != net::ERR_IO_PENDING)
117 callback.Run(rv);
120 scoped_ptr<disk_cache::Backend> backend_;
121 bool delay_open_;
122 base::Closure open_entry_callback_;
125 } // namespace
127 // A CacheStorageCache that can optionally delay during backend creation.
128 class TestCacheStorageCache : public CacheStorageCache {
129 public:
130 TestCacheStorageCache(
131 const GURL& origin,
132 const base::FilePath& path,
133 const scoped_refptr<net::URLRequestContextGetter>& request_context_getter,
134 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
135 base::WeakPtr<storage::BlobStorageContext> blob_context)
136 : CacheStorageCache(origin,
137 path,
138 request_context_getter,
139 quota_manager_proxy,
140 blob_context),
141 delay_backend_creation_(false) {}
143 void CreateBackend(const ErrorCallback& callback) override {
144 backend_creation_callback_ = callback;
145 if (delay_backend_creation_)
146 return;
147 ContinueCreateBackend();
150 void ContinueCreateBackend() {
151 CacheStorageCache::CreateBackend(backend_creation_callback_);
154 void set_delay_backend_creation(bool delay) {
155 delay_backend_creation_ = delay;
158 // Swap the existing backend with a delayable one. The backend must have been
159 // created before calling this.
160 DelayableBackend* UseDelayableBackend() {
161 EXPECT_TRUE(backend_);
162 DelayableBackend* delayable_backend = new DelayableBackend(backend_.Pass());
163 backend_.reset(delayable_backend);
164 return delayable_backend;
167 private:
168 ~TestCacheStorageCache() override {}
170 bool delay_backend_creation_;
171 ErrorCallback backend_creation_callback_;
173 DISALLOW_COPY_AND_ASSIGN(TestCacheStorageCache);
176 class CacheStorageCacheTest : public testing::Test {
177 public:
178 CacheStorageCacheTest()
179 : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
180 callback_error_(CACHE_STORAGE_OK),
181 callback_closed_(false) {}
183 void SetUp() override {
184 ChromeBlobStorageContext* blob_storage_context =
185 ChromeBlobStorageContext::GetFor(&browser_context_);
186 // Wait for chrome_blob_storage_context to finish initializing.
187 base::RunLoop().RunUntilIdle();
188 blob_storage_context_ = blob_storage_context->context();
190 quota_manager_proxy_ = new MockQuotaManagerProxy(
191 nullptr, base::ThreadTaskRunnerHandle::Get().get());
193 url_request_job_factory_.reset(new net::URLRequestJobFactoryImpl);
194 url_request_job_factory_->SetProtocolHandler(
195 "blob", CreateMockBlobProtocolHandler(blob_storage_context->context()));
197 net::URLRequestContext* url_request_context =
198 browser_context_.GetRequestContext()->GetURLRequestContext();
200 url_request_context->set_job_factory(url_request_job_factory_.get());
202 CreateRequests(blob_storage_context);
204 if (!MemoryOnly())
205 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
206 base::FilePath path = MemoryOnly() ? base::FilePath() : temp_dir_.path();
208 cache_ = make_scoped_refptr(new TestCacheStorageCache(
209 GURL("http://example.com"), path, browser_context_.GetRequestContext(),
210 quota_manager_proxy_, blob_storage_context->context()->AsWeakPtr()));
213 void TearDown() override {
214 quota_manager_proxy_->SimulateQuotaManagerDestroyed();
215 base::RunLoop().RunUntilIdle();
218 void CreateRequests(ChromeBlobStorageContext* blob_storage_context) {
219 ServiceWorkerHeaderMap headers;
220 headers.insert(std::make_pair("a", "a"));
221 headers.insert(std::make_pair("b", "b"));
222 body_request_ =
223 ServiceWorkerFetchRequest(GURL("http://example.com/body.html"), "GET",
224 headers, Referrer(), false);
225 no_body_request_ =
226 ServiceWorkerFetchRequest(GURL("http://example.com/no_body.html"),
227 "GET", headers, Referrer(), false);
229 std::string expected_response;
230 for (int i = 0; i < 100; ++i)
231 expected_blob_data_ += kTestData;
233 scoped_ptr<storage::BlobDataBuilder> blob_data(
234 new storage::BlobDataBuilder("blob-id:myblob"));
235 blob_data->AppendData(expected_blob_data_);
237 blob_handle_ =
238 blob_storage_context->context()->AddFinishedBlob(blob_data.get());
240 body_response_ = ServiceWorkerResponse(
241 GURL("http://example.com/body.html"), 200, "OK",
242 blink::WebServiceWorkerResponseTypeDefault, headers,
243 blob_handle_->uuid(), expected_blob_data_.size(), GURL(),
244 blink::WebServiceWorkerResponseErrorUnknown);
246 no_body_response_ = ServiceWorkerResponse(
247 GURL("http://example.com/no_body.html"), 200, "OK",
248 blink::WebServiceWorkerResponseTypeDefault, headers, "", 0, GURL(),
249 blink::WebServiceWorkerResponseErrorUnknown);
252 scoped_ptr<ServiceWorkerFetchRequest> CopyFetchRequest(
253 const ServiceWorkerFetchRequest& request) {
254 return make_scoped_ptr(new ServiceWorkerFetchRequest(
255 request.url, request.method, request.headers, request.referrer,
256 request.is_reload));
259 CacheStorageError BatchOperation(
260 const std::vector<CacheStorageBatchOperation>& operations) {
261 scoped_ptr<base::RunLoop> loop(new base::RunLoop());
263 cache_->BatchOperation(
264 operations,
265 base::Bind(&CacheStorageCacheTest::ErrorTypeCallback,
266 base::Unretained(this), base::Unretained(loop.get())));
267 // TODO(jkarlin): These functions should use base::RunLoop().RunUntilIdle()
268 // once the cache uses a passed in task runner instead of the CACHE thread.
269 loop->Run();
271 return callback_error_;
274 bool Put(const ServiceWorkerFetchRequest& request,
275 const ServiceWorkerResponse& response) {
276 CacheStorageBatchOperation operation;
277 operation.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT;
278 operation.request = request;
279 operation.response = response;
281 CacheStorageError error =
282 BatchOperation(std::vector<CacheStorageBatchOperation>(1, operation));
283 return error == CACHE_STORAGE_OK;
286 bool Match(const ServiceWorkerFetchRequest& request) {
287 scoped_ptr<base::RunLoop> loop(new base::RunLoop());
289 cache_->Match(
290 CopyFetchRequest(request),
291 base::Bind(&CacheStorageCacheTest::ResponseAndErrorCallback,
292 base::Unretained(this), base::Unretained(loop.get())));
293 loop->Run();
295 return callback_error_ == CACHE_STORAGE_OK;
298 bool Delete(const ServiceWorkerFetchRequest& request) {
299 CacheStorageBatchOperation operation;
300 operation.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_DELETE;
301 operation.request = request;
303 CacheStorageError error =
304 BatchOperation(std::vector<CacheStorageBatchOperation>(1, operation));
305 return error == CACHE_STORAGE_OK;
308 bool Keys() {
309 scoped_ptr<base::RunLoop> loop(new base::RunLoop());
311 cache_->Keys(base::Bind(&CacheStorageCacheTest::RequestsCallback,
312 base::Unretained(this),
313 base::Unretained(loop.get())));
314 loop->Run();
316 return callback_error_ == CACHE_STORAGE_OK;
319 bool Close() {
320 scoped_ptr<base::RunLoop> loop(new base::RunLoop());
322 cache_->Close(base::Bind(&CacheStorageCacheTest::CloseCallback,
323 base::Unretained(this),
324 base::Unretained(loop.get())));
325 loop->Run();
326 return callback_closed_;
329 void RequestsCallback(base::RunLoop* run_loop,
330 CacheStorageError error,
331 scoped_ptr<CacheStorageCache::Requests> requests) {
332 callback_error_ = error;
333 callback_strings_.clear();
334 if (requests) {
335 for (size_t i = 0u; i < requests->size(); ++i)
336 callback_strings_.push_back(requests->at(i).url.spec());
338 if (run_loop)
339 run_loop->Quit();
342 void ErrorTypeCallback(base::RunLoop* run_loop, CacheStorageError error) {
343 callback_error_ = error;
344 if (run_loop)
345 run_loop->Quit();
348 void SequenceCallback(int sequence,
349 int* sequence_out,
350 base::RunLoop* run_loop,
351 CacheStorageError error) {
352 *sequence_out = sequence;
353 callback_error_ = error;
354 if (run_loop)
355 run_loop->Quit();
358 void ResponseAndErrorCallback(
359 base::RunLoop* run_loop,
360 CacheStorageError error,
361 scoped_ptr<ServiceWorkerResponse> response,
362 scoped_ptr<storage::BlobDataHandle> body_handle) {
363 callback_error_ = error;
364 callback_response_ = response.Pass();
365 callback_response_data_.reset();
366 if (error == CACHE_STORAGE_OK && !callback_response_->blob_uuid.empty())
367 callback_response_data_ = body_handle.Pass();
369 if (run_loop)
370 run_loop->Quit();
373 void CloseCallback(base::RunLoop* run_loop) {
374 EXPECT_FALSE(callback_closed_);
375 callback_closed_ = true;
376 if (run_loop)
377 run_loop->Quit();
380 void CopyBody(storage::BlobDataHandle* blob_handle, std::string* output) {
381 *output = std::string();
382 scoped_ptr<storage::BlobDataSnapshot> data = blob_handle->CreateSnapshot();
383 const auto& items = data->items();
384 for (const auto& item : items) {
385 switch (item->type()) {
386 case storage::DataElement::TYPE_BYTES: {
387 output->append(item->bytes(), item->length());
388 break;
390 case storage::DataElement::TYPE_DISK_CACHE_ENTRY: {
391 disk_cache::Entry* entry = item->disk_cache_entry();
392 int32 body_size = entry->GetDataSize(item->disk_cache_stream_index());
394 scoped_refptr<net::IOBuffer> io_buffer = new net::IOBuffer(body_size);
395 net::TestCompletionCallback callback;
396 int rv =
397 entry->ReadData(item->disk_cache_stream_index(), 0,
398 io_buffer.get(), body_size, callback.callback());
399 if (rv == net::ERR_IO_PENDING)
400 rv = callback.WaitForResult();
401 EXPECT_EQ(body_size, rv);
402 if (rv > 0)
403 output->append(io_buffer->data(), rv);
404 break;
406 default: { ADD_FAILURE() << "invalid response blob type"; } break;
411 bool VerifyKeys(const std::vector<std::string>& expected_keys) {
412 if (expected_keys.size() != callback_strings_.size())
413 return false;
415 std::set<std::string> found_set;
416 for (int i = 0, max = callback_strings_.size(); i < max; ++i)
417 found_set.insert(callback_strings_[i]);
419 for (int i = 0, max = expected_keys.size(); i < max; ++i) {
420 if (found_set.find(expected_keys[i]) == found_set.end())
421 return false;
423 return true;
426 bool TestResponseType(blink::WebServiceWorkerResponseType response_type) {
427 body_response_.response_type = response_type;
428 EXPECT_TRUE(Put(body_request_, body_response_));
429 EXPECT_TRUE(Match(body_request_));
430 EXPECT_TRUE(Delete(body_request_));
431 return response_type == callback_response_->response_type;
434 void VerifyAllOpsFail() {
435 EXPECT_FALSE(Put(no_body_request_, no_body_response_));
436 EXPECT_FALSE(Match(no_body_request_));
437 EXPECT_FALSE(Delete(body_request_));
438 EXPECT_FALSE(Keys());
441 virtual bool MemoryOnly() { return false; }
443 protected:
444 TestBrowserContext browser_context_;
445 TestBrowserThreadBundle browser_thread_bundle_;
446 scoped_ptr<net::URLRequestJobFactoryImpl> url_request_job_factory_;
447 scoped_refptr<MockQuotaManagerProxy> quota_manager_proxy_;
448 storage::BlobStorageContext* blob_storage_context_;
450 base::ScopedTempDir temp_dir_;
451 scoped_refptr<TestCacheStorageCache> cache_;
453 ServiceWorkerFetchRequest body_request_;
454 ServiceWorkerResponse body_response_;
455 ServiceWorkerFetchRequest no_body_request_;
456 ServiceWorkerResponse no_body_response_;
457 scoped_ptr<storage::BlobDataHandle> blob_handle_;
458 std::string expected_blob_data_;
460 CacheStorageError callback_error_;
461 scoped_ptr<ServiceWorkerResponse> callback_response_;
462 scoped_ptr<storage::BlobDataHandle> callback_response_data_;
463 std::vector<std::string> callback_strings_;
464 bool callback_closed_;
467 class CacheStorageCacheTestP : public CacheStorageCacheTest,
468 public testing::WithParamInterface<bool> {
469 bool MemoryOnly() override { return !GetParam(); }
472 class CacheStorageCacheMemoryOnlyTest
473 : public CacheStorageCacheTest,
474 public testing::WithParamInterface<bool> {
475 bool MemoryOnly() override { return true; }
478 TEST_P(CacheStorageCacheTestP, PutNoBody) {
479 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
482 TEST_P(CacheStorageCacheTestP, PutBody) {
483 EXPECT_TRUE(Put(body_request_, body_response_));
486 TEST_P(CacheStorageCacheTestP, PutBody_Multiple) {
487 CacheStorageBatchOperation operation1;
488 operation1.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT;
489 operation1.request = body_request_;
490 operation1.request.url = GURL("http://example.com/1");
491 operation1.response = body_response_;
492 operation1.response.url = GURL("http://example.com/1");
494 CacheStorageBatchOperation operation2;
495 operation2.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT;
496 operation2.request = body_request_;
497 operation2.request.url = GURL("http://example.com/2");
498 operation2.response = body_response_;
499 operation2.response.url = GURL("http://example.com/2");
501 CacheStorageBatchOperation operation3;
502 operation3.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT;
503 operation3.request = body_request_;
504 operation3.request.url = GURL("http://example.com/3");
505 operation3.response = body_response_;
506 operation3.response.url = GURL("http://example.com/3");
508 std::vector<CacheStorageBatchOperation> operations;
509 operations.push_back(operation1);
510 operations.push_back(operation2);
511 operations.push_back(operation3);
513 EXPECT_EQ(CACHE_STORAGE_OK, BatchOperation(operations));
514 EXPECT_TRUE(Match(operation1.request));
515 EXPECT_TRUE(Match(operation2.request));
516 EXPECT_TRUE(Match(operation3.request));
519 // TODO(nhiroki): Add a test for the case where one of PUT operations fails.
520 // Currently there is no handy way to fail only one operation in a batch.
521 // This could be easily achieved after adding some security checks in the
522 // browser side (http://crbug.com/425505).
524 TEST_P(CacheStorageCacheTestP, ResponseURLDiffersFromRequestURL) {
525 no_body_response_.url = GURL("http://example.com/foobar");
526 EXPECT_STRNE("http://example.com/foobar",
527 no_body_request_.url.spec().c_str());
528 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
529 EXPECT_TRUE(Match(no_body_request_));
530 EXPECT_STREQ("http://example.com/foobar",
531 callback_response_->url.spec().c_str());
534 TEST_P(CacheStorageCacheTestP, ResponseURLEmpty) {
535 no_body_response_.url = GURL();
536 EXPECT_STRNE("", no_body_request_.url.spec().c_str());
537 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
538 EXPECT_TRUE(Match(no_body_request_));
539 EXPECT_STREQ("", callback_response_->url.spec().c_str());
542 TEST_F(CacheStorageCacheTest, PutBodyDropBlobRef) {
543 CacheStorageBatchOperation operation;
544 operation.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT;
545 operation.request = body_request_;
546 operation.response = body_response_;
548 scoped_ptr<base::RunLoop> loop(new base::RunLoop());
549 cache_->BatchOperation(
550 std::vector<CacheStorageBatchOperation>(1, operation),
551 base::Bind(&CacheStorageCacheTestP::ErrorTypeCallback,
552 base::Unretained(this), base::Unretained(loop.get())));
553 // The handle should be held by the cache now so the deref here should be
554 // okay.
555 blob_handle_.reset();
556 loop->Run();
558 EXPECT_EQ(CACHE_STORAGE_OK, callback_error_);
561 TEST_P(CacheStorageCacheTestP, PutReplace) {
562 EXPECT_TRUE(Put(body_request_, no_body_response_));
563 EXPECT_TRUE(Match(body_request_));
564 EXPECT_FALSE(callback_response_data_);
566 EXPECT_TRUE(Put(body_request_, body_response_));
567 EXPECT_TRUE(Match(body_request_));
568 EXPECT_TRUE(callback_response_data_);
570 EXPECT_TRUE(Put(body_request_, no_body_response_));
571 EXPECT_TRUE(Match(body_request_));
572 EXPECT_FALSE(callback_response_data_);
575 TEST_P(CacheStorageCacheTestP, PutReplcaceInBatch) {
576 CacheStorageBatchOperation operation1;
577 operation1.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT;
578 operation1.request = body_request_;
579 operation1.response = no_body_response_;
581 CacheStorageBatchOperation operation2;
582 operation2.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT;
583 operation2.request = body_request_;
584 operation2.response = body_response_;
586 std::vector<CacheStorageBatchOperation> operations;
587 operations.push_back(operation1);
588 operations.push_back(operation2);
590 EXPECT_EQ(CACHE_STORAGE_OK, BatchOperation(operations));
592 // |operation2| should win.
593 EXPECT_TRUE(Match(operation2.request));
594 EXPECT_TRUE(callback_response_data_);
597 TEST_P(CacheStorageCacheTestP, MatchNoBody) {
598 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
599 EXPECT_TRUE(Match(no_body_request_));
600 EXPECT_EQ(200, callback_response_->status_code);
601 EXPECT_STREQ("OK", callback_response_->status_text.c_str());
602 EXPECT_STREQ("http://example.com/no_body.html",
603 callback_response_->url.spec().c_str());
604 EXPECT_STREQ("", callback_response_->blob_uuid.c_str());
605 EXPECT_EQ(0u, callback_response_->blob_size);
608 TEST_P(CacheStorageCacheTestP, MatchBody) {
609 EXPECT_TRUE(Put(body_request_, body_response_));
610 EXPECT_TRUE(Match(body_request_));
611 EXPECT_EQ(200, callback_response_->status_code);
612 EXPECT_STREQ("OK", callback_response_->status_text.c_str());
613 EXPECT_STREQ("http://example.com/body.html",
614 callback_response_->url.spec().c_str());
615 EXPECT_STRNE("", callback_response_->blob_uuid.c_str());
616 EXPECT_EQ(expected_blob_data_.size(), callback_response_->blob_size);
618 std::string response_body;
619 CopyBody(callback_response_data_.get(), &response_body);
620 EXPECT_STREQ(expected_blob_data_.c_str(), response_body.c_str());
623 TEST_P(CacheStorageCacheTestP, Vary) {
624 body_request_.headers["vary_foo"] = "foo";
625 body_response_.headers["vary"] = "vary_foo";
626 EXPECT_TRUE(Put(body_request_, body_response_));
627 EXPECT_TRUE(Match(body_request_));
629 body_request_.headers["vary_foo"] = "bar";
630 EXPECT_FALSE(Match(body_request_));
632 body_request_.headers.erase("vary_foo");
633 EXPECT_FALSE(Match(body_request_));
636 TEST_P(CacheStorageCacheTestP, EmptyVary) {
637 body_response_.headers["vary"] = "";
638 EXPECT_TRUE(Put(body_request_, body_response_));
639 EXPECT_TRUE(Match(body_request_));
641 body_request_.headers["zoo"] = "zoo";
642 EXPECT_TRUE(Match(body_request_));
645 TEST_P(CacheStorageCacheTestP, NoVaryButDiffHeaders) {
646 EXPECT_TRUE(Put(body_request_, body_response_));
647 EXPECT_TRUE(Match(body_request_));
649 body_request_.headers["zoo"] = "zoo";
650 EXPECT_TRUE(Match(body_request_));
653 TEST_P(CacheStorageCacheTestP, VaryMultiple) {
654 body_request_.headers["vary_foo"] = "foo";
655 body_request_.headers["vary_bar"] = "bar";
656 body_response_.headers["vary"] = " vary_foo , vary_bar";
657 EXPECT_TRUE(Put(body_request_, body_response_));
658 EXPECT_TRUE(Match(body_request_));
660 body_request_.headers["vary_bar"] = "foo";
661 EXPECT_FALSE(Match(body_request_));
663 body_request_.headers.erase("vary_bar");
664 EXPECT_FALSE(Match(body_request_));
667 TEST_P(CacheStorageCacheTestP, VaryNewHeader) {
668 body_request_.headers["vary_foo"] = "foo";
669 body_response_.headers["vary"] = " vary_foo, vary_bar";
670 EXPECT_TRUE(Put(body_request_, body_response_));
671 EXPECT_TRUE(Match(body_request_));
673 body_request_.headers["vary_bar"] = "bar";
674 EXPECT_FALSE(Match(body_request_));
677 TEST_P(CacheStorageCacheTestP, VaryStar) {
678 body_response_.headers["vary"] = "*";
679 EXPECT_TRUE(Put(body_request_, body_response_));
680 EXPECT_FALSE(Match(body_request_));
683 TEST_P(CacheStorageCacheTestP, EmptyKeys) {
684 EXPECT_TRUE(Keys());
685 EXPECT_EQ(0u, callback_strings_.size());
688 TEST_P(CacheStorageCacheTestP, TwoKeys) {
689 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
690 EXPECT_TRUE(Put(body_request_, body_response_));
691 EXPECT_TRUE(Keys());
692 EXPECT_EQ(2u, callback_strings_.size());
693 std::vector<std::string> expected_keys;
694 expected_keys.push_back(no_body_request_.url.spec());
695 expected_keys.push_back(body_request_.url.spec());
696 EXPECT_TRUE(VerifyKeys(expected_keys));
699 TEST_P(CacheStorageCacheTestP, TwoKeysThenOne) {
700 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
701 EXPECT_TRUE(Put(body_request_, body_response_));
702 EXPECT_TRUE(Keys());
703 EXPECT_EQ(2u, callback_strings_.size());
704 std::vector<std::string> expected_keys;
705 expected_keys.push_back(no_body_request_.url.spec());
706 expected_keys.push_back(body_request_.url.spec());
707 EXPECT_TRUE(VerifyKeys(expected_keys));
709 EXPECT_TRUE(Delete(body_request_));
710 EXPECT_TRUE(Keys());
711 EXPECT_EQ(1u, callback_strings_.size());
712 std::vector<std::string> expected_key;
713 expected_key.push_back(no_body_request_.url.spec());
714 EXPECT_TRUE(VerifyKeys(expected_key));
717 TEST_P(CacheStorageCacheTestP, DeleteNoBody) {
718 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
719 EXPECT_TRUE(Match(no_body_request_));
720 EXPECT_TRUE(Delete(no_body_request_));
721 EXPECT_FALSE(Match(no_body_request_));
722 EXPECT_FALSE(Delete(no_body_request_));
723 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
724 EXPECT_TRUE(Match(no_body_request_));
725 EXPECT_TRUE(Delete(no_body_request_));
728 TEST_P(CacheStorageCacheTestP, DeleteBody) {
729 EXPECT_TRUE(Put(body_request_, body_response_));
730 EXPECT_TRUE(Match(body_request_));
731 EXPECT_TRUE(Delete(body_request_));
732 EXPECT_FALSE(Match(body_request_));
733 EXPECT_FALSE(Delete(body_request_));
734 EXPECT_TRUE(Put(body_request_, body_response_));
735 EXPECT_TRUE(Match(body_request_));
736 EXPECT_TRUE(Delete(body_request_));
739 TEST_P(CacheStorageCacheTestP, QuickStressNoBody) {
740 for (int i = 0; i < 100; ++i) {
741 EXPECT_FALSE(Match(no_body_request_));
742 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
743 EXPECT_TRUE(Match(no_body_request_));
744 EXPECT_TRUE(Delete(no_body_request_));
748 TEST_P(CacheStorageCacheTestP, QuickStressBody) {
749 for (int i = 0; i < 100; ++i) {
750 ASSERT_FALSE(Match(body_request_));
751 ASSERT_TRUE(Put(body_request_, body_response_));
752 ASSERT_TRUE(Match(body_request_));
753 ASSERT_TRUE(Delete(body_request_));
757 TEST_P(CacheStorageCacheTestP, PutResponseType) {
758 EXPECT_TRUE(TestResponseType(blink::WebServiceWorkerResponseTypeBasic));
759 EXPECT_TRUE(TestResponseType(blink::WebServiceWorkerResponseTypeCORS));
760 EXPECT_TRUE(TestResponseType(blink::WebServiceWorkerResponseTypeDefault));
761 EXPECT_TRUE(TestResponseType(blink::WebServiceWorkerResponseTypeError));
762 EXPECT_TRUE(TestResponseType(blink::WebServiceWorkerResponseTypeOpaque));
765 TEST_F(CacheStorageCacheTest, CaselessServiceWorkerResponseHeaders) {
766 // CacheStorageCache depends on ServiceWorkerResponse having caseless
767 // headers so that it can quickly lookup vary headers.
768 ServiceWorkerResponse response(GURL("http://www.example.com"), 200, "OK",
769 blink::WebServiceWorkerResponseTypeDefault,
770 ServiceWorkerHeaderMap(), "", 0, GURL(),
771 blink::WebServiceWorkerResponseErrorUnknown);
772 response.headers["content-type"] = "foo";
773 response.headers["Content-Type"] = "bar";
774 EXPECT_EQ("bar", response.headers["content-type"]);
777 TEST_F(CacheStorageCacheTest, CaselessServiceWorkerFetchRequestHeaders) {
778 // CacheStorageCache depends on ServiceWorkerFetchRequest having caseless
779 // headers so that it can quickly lookup vary headers.
780 ServiceWorkerFetchRequest request(GURL("http://www.example.com"), "GET",
781 ServiceWorkerHeaderMap(), Referrer(),
782 false);
783 request.headers["content-type"] = "foo";
784 request.headers["Content-Type"] = "bar";
785 EXPECT_EQ("bar", request.headers["content-type"]);
788 TEST_P(CacheStorageCacheTestP, QuotaManagerModified) {
789 EXPECT_EQ(0, quota_manager_proxy_->notify_storage_modified_count());
791 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
792 EXPECT_EQ(1, quota_manager_proxy_->notify_storage_modified_count());
793 EXPECT_LT(0, quota_manager_proxy_->last_notified_delta());
794 int64 sum_delta = quota_manager_proxy_->last_notified_delta();
796 EXPECT_TRUE(Put(body_request_, body_response_));
797 EXPECT_EQ(2, quota_manager_proxy_->notify_storage_modified_count());
798 EXPECT_LT(sum_delta, quota_manager_proxy_->last_notified_delta());
799 sum_delta += quota_manager_proxy_->last_notified_delta();
801 EXPECT_TRUE(Delete(body_request_));
802 EXPECT_EQ(3, quota_manager_proxy_->notify_storage_modified_count());
803 sum_delta += quota_manager_proxy_->last_notified_delta();
805 EXPECT_TRUE(Delete(no_body_request_));
806 EXPECT_EQ(4, quota_manager_proxy_->notify_storage_modified_count());
807 sum_delta += quota_manager_proxy_->last_notified_delta();
809 EXPECT_EQ(0, sum_delta);
812 TEST_F(CacheStorageCacheMemoryOnlyTest, MemoryBackedSize) {
813 EXPECT_EQ(0, cache_->MemoryBackedSize());
814 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
815 EXPECT_LT(0, cache_->MemoryBackedSize());
816 int64 no_body_size = cache_->MemoryBackedSize();
818 EXPECT_TRUE(Delete(no_body_request_));
819 EXPECT_EQ(0, cache_->MemoryBackedSize());
821 EXPECT_TRUE(Put(body_request_, body_response_));
822 EXPECT_LT(no_body_size, cache_->MemoryBackedSize());
824 EXPECT_TRUE(Delete(body_request_));
825 EXPECT_EQ(0, cache_->MemoryBackedSize());
828 TEST_F(CacheStorageCacheTest, MemoryBackedSizePersistent) {
829 EXPECT_EQ(0, cache_->MemoryBackedSize());
830 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
831 EXPECT_EQ(0, cache_->MemoryBackedSize());
834 TEST_P(CacheStorageCacheTestP, OpsFailOnClosedBackendNeverCreated) {
835 cache_->set_delay_backend_creation(
836 true); // Will hang the test if a backend is created.
837 EXPECT_TRUE(Close());
838 VerifyAllOpsFail();
841 TEST_P(CacheStorageCacheTestP, OpsFailOnClosedBackend) {
842 // Create the backend and put something in it.
843 EXPECT_TRUE(Put(body_request_, body_response_));
844 EXPECT_TRUE(Close());
845 VerifyAllOpsFail();
848 TEST_P(CacheStorageCacheTestP, VerifySerialScheduling) {
849 // Start two operations, the first one is delayed but the second isn't. The
850 // second should wait for the first.
851 EXPECT_TRUE(Keys()); // Opens the backend.
852 DelayableBackend* delayable_backend = cache_->UseDelayableBackend();
853 delayable_backend->set_delay_open(true);
855 int sequence_out = -1;
857 CacheStorageBatchOperation operation1;
858 operation1.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT;
859 operation1.request = body_request_;
860 operation1.response = body_response_;
862 scoped_ptr<base::RunLoop> close_loop1(new base::RunLoop());
863 cache_->BatchOperation(
864 std::vector<CacheStorageBatchOperation>(1, operation1),
865 base::Bind(&CacheStorageCacheTest::SequenceCallback,
866 base::Unretained(this), 1, &sequence_out, close_loop1.get()));
868 // Blocks on opening the cache entry.
869 base::RunLoop().RunUntilIdle();
871 CacheStorageBatchOperation operation2;
872 operation2.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT;
873 operation2.request = body_request_;
874 operation2.response = body_response_;
876 delayable_backend->set_delay_open(false);
877 scoped_ptr<base::RunLoop> close_loop2(new base::RunLoop());
878 cache_->BatchOperation(
879 std::vector<CacheStorageBatchOperation>(1, operation2),
880 base::Bind(&CacheStorageCacheTest::SequenceCallback,
881 base::Unretained(this), 2, &sequence_out, close_loop2.get()));
883 // The second put operation should wait for the first to complete.
884 base::RunLoop().RunUntilIdle();
885 EXPECT_FALSE(callback_response_);
887 delayable_backend->OpenEntryContinue();
888 close_loop1->Run();
889 EXPECT_EQ(1, sequence_out);
890 close_loop2->Run();
891 EXPECT_EQ(2, sequence_out);
894 INSTANTIATE_TEST_CASE_P(CacheStorageCacheTest,
895 CacheStorageCacheTestP,
896 ::testing::Values(false, true));
898 } // namespace content