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/service_worker/service_worker_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/service_worker/service_worker_types.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "content/public/test/test_browser_context.h"
17 #include "content/public/test/test_browser_thread_bundle.h"
18 #include "net/url_request/url_request_context.h"
19 #include "net/url_request/url_request_context_getter.h"
20 #include "net/url_request/url_request_job_factory_impl.h"
21 #include "storage/browser/blob/blob_data_handle.h"
22 #include "storage/browser/blob/blob_storage_context.h"
23 #include "storage/browser/blob/blob_url_request_job_factory.h"
24 #include "storage/browser/quota/quota_manager_proxy.h"
25 #include "storage/common/blob/blob_data.h"
26 #include "testing/gtest/include/gtest/gtest.h"
31 const char kTestData[] = "Hello World";
33 // Returns a BlobProtocolHandler that uses |blob_storage_context|. Caller owns
35 storage::BlobProtocolHandler* CreateMockBlobProtocolHandler(
36 storage::BlobStorageContext* blob_storage_context) {
37 // The FileSystemContext and MessageLoopProxy are not actually used but a
38 // MessageLoopProxy is needed to avoid a DCHECK in BlobURLRequestJob ctor.
39 return new storage::BlobProtocolHandler(
40 blob_storage_context, NULL, base::MessageLoopProxy::current().get());
45 // A ServiceWorkerCache that can optionally pause during backend creation.
46 class TestServiceWorkerCache : public ServiceWorkerCache {
48 TestServiceWorkerCache(
50 const base::FilePath& path,
51 net::URLRequestContext* request_context,
52 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
53 base::WeakPtr<storage::BlobStorageContext> blob_context)
54 : ServiceWorkerCache(origin,
59 pause_backend_creation_(false) {}
61 virtual void CreateBackend(const ErrorCallback& callback) override {
62 backend_creation_callback_ = callback;
63 if (pause_backend_creation_)
65 ContinueCreateBackend();
68 void ContinueCreateBackend() {
69 ServiceWorkerCache::CreateBackend(backend_creation_callback_);
72 void set_pause_backend_creation(bool pause) {
73 pause_backend_creation_ = pause;
77 virtual ~TestServiceWorkerCache() override {}
79 bool pause_backend_creation_;
80 ErrorCallback backend_creation_callback_;
82 DISALLOW_COPY_AND_ASSIGN(TestServiceWorkerCache);
85 class ServiceWorkerCacheTest : public testing::Test {
87 ServiceWorkerCacheTest()
88 : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
89 callback_error_(ServiceWorkerCache::ErrorTypeOK),
90 callback_closed_(false) {}
92 void SetUp() override {
93 ChromeBlobStorageContext* blob_storage_context =
94 ChromeBlobStorageContext::GetFor(&browser_context_);
95 // Wait for chrome_blob_storage_context to finish initializing.
96 base::RunLoop().RunUntilIdle();
97 blob_storage_context_ = blob_storage_context->context();
99 quota_manager_proxy_ = new MockQuotaManagerProxy(
100 nullptr, base::MessageLoopProxy::current().get());
102 url_request_job_factory_.reset(new net::URLRequestJobFactoryImpl);
103 url_request_job_factory_->SetProtocolHandler(
104 "blob", CreateMockBlobProtocolHandler(blob_storage_context->context()));
106 net::URLRequestContext* url_request_context =
107 browser_context_.GetRequestContext()->GetURLRequestContext();
109 url_request_context->set_job_factory(url_request_job_factory_.get());
111 CreateRequests(blob_storage_context);
114 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
115 base::FilePath path = MemoryOnly() ? base::FilePath() : temp_dir_.path();
117 cache_ = make_scoped_refptr(new TestServiceWorkerCache(
118 GURL("http://example.com"), path, url_request_context,
119 quota_manager_proxy_, blob_storage_context->context()->AsWeakPtr()));
122 void TearDown() override {
123 quota_manager_proxy_->SimulateQuotaManagerDestroyed();
124 base::RunLoop().RunUntilIdle();
127 void CreateRequests(ChromeBlobStorageContext* blob_storage_context) {
128 ServiceWorkerHeaderMap headers;
129 headers.insert(std::make_pair("a", "a"));
130 headers.insert(std::make_pair("b", "b"));
131 body_request_ = ServiceWorkerFetchRequest(
132 GURL("http://example.com/body.html"), "GET", headers, GURL(""), false);
134 ServiceWorkerFetchRequest(GURL("http://example.com/no_body.html"),
140 std::string expected_response;
141 for (int i = 0; i < 100; ++i)
142 expected_blob_data_ += kTestData;
144 scoped_refptr<storage::BlobData> blob_data(
145 new storage::BlobData("blob-id:myblob"));
146 blob_data->AppendData(expected_blob_data_);
149 blob_storage_context->context()->AddFinishedBlob(blob_data.get());
152 ServiceWorkerResponse(GURL("http://example.com/body.html"),
155 blink::WebServiceWorkerResponseTypeDefault,
157 blob_handle_->uuid(),
158 expected_blob_data_.size());
161 ServiceWorkerResponse(GURL("http://example.com/no_body.html"),
164 blink::WebServiceWorkerResponseTypeDefault,
170 scoped_ptr<ServiceWorkerFetchRequest> CopyFetchRequest(
171 const ServiceWorkerFetchRequest& request) {
172 return make_scoped_ptr(new ServiceWorkerFetchRequest(request.url,
179 scoped_ptr<ServiceWorkerResponse> CopyFetchResponse(
180 const ServiceWorkerResponse& response) {
181 scoped_ptr<ServiceWorkerResponse> sw_response(
182 new ServiceWorkerResponse(response.url,
183 response.status_code,
184 response.status_text,
185 response.response_type,
188 response.blob_size));
189 return sw_response.Pass();
192 bool Put(const ServiceWorkerFetchRequest& request,
193 const ServiceWorkerResponse& response) {
194 scoped_ptr<base::RunLoop> loop(new base::RunLoop());
196 cache_->Put(CopyFetchRequest(request),
197 CopyFetchResponse(response),
198 base::Bind(&ServiceWorkerCacheTest::ResponseAndErrorCallback,
199 base::Unretained(this),
200 base::Unretained(loop.get())));
201 // TODO(jkarlin): These functions should use base::RunLoop().RunUntilIdle()
202 // once the cache uses a passed in MessageLoopProxy instead of the CACHE
206 return callback_error_ == ServiceWorkerCache::ErrorTypeOK;
209 bool Match(const ServiceWorkerFetchRequest& request) {
210 scoped_ptr<base::RunLoop> loop(new base::RunLoop());
212 cache_->Match(CopyFetchRequest(request),
213 base::Bind(&ServiceWorkerCacheTest::ResponseAndErrorCallback,
214 base::Unretained(this),
215 base::Unretained(loop.get())));
218 return callback_error_ == ServiceWorkerCache::ErrorTypeOK;
221 bool Delete(const ServiceWorkerFetchRequest& request) {
222 scoped_ptr<base::RunLoop> loop(new base::RunLoop());
224 cache_->Delete(CopyFetchRequest(request),
225 base::Bind(&ServiceWorkerCacheTest::ErrorTypeCallback,
226 base::Unretained(this),
227 base::Unretained(loop.get())));
230 return callback_error_ == ServiceWorkerCache::ErrorTypeOK;
234 scoped_ptr<base::RunLoop> loop(new base::RunLoop());
236 cache_->Keys(base::Bind(&ServiceWorkerCacheTest::RequestsCallback,
237 base::Unretained(this),
238 base::Unretained(loop.get())));
241 return callback_error_ == ServiceWorkerCache::ErrorTypeOK;
245 scoped_ptr<base::RunLoop> loop(new base::RunLoop());
247 cache_->Close(base::Bind(&ServiceWorkerCacheTest::CloseCallback,
248 base::Unretained(this),
249 base::Unretained(loop.get())));
251 return callback_closed_;
254 void RequestsCallback(base::RunLoop* run_loop,
255 ServiceWorkerCache::ErrorType error,
256 scoped_ptr<ServiceWorkerCache::Requests> requests) {
257 callback_error_ = error;
258 callback_strings_.clear();
260 for (size_t i = 0u; i < requests->size(); ++i)
261 callback_strings_.push_back(requests->at(i).url.spec());
267 void ErrorTypeCallback(base::RunLoop* run_loop,
268 ServiceWorkerCache::ErrorType error) {
269 callback_error_ = error;
274 void ResponseAndErrorCallback(
275 base::RunLoop* run_loop,
276 ServiceWorkerCache::ErrorType error,
277 scoped_ptr<ServiceWorkerResponse> response,
278 scoped_ptr<storage::BlobDataHandle> body_handle) {
279 callback_error_ = error;
280 callback_response_ = response.Pass();
281 callback_response_data_.reset();
282 if (error == ServiceWorkerCache::ErrorTypeOK &&
283 !callback_response_->blob_uuid.empty()) {
284 callback_response_data_ = body_handle.Pass();
291 void CloseCallback(base::RunLoop* run_loop) {
292 EXPECT_FALSE(callback_closed_);
293 callback_closed_ = true;
298 void CopyBody(storage::BlobDataHandle* blob_handle, std::string* output) {
299 storage::BlobData* data = blob_handle->data();
300 std::vector<storage::BlobData::Item> items = data->items();
301 for (size_t i = 0, max = items.size(); i < max; ++i)
302 output->append(items[i].bytes(), items[i].length());
305 bool VerifyKeys(const std::vector<std::string>& expected_keys) {
306 if (expected_keys.size() != callback_strings_.size())
309 std::set<std::string> found_set;
310 for (int i = 0, max = callback_strings_.size(); i < max; ++i)
311 found_set.insert(callback_strings_[i]);
313 for (int i = 0, max = expected_keys.size(); i < max; ++i) {
314 if (found_set.find(expected_keys[i]) == found_set.end())
320 bool TestResponseType(blink::WebServiceWorkerResponseType response_type) {
321 body_response_.response_type = response_type;
322 EXPECT_TRUE(Put(body_request_, body_response_));
323 EXPECT_TRUE(Match(body_request_));
324 EXPECT_TRUE(Delete(body_request_));
325 return response_type == callback_response_->response_type;
328 void VerifyAllOpsFail() {
329 EXPECT_FALSE(Put(no_body_request_, no_body_response_));
330 EXPECT_FALSE(Match(no_body_request_));
331 EXPECT_FALSE(Delete(body_request_));
332 EXPECT_FALSE(Keys());
335 virtual bool MemoryOnly() { return false; }
338 TestBrowserContext browser_context_;
339 TestBrowserThreadBundle browser_thread_bundle_;
340 scoped_ptr<net::URLRequestJobFactoryImpl> url_request_job_factory_;
341 scoped_refptr<MockQuotaManagerProxy> quota_manager_proxy_;
342 storage::BlobStorageContext* blob_storage_context_;
344 base::ScopedTempDir temp_dir_;
345 scoped_refptr<TestServiceWorkerCache> cache_;
347 ServiceWorkerFetchRequest body_request_;
348 ServiceWorkerResponse body_response_;
349 ServiceWorkerFetchRequest no_body_request_;
350 ServiceWorkerResponse no_body_response_;
351 scoped_ptr<storage::BlobDataHandle> blob_handle_;
352 std::string expected_blob_data_;
354 ServiceWorkerCache::ErrorType callback_error_;
355 scoped_ptr<ServiceWorkerResponse> callback_response_;
356 scoped_ptr<storage::BlobDataHandle> callback_response_data_;
357 std::vector<std::string> callback_strings_;
358 bool callback_closed_;
361 class ServiceWorkerCacheTestP : public ServiceWorkerCacheTest,
362 public testing::WithParamInterface<bool> {
363 bool MemoryOnly() override { return !GetParam(); }
366 class ServiceWorkerCacheMemoryOnlyTest
367 : public ServiceWorkerCacheTest,
368 public testing::WithParamInterface<bool> {
369 bool MemoryOnly() override { return true; }
372 TEST_P(ServiceWorkerCacheTestP, PutNoBody) {
373 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
374 EXPECT_TRUE(callback_response_);
375 EXPECT_STREQ(no_body_response_.url.spec().c_str(),
376 callback_response_->url.spec().c_str());
377 EXPECT_FALSE(callback_response_data_);
378 EXPECT_STREQ("", callback_response_->blob_uuid.c_str());
379 EXPECT_EQ(0u, callback_response_->blob_size);
382 TEST_P(ServiceWorkerCacheTestP, PutBody) {
383 EXPECT_TRUE(Put(body_request_, body_response_));
384 EXPECT_TRUE(callback_response_);
385 EXPECT_STREQ(body_response_.url.spec().c_str(),
386 callback_response_->url.spec().c_str());
387 EXPECT_TRUE(callback_response_data_);
388 EXPECT_STRNE("", callback_response_->blob_uuid.c_str());
389 EXPECT_EQ(expected_blob_data_.size(), callback_response_->blob_size);
391 std::string response_body;
392 CopyBody(callback_response_data_.get(), &response_body);
393 EXPECT_STREQ(expected_blob_data_.c_str(), response_body.c_str());
396 TEST_P(ServiceWorkerCacheTestP, ResponseURLDiffersFromRequestURL) {
397 no_body_response_.url = GURL("http://example.com/foobar");
398 EXPECT_STRNE("http://example.com/foobar",
399 no_body_request_.url.spec().c_str());
400 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
401 EXPECT_TRUE(Match(no_body_request_));
402 EXPECT_STREQ("http://example.com/foobar",
403 callback_response_->url.spec().c_str());
406 TEST_P(ServiceWorkerCacheTestP, ResponseURLEmpty) {
407 no_body_response_.url = GURL();
408 EXPECT_STRNE("", no_body_request_.url.spec().c_str());
409 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
410 EXPECT_TRUE(Match(no_body_request_));
411 EXPECT_STREQ("", callback_response_->url.spec().c_str());
414 TEST_F(ServiceWorkerCacheTest, PutBodyDropBlobRef) {
415 scoped_ptr<base::RunLoop> loop(new base::RunLoop());
416 cache_->Put(CopyFetchRequest(body_request_),
417 CopyFetchResponse(body_response_),
418 base::Bind(&ServiceWorkerCacheTestP::ResponseAndErrorCallback,
419 base::Unretained(this),
420 base::Unretained(loop.get())));
421 // The handle should be held by the cache now so the deref here should be
423 blob_handle_.reset();
426 EXPECT_EQ(ServiceWorkerCache::ErrorTypeOK, callback_error_);
429 TEST_P(ServiceWorkerCacheTestP, PutReplace) {
430 EXPECT_TRUE(Put(body_request_, no_body_response_));
431 EXPECT_TRUE(Match(body_request_));
432 EXPECT_FALSE(callback_response_data_);
434 EXPECT_TRUE(Put(body_request_, body_response_));
435 EXPECT_TRUE(Match(body_request_));
436 EXPECT_TRUE(callback_response_data_);
438 EXPECT_TRUE(Put(body_request_, no_body_response_));
439 EXPECT_TRUE(Match(body_request_));
440 EXPECT_FALSE(callback_response_data_);
443 TEST_P(ServiceWorkerCacheTestP, MatchNoBody) {
444 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
445 EXPECT_TRUE(Match(no_body_request_));
446 EXPECT_EQ(200, callback_response_->status_code);
447 EXPECT_STREQ("OK", callback_response_->status_text.c_str());
448 EXPECT_STREQ("http://example.com/no_body.html",
449 callback_response_->url.spec().c_str());
450 EXPECT_STREQ("", callback_response_->blob_uuid.c_str());
451 EXPECT_EQ(0u, callback_response_->blob_size);
454 TEST_P(ServiceWorkerCacheTestP, MatchBody) {
455 EXPECT_TRUE(Put(body_request_, body_response_));
456 EXPECT_TRUE(Match(body_request_));
457 EXPECT_EQ(200, callback_response_->status_code);
458 EXPECT_STREQ("OK", callback_response_->status_text.c_str());
459 EXPECT_STREQ("http://example.com/body.html",
460 callback_response_->url.spec().c_str());
461 EXPECT_STRNE("", callback_response_->blob_uuid.c_str());
462 EXPECT_EQ(expected_blob_data_.size(), callback_response_->blob_size);
464 std::string response_body;
465 CopyBody(callback_response_data_.get(), &response_body);
466 EXPECT_STREQ(expected_blob_data_.c_str(), response_body.c_str());
469 TEST_P(ServiceWorkerCacheTestP, Vary) {
470 body_request_.headers["vary_foo"] = "foo";
471 body_response_.headers["vary"] = "vary_foo";
472 EXPECT_TRUE(Put(body_request_, body_response_));
473 EXPECT_TRUE(Match(body_request_));
475 body_request_.headers["vary_foo"] = "bar";
476 EXPECT_FALSE(Match(body_request_));
478 body_request_.headers.erase("vary_foo");
479 EXPECT_FALSE(Match(body_request_));
482 TEST_P(ServiceWorkerCacheTestP, EmptyVary) {
483 body_response_.headers["vary"] = "";
484 EXPECT_TRUE(Put(body_request_, body_response_));
485 EXPECT_TRUE(Match(body_request_));
487 body_request_.headers["zoo"] = "zoo";
488 EXPECT_TRUE(Match(body_request_));
491 TEST_P(ServiceWorkerCacheTestP, NoVaryButDiffHeaders) {
492 EXPECT_TRUE(Put(body_request_, body_response_));
493 EXPECT_TRUE(Match(body_request_));
495 body_request_.headers["zoo"] = "zoo";
496 EXPECT_TRUE(Match(body_request_));
499 TEST_P(ServiceWorkerCacheTestP, VaryMultiple) {
500 body_request_.headers["vary_foo"] = "foo";
501 body_request_.headers["vary_bar"] = "bar";
502 body_response_.headers["vary"] = " vary_foo , vary_bar";
503 EXPECT_TRUE(Put(body_request_, body_response_));
504 EXPECT_TRUE(Match(body_request_));
506 body_request_.headers["vary_bar"] = "foo";
507 EXPECT_FALSE(Match(body_request_));
509 body_request_.headers.erase("vary_bar");
510 EXPECT_FALSE(Match(body_request_));
513 TEST_P(ServiceWorkerCacheTestP, VaryNewHeader) {
514 body_request_.headers["vary_foo"] = "foo";
515 body_response_.headers["vary"] = " vary_foo, vary_bar";
516 EXPECT_TRUE(Put(body_request_, body_response_));
517 EXPECT_TRUE(Match(body_request_));
519 body_request_.headers["vary_bar"] = "bar";
520 EXPECT_FALSE(Match(body_request_));
523 TEST_P(ServiceWorkerCacheTestP, VaryStar) {
524 body_response_.headers["vary"] = "*";
525 EXPECT_TRUE(Put(body_request_, body_response_));
526 EXPECT_FALSE(Match(body_request_));
529 TEST_P(ServiceWorkerCacheTestP, EmptyKeys) {
531 EXPECT_EQ(0u, callback_strings_.size());
534 TEST_P(ServiceWorkerCacheTestP, TwoKeys) {
535 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
536 EXPECT_TRUE(Put(body_request_, body_response_));
538 EXPECT_EQ(2u, callback_strings_.size());
539 std::vector<std::string> expected_keys;
540 expected_keys.push_back(no_body_request_.url.spec());
541 expected_keys.push_back(body_request_.url.spec());
542 EXPECT_TRUE(VerifyKeys(expected_keys));
545 TEST_P(ServiceWorkerCacheTestP, TwoKeysThenOne) {
546 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
547 EXPECT_TRUE(Put(body_request_, body_response_));
549 EXPECT_EQ(2u, callback_strings_.size());
550 std::vector<std::string> expected_keys;
551 expected_keys.push_back(no_body_request_.url.spec());
552 expected_keys.push_back(body_request_.url.spec());
553 EXPECT_TRUE(VerifyKeys(expected_keys));
555 EXPECT_TRUE(Delete(body_request_));
557 EXPECT_EQ(1u, callback_strings_.size());
558 std::vector<std::string> expected_key;
559 expected_key.push_back(no_body_request_.url.spec());
560 EXPECT_TRUE(VerifyKeys(expected_key));
563 TEST_P(ServiceWorkerCacheTestP, DeleteNoBody) {
564 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
565 EXPECT_TRUE(Match(no_body_request_));
566 EXPECT_TRUE(Delete(no_body_request_));
567 EXPECT_FALSE(Match(no_body_request_));
568 EXPECT_FALSE(Delete(no_body_request_));
569 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
570 EXPECT_TRUE(Match(no_body_request_));
571 EXPECT_TRUE(Delete(no_body_request_));
574 TEST_P(ServiceWorkerCacheTestP, DeleteBody) {
575 EXPECT_TRUE(Put(body_request_, body_response_));
576 EXPECT_TRUE(Match(body_request_));
577 EXPECT_TRUE(Delete(body_request_));
578 EXPECT_FALSE(Match(body_request_));
579 EXPECT_FALSE(Delete(body_request_));
580 EXPECT_TRUE(Put(body_request_, body_response_));
581 EXPECT_TRUE(Match(body_request_));
582 EXPECT_TRUE(Delete(body_request_));
585 TEST_P(ServiceWorkerCacheTestP, QuickStressNoBody) {
586 for (int i = 0; i < 100; ++i) {
587 EXPECT_FALSE(Match(no_body_request_));
588 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
589 EXPECT_TRUE(Match(no_body_request_));
590 EXPECT_TRUE(Delete(no_body_request_));
594 TEST_P(ServiceWorkerCacheTestP, QuickStressBody) {
595 for (int i = 0; i < 100; ++i) {
596 ASSERT_FALSE(Match(body_request_));
597 ASSERT_TRUE(Put(body_request_, body_response_));
598 ASSERT_TRUE(Match(body_request_));
599 ASSERT_TRUE(Delete(body_request_));
603 TEST_P(ServiceWorkerCacheTestP, PutResponseType) {
604 EXPECT_TRUE(TestResponseType(blink::WebServiceWorkerResponseTypeBasic));
605 EXPECT_TRUE(TestResponseType(blink::WebServiceWorkerResponseTypeCORS));
606 EXPECT_TRUE(TestResponseType(blink::WebServiceWorkerResponseTypeDefault));
607 EXPECT_TRUE(TestResponseType(blink::WebServiceWorkerResponseTypeError));
608 EXPECT_TRUE(TestResponseType(blink::WebServiceWorkerResponseTypeOpaque));
611 TEST_F(ServiceWorkerCacheTest, CaselessServiceWorkerResponseHeaders) {
612 // ServiceWorkerCache depends on ServiceWorkerResponse having caseless
613 // headers so that it can quickly lookup vary headers.
614 ServiceWorkerResponse response(GURL("http://www.example.com"),
617 blink::WebServiceWorkerResponseTypeDefault,
618 ServiceWorkerHeaderMap(),
621 response.headers["content-type"] = "foo";
622 response.headers["Content-Type"] = "bar";
623 EXPECT_EQ("bar", response.headers["content-type"]);
626 TEST_F(ServiceWorkerCacheTest, CaselessServiceWorkerFetchRequestHeaders) {
627 // ServiceWorkerCache depends on ServiceWorkerFetchRequest having caseless
628 // headers so that it can quickly lookup vary headers.
629 ServiceWorkerFetchRequest request(GURL("http://www.example.com"),
631 ServiceWorkerHeaderMap(),
634 request.headers["content-type"] = "foo";
635 request.headers["Content-Type"] = "bar";
636 EXPECT_EQ("bar", request.headers["content-type"]);
639 TEST_P(ServiceWorkerCacheTestP, QuotaManagerModified) {
640 EXPECT_EQ(0, quota_manager_proxy_->notify_storage_modified_count());
642 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
643 EXPECT_EQ(1, quota_manager_proxy_->notify_storage_modified_count());
644 EXPECT_LT(0, quota_manager_proxy_->last_notified_delta());
645 int64 sum_delta = quota_manager_proxy_->last_notified_delta();
647 EXPECT_TRUE(Put(body_request_, body_response_));
648 EXPECT_EQ(2, quota_manager_proxy_->notify_storage_modified_count());
649 EXPECT_LT(sum_delta, quota_manager_proxy_->last_notified_delta());
650 sum_delta += quota_manager_proxy_->last_notified_delta();
652 EXPECT_TRUE(Delete(body_request_));
653 EXPECT_EQ(3, quota_manager_proxy_->notify_storage_modified_count());
654 sum_delta += quota_manager_proxy_->last_notified_delta();
656 EXPECT_TRUE(Delete(no_body_request_));
657 EXPECT_EQ(4, quota_manager_proxy_->notify_storage_modified_count());
658 sum_delta += quota_manager_proxy_->last_notified_delta();
660 EXPECT_EQ(0, sum_delta);
663 TEST_F(ServiceWorkerCacheMemoryOnlyTest, MemoryBackedSize) {
664 EXPECT_EQ(0, cache_->MemoryBackedSize());
665 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
666 EXPECT_LT(0, cache_->MemoryBackedSize());
667 int64 no_body_size = cache_->MemoryBackedSize();
669 EXPECT_TRUE(Delete(no_body_request_));
670 EXPECT_EQ(0, cache_->MemoryBackedSize());
672 EXPECT_TRUE(Put(body_request_, body_response_));
673 EXPECT_LT(no_body_size, cache_->MemoryBackedSize());
675 EXPECT_TRUE(Delete(body_request_));
676 EXPECT_EQ(0, cache_->MemoryBackedSize());
679 TEST_F(ServiceWorkerCacheTest, MemoryBackedSizePersistent) {
680 EXPECT_EQ(0, cache_->MemoryBackedSize());
681 EXPECT_TRUE(Put(no_body_request_, no_body_response_));
682 EXPECT_EQ(0, cache_->MemoryBackedSize());
685 TEST_P(ServiceWorkerCacheTestP, OpsFailOnClosedBackendNeverCreated) {
686 cache_->set_pause_backend_creation(
687 true); // Will hang the test if a backend is created.
688 EXPECT_TRUE(Close());
692 TEST_P(ServiceWorkerCacheTestP, OpsFailOnClosedBackend) {
693 // Create the backend and put something in it.
694 EXPECT_TRUE(Put(body_request_, body_response_));
695 EXPECT_TRUE(Close());
699 TEST_F(ServiceWorkerCacheTest, ClosedDuringPut) {
700 // Even though Close is called in the middle of a Put operation (during
701 // backend creation), the put operation should still finish.
702 cache_->set_pause_backend_creation(true);
703 scoped_ptr<base::RunLoop> close_loop(new base::RunLoop());
704 cache_->Put(CopyFetchRequest(body_request_),
705 CopyFetchResponse(body_response_),
706 base::Bind(&ServiceWorkerCacheTest::ResponseAndErrorCallback,
707 base::Unretained(this), nullptr));
708 cache_->Close(base::Bind(&ServiceWorkerCacheTest::CloseCallback,
709 base::Unretained(this), close_loop.get()));
710 base::RunLoop().RunUntilIdle();
711 EXPECT_FALSE(callback_response_);
712 EXPECT_FALSE(callback_closed_);
714 cache_->ContinueCreateBackend();
717 EXPECT_TRUE(callback_response_);
718 EXPECT_TRUE(callback_closed_);
723 TEST_F(ServiceWorkerCacheTest, ClosedDuringMatch) {
724 // Even though Close is called in the middle of a Match operation (during
725 // backend creation), the match operation should still finish.
726 cache_->set_pause_backend_creation(true);
727 scoped_ptr<base::RunLoop> close_loop(new base::RunLoop());
728 cache_->Match(CopyFetchRequest(body_request_),
729 base::Bind(&ServiceWorkerCacheTest::ResponseAndErrorCallback,
730 base::Unretained(this), nullptr));
731 cache_->Close(base::Bind(&ServiceWorkerCacheTest::CloseCallback,
732 base::Unretained(this), close_loop.get()));
733 base::RunLoop().RunUntilIdle();
734 EXPECT_EQ(ServiceWorkerCache::ErrorTypeOK, callback_error_);
735 EXPECT_FALSE(callback_closed_);
737 cache_->ContinueCreateBackend();
740 EXPECT_EQ(ServiceWorkerCache::ErrorTypeNotFound, callback_error_);
741 EXPECT_TRUE(callback_closed_);
746 TEST_F(ServiceWorkerCacheTest, ClosedDuringDelete) {
747 // Even though Close is called in the middle of a Delete operation (during
748 // backend creation), the delete operation should still finish.
749 cache_->set_pause_backend_creation(true);
750 scoped_ptr<base::RunLoop> close_loop(new base::RunLoop());
751 cache_->Delete(CopyFetchRequest(body_request_),
752 base::Bind(&ServiceWorkerCacheTest::ErrorTypeCallback,
753 base::Unretained(this), nullptr));
754 cache_->Close(base::Bind(&ServiceWorkerCacheTest::CloseCallback,
755 base::Unretained(this), close_loop.get()));
756 base::RunLoop().RunUntilIdle();
757 EXPECT_EQ(ServiceWorkerCache::ErrorTypeOK, callback_error_);
758 EXPECT_FALSE(callback_closed_);
760 cache_->ContinueCreateBackend();
763 EXPECT_EQ(ServiceWorkerCache::ErrorTypeNotFound, callback_error_);
764 EXPECT_TRUE(callback_closed_);
769 TEST_F(ServiceWorkerCacheTest, ClosedDuringKeys) {
770 // Even though Close is called in the middle of a Keys operation (during
771 // backend creation), the keys operation should still finish.
772 cache_->set_pause_backend_creation(true);
773 scoped_ptr<base::RunLoop> close_loop(new base::RunLoop());
774 callback_error_ = ServiceWorkerCache::ErrorTypeNotFound;
775 cache_->Keys(base::Bind(&ServiceWorkerCacheTest::RequestsCallback,
776 base::Unretained(this), nullptr));
777 cache_->Close(base::Bind(&ServiceWorkerCacheTest::CloseCallback,
778 base::Unretained(this), close_loop.get()));
779 base::RunLoop().RunUntilIdle();
780 EXPECT_EQ(ServiceWorkerCache::ErrorTypeNotFound, callback_error_);
781 EXPECT_FALSE(callback_closed_);
783 cache_->ContinueCreateBackend();
786 EXPECT_EQ(ServiceWorkerCache::ErrorTypeOK, callback_error_);
787 EXPECT_TRUE(callback_closed_);
792 INSTANTIATE_TEST_CASE_P(ServiceWorkerCacheTest,
793 ServiceWorkerCacheTestP,
794 ::testing::Values(false, true));
796 } // namespace content