Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / browser / service_worker / service_worker_cache_unittest.cc
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.
4
5 #include "content/browser/service_worker/service_worker_cache.h"
6
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"
27
28 namespace content {
29
30 namespace {
31 const char kTestData[] = "Hello World";
32
33 // Returns a BlobProtocolHandler that uses |blob_storage_context|. Caller owns
34 // the memory.
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());
41 }
42
43 }  // namespace
44
45 // A ServiceWorkerCache that can optionally pause during backend creation.
46 class TestServiceWorkerCache : public ServiceWorkerCache {
47  public:
48   TestServiceWorkerCache(
49       const GURL& origin,
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,
55                            path,
56                            request_context,
57                            quota_manager_proxy,
58                            blob_context),
59         pause_backend_creation_(false) {}
60
61   virtual void CreateBackend(const ErrorCallback& callback) override {
62     backend_creation_callback_ = callback;
63     if (pause_backend_creation_)
64       return;
65     ContinueCreateBackend();
66   }
67
68   void ContinueCreateBackend() {
69     ServiceWorkerCache::CreateBackend(backend_creation_callback_);
70   }
71
72   void set_pause_backend_creation(bool pause) {
73     pause_backend_creation_ = pause;
74   }
75
76  private:
77   virtual ~TestServiceWorkerCache() override {}
78
79   bool pause_backend_creation_;
80   ErrorCallback backend_creation_callback_;
81
82   DISALLOW_COPY_AND_ASSIGN(TestServiceWorkerCache);
83 };
84
85 class ServiceWorkerCacheTest : public testing::Test {
86  public:
87   ServiceWorkerCacheTest()
88       : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
89         callback_error_(ServiceWorkerCache::ErrorTypeOK),
90         callback_closed_(false) {}
91
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();
98
99     quota_manager_proxy_ = new MockQuotaManagerProxy(
100         nullptr, base::MessageLoopProxy::current().get());
101
102     url_request_job_factory_.reset(new net::URLRequestJobFactoryImpl);
103     url_request_job_factory_->SetProtocolHandler(
104         "blob", CreateMockBlobProtocolHandler(blob_storage_context->context()));
105
106     net::URLRequestContext* url_request_context =
107         browser_context_.GetRequestContext()->GetURLRequestContext();
108
109     url_request_context->set_job_factory(url_request_job_factory_.get());
110
111     CreateRequests(blob_storage_context);
112
113     if (!MemoryOnly())
114       ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
115     base::FilePath path = MemoryOnly() ? base::FilePath() : temp_dir_.path();
116
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()));
120   }
121
122   void TearDown() override {
123     quota_manager_proxy_->SimulateQuotaManagerDestroyed();
124     base::RunLoop().RunUntilIdle();
125   }
126
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);
133     no_body_request_ =
134         ServiceWorkerFetchRequest(GURL("http://example.com/no_body.html"),
135                                   "GET",
136                                   headers,
137                                   GURL(""),
138                                   false);
139
140     std::string expected_response;
141     for (int i = 0; i < 100; ++i)
142       expected_blob_data_ += kTestData;
143
144     scoped_refptr<storage::BlobData> blob_data(
145         new storage::BlobData("blob-id:myblob"));
146     blob_data->AppendData(expected_blob_data_);
147
148     blob_handle_ =
149         blob_storage_context->context()->AddFinishedBlob(blob_data.get());
150
151     body_response_ =
152         ServiceWorkerResponse(GURL("http://example.com/body.html"),
153                               200,
154                               "OK",
155                               blink::WebServiceWorkerResponseTypeDefault,
156                               headers,
157                               blob_handle_->uuid(),
158                               expected_blob_data_.size());
159
160     no_body_response_ =
161         ServiceWorkerResponse(GURL("http://example.com/no_body.html"),
162                               200,
163                               "OK",
164                               blink::WebServiceWorkerResponseTypeDefault,
165                               headers,
166                               "",
167                               0);
168   }
169
170   scoped_ptr<ServiceWorkerFetchRequest> CopyFetchRequest(
171       const ServiceWorkerFetchRequest& request) {
172     return make_scoped_ptr(new ServiceWorkerFetchRequest(request.url,
173                                                          request.method,
174                                                          request.headers,
175                                                          request.referrer,
176                                                          request.is_reload));
177   }
178
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,
186                                   response.headers,
187                                   response.blob_uuid,
188                                   response.blob_size));
189     return sw_response.Pass();
190   }
191
192   bool Put(const ServiceWorkerFetchRequest& request,
193            const ServiceWorkerResponse& response) {
194     scoped_ptr<base::RunLoop> loop(new base::RunLoop());
195
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
203     // thread.
204     loop->Run();
205
206     return callback_error_ == ServiceWorkerCache::ErrorTypeOK;
207   }
208
209   bool Match(const ServiceWorkerFetchRequest& request) {
210     scoped_ptr<base::RunLoop> loop(new base::RunLoop());
211
212     cache_->Match(CopyFetchRequest(request),
213                   base::Bind(&ServiceWorkerCacheTest::ResponseAndErrorCallback,
214                              base::Unretained(this),
215                              base::Unretained(loop.get())));
216     loop->Run();
217
218     return callback_error_ == ServiceWorkerCache::ErrorTypeOK;
219   }
220
221   bool Delete(const ServiceWorkerFetchRequest& request) {
222     scoped_ptr<base::RunLoop> loop(new base::RunLoop());
223
224     cache_->Delete(CopyFetchRequest(request),
225                    base::Bind(&ServiceWorkerCacheTest::ErrorTypeCallback,
226                               base::Unretained(this),
227                               base::Unretained(loop.get())));
228     loop->Run();
229
230     return callback_error_ == ServiceWorkerCache::ErrorTypeOK;
231   }
232
233   bool Keys() {
234     scoped_ptr<base::RunLoop> loop(new base::RunLoop());
235
236     cache_->Keys(base::Bind(&ServiceWorkerCacheTest::RequestsCallback,
237                             base::Unretained(this),
238                             base::Unretained(loop.get())));
239     loop->Run();
240
241     return callback_error_ == ServiceWorkerCache::ErrorTypeOK;
242   }
243
244   bool Close() {
245     scoped_ptr<base::RunLoop> loop(new base::RunLoop());
246
247     cache_->Close(base::Bind(&ServiceWorkerCacheTest::CloseCallback,
248                              base::Unretained(this),
249                              base::Unretained(loop.get())));
250     loop->Run();
251     return callback_closed_;
252   }
253
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();
259     if (requests) {
260       for (size_t i = 0u; i < requests->size(); ++i)
261         callback_strings_.push_back(requests->at(i).url.spec());
262     }
263     if (run_loop)
264       run_loop->Quit();
265   }
266
267   void ErrorTypeCallback(base::RunLoop* run_loop,
268                          ServiceWorkerCache::ErrorType error) {
269     callback_error_ = error;
270     if (run_loop)
271       run_loop->Quit();
272   }
273
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();
285     }
286
287     if (run_loop)
288       run_loop->Quit();
289   }
290
291   void CloseCallback(base::RunLoop* run_loop) {
292     EXPECT_FALSE(callback_closed_);
293     callback_closed_ = true;
294     if (run_loop)
295       run_loop->Quit();
296   }
297
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());
303   }
304
305   bool VerifyKeys(const std::vector<std::string>& expected_keys) {
306     if (expected_keys.size() != callback_strings_.size())
307       return false;
308
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]);
312
313     for (int i = 0, max = expected_keys.size(); i < max; ++i) {
314       if (found_set.find(expected_keys[i]) == found_set.end())
315         return false;
316     }
317     return true;
318   }
319
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;
326   }
327
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());
333   }
334
335   virtual bool MemoryOnly() { return false; }
336
337  protected:
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_;
343
344   base::ScopedTempDir temp_dir_;
345   scoped_refptr<TestServiceWorkerCache> cache_;
346
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_;
353
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_;
359 };
360
361 class ServiceWorkerCacheTestP : public ServiceWorkerCacheTest,
362                                 public testing::WithParamInterface<bool> {
363   bool MemoryOnly() override { return !GetParam(); }
364 };
365
366 class ServiceWorkerCacheMemoryOnlyTest
367     : public ServiceWorkerCacheTest,
368       public testing::WithParamInterface<bool> {
369   bool MemoryOnly() override { return true; }
370 };
371
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);
380 }
381
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);
390
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());
394 }
395
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());
404 }
405
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());
412 }
413
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
422   // okay.
423   blob_handle_.reset();
424   loop->Run();
425
426   EXPECT_EQ(ServiceWorkerCache::ErrorTypeOK, callback_error_);
427 }
428
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_);
433
434   EXPECT_TRUE(Put(body_request_, body_response_));
435   EXPECT_TRUE(Match(body_request_));
436   EXPECT_TRUE(callback_response_data_);
437
438   EXPECT_TRUE(Put(body_request_, no_body_response_));
439   EXPECT_TRUE(Match(body_request_));
440   EXPECT_FALSE(callback_response_data_);
441 }
442
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);
452 }
453
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);
463
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());
467 }
468
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_));
474
475   body_request_.headers["vary_foo"] = "bar";
476   EXPECT_FALSE(Match(body_request_));
477
478   body_request_.headers.erase("vary_foo");
479   EXPECT_FALSE(Match(body_request_));
480 }
481
482 TEST_P(ServiceWorkerCacheTestP, EmptyVary) {
483   body_response_.headers["vary"] = "";
484   EXPECT_TRUE(Put(body_request_, body_response_));
485   EXPECT_TRUE(Match(body_request_));
486
487   body_request_.headers["zoo"] = "zoo";
488   EXPECT_TRUE(Match(body_request_));
489 }
490
491 TEST_P(ServiceWorkerCacheTestP, NoVaryButDiffHeaders) {
492   EXPECT_TRUE(Put(body_request_, body_response_));
493   EXPECT_TRUE(Match(body_request_));
494
495   body_request_.headers["zoo"] = "zoo";
496   EXPECT_TRUE(Match(body_request_));
497 }
498
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_));
505
506   body_request_.headers["vary_bar"] = "foo";
507   EXPECT_FALSE(Match(body_request_));
508
509   body_request_.headers.erase("vary_bar");
510   EXPECT_FALSE(Match(body_request_));
511 }
512
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_));
518
519   body_request_.headers["vary_bar"] = "bar";
520   EXPECT_FALSE(Match(body_request_));
521 }
522
523 TEST_P(ServiceWorkerCacheTestP, VaryStar) {
524   body_response_.headers["vary"] = "*";
525   EXPECT_TRUE(Put(body_request_, body_response_));
526   EXPECT_FALSE(Match(body_request_));
527 }
528
529 TEST_P(ServiceWorkerCacheTestP, EmptyKeys) {
530   EXPECT_TRUE(Keys());
531   EXPECT_EQ(0u, callback_strings_.size());
532 }
533
534 TEST_P(ServiceWorkerCacheTestP, TwoKeys) {
535   EXPECT_TRUE(Put(no_body_request_, no_body_response_));
536   EXPECT_TRUE(Put(body_request_, body_response_));
537   EXPECT_TRUE(Keys());
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));
543 }
544
545 TEST_P(ServiceWorkerCacheTestP, TwoKeysThenOne) {
546   EXPECT_TRUE(Put(no_body_request_, no_body_response_));
547   EXPECT_TRUE(Put(body_request_, body_response_));
548   EXPECT_TRUE(Keys());
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));
554
555   EXPECT_TRUE(Delete(body_request_));
556   EXPECT_TRUE(Keys());
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));
561 }
562
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_));
572 }
573
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_));
583 }
584
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_));
591   }
592 }
593
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_));
600   }
601 }
602
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));
609 }
610
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"),
615                                  200,
616                                  "OK",
617                                  blink::WebServiceWorkerResponseTypeDefault,
618                                  ServiceWorkerHeaderMap(),
619                                  "",
620                                  0);
621   response.headers["content-type"] = "foo";
622   response.headers["Content-Type"] = "bar";
623   EXPECT_EQ("bar", response.headers["content-type"]);
624 }
625
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"),
630                                          "GET",
631                                          ServiceWorkerHeaderMap(),
632                                          GURL(""),
633                                          false);
634   request.headers["content-type"] = "foo";
635   request.headers["Content-Type"] = "bar";
636   EXPECT_EQ("bar", request.headers["content-type"]);
637 }
638
639 TEST_P(ServiceWorkerCacheTestP, QuotaManagerModified) {
640   EXPECT_EQ(0, quota_manager_proxy_->notify_storage_modified_count());
641
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();
646
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();
651
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();
655
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();
659
660   EXPECT_EQ(0, sum_delta);
661 }
662
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();
668
669   EXPECT_TRUE(Delete(no_body_request_));
670   EXPECT_EQ(0, cache_->MemoryBackedSize());
671
672   EXPECT_TRUE(Put(body_request_, body_response_));
673   EXPECT_LT(no_body_size, cache_->MemoryBackedSize());
674
675   EXPECT_TRUE(Delete(body_request_));
676   EXPECT_EQ(0, cache_->MemoryBackedSize());
677 }
678
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());
683 }
684
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());
689   VerifyAllOpsFail();
690 }
691
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());
696   VerifyAllOpsFail();
697 }
698
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_);
713
714   cache_->ContinueCreateBackend();
715
716   close_loop->Run();
717   EXPECT_TRUE(callback_response_);
718   EXPECT_TRUE(callback_closed_);
719
720   VerifyAllOpsFail();
721 }
722
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_);
736
737   cache_->ContinueCreateBackend();
738
739   close_loop->Run();
740   EXPECT_EQ(ServiceWorkerCache::ErrorTypeNotFound, callback_error_);
741   EXPECT_TRUE(callback_closed_);
742
743   VerifyAllOpsFail();
744 }
745
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_);
759
760   cache_->ContinueCreateBackend();
761
762   close_loop->Run();
763   EXPECT_EQ(ServiceWorkerCache::ErrorTypeNotFound, callback_error_);
764   EXPECT_TRUE(callback_closed_);
765
766   VerifyAllOpsFail();
767 }
768
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_);
782
783   cache_->ContinueCreateBackend();
784
785   close_loop->Run();
786   EXPECT_EQ(ServiceWorkerCache::ErrorTypeOK, callback_error_);
787   EXPECT_TRUE(callback_closed_);
788
789   VerifyAllOpsFail();
790 }
791
792 INSTANTIATE_TEST_CASE_P(ServiceWorkerCacheTest,
793                         ServiceWorkerCacheTestP,
794                         ::testing::Values(false, true));
795
796 }  // namespace content