Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / content / browser / appcache / mock_appcache_storage_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 "base/run_loop.h"
6 #include "content/browser/appcache/mock_appcache_service.h"
7 #include "testing/gtest/include/gtest/gtest.h"
8 #include "webkit/browser/appcache/appcache.h"
9 #include "webkit/browser/appcache/appcache_group.h"
10 #include "webkit/browser/appcache/appcache_response.h"
11 #include "webkit/browser/appcache/appcache_storage.h"
12
13 using appcache::AppCache;
14 using appcache::AppCacheEntry;
15 using appcache::AppCacheGroup;
16 using appcache::AppCacheStorage;
17 using appcache::FALLBACK_NAMESPACE;
18 using appcache::INTERCEPT_NAMESPACE;
19 using appcache::kNoCacheId;
20 using appcache::kNoResponseId;
21 using appcache::Manifest;
22 using appcache::Namespace;
23 using appcache::NETWORK_NAMESPACE;
24
25 namespace content {
26
27 class MockAppCacheStorageTest : public testing::Test {
28  public:
29   class MockStorageDelegate : public AppCacheStorage::Delegate {
30    public:
31     explicit MockStorageDelegate()
32         : loaded_cache_id_(0), stored_group_success_(false),
33           obsoleted_success_(false), found_cache_id_(kNoCacheId) {
34     }
35
36     virtual void OnCacheLoaded(AppCache* cache, int64 cache_id) OVERRIDE {
37       loaded_cache_ = cache;
38       loaded_cache_id_ = cache_id;
39     }
40
41     virtual void OnGroupLoaded(AppCacheGroup* group,
42                                const GURL& manifest_url) OVERRIDE {
43       loaded_group_ = group;
44       loaded_manifest_url_ = manifest_url;
45     }
46
47     virtual void OnGroupAndNewestCacheStored(
48         AppCacheGroup* group, AppCache* newest_cache, bool success,
49         bool would_exceed_quota) OVERRIDE {
50       stored_group_ = group;
51       stored_group_success_ = success;
52     }
53
54     virtual void OnGroupMadeObsolete(AppCacheGroup* group,
55                                      bool success,
56                                      int response_code) OVERRIDE {
57       obsoleted_group_ = group;
58       obsoleted_success_ = success;
59     }
60
61     virtual void OnMainResponseFound(const GURL& url,
62                                      const AppCacheEntry& entry,
63                                      const GURL& fallback_url,
64                                      const AppCacheEntry& fallback_entry,
65                                      int64 cache_id,
66                                      int64 group_id,
67                                      const GURL& manifest_url) OVERRIDE {
68       found_url_ = url;
69       found_entry_ = entry;
70       found_fallback_url_ = fallback_url;
71       found_fallback_entry_ = fallback_entry;
72       found_cache_id_ = cache_id;
73       found_manifest_url_ = manifest_url;
74     }
75
76     scoped_refptr<AppCache> loaded_cache_;
77     int64 loaded_cache_id_;
78     scoped_refptr<AppCacheGroup> loaded_group_;
79     GURL loaded_manifest_url_;
80     scoped_refptr<AppCacheGroup> stored_group_;
81     bool stored_group_success_;
82     scoped_refptr<AppCacheGroup> obsoleted_group_;
83     bool obsoleted_success_;
84     GURL found_url_;
85     AppCacheEntry found_entry_;
86     GURL found_fallback_url_;
87     AppCacheEntry found_fallback_entry_;
88     int64 found_cache_id_;
89     GURL found_manifest_url_;
90   };
91
92  private:
93   base::MessageLoop message_loop_;
94 };
95
96 TEST_F(MockAppCacheStorageTest, LoadCache_Miss) {
97   // Attempt to load a cache that doesn't exist. Should
98   // complete asyncly.
99   MockAppCacheService service;
100   MockStorageDelegate delegate;
101   service.storage()->LoadCache(111, &delegate);
102   EXPECT_NE(111, delegate.loaded_cache_id_);
103   base::RunLoop().RunUntilIdle();  // Do async task execution.
104   EXPECT_EQ(111, delegate.loaded_cache_id_);
105   EXPECT_FALSE(delegate.loaded_cache_.get());
106 }
107
108 TEST_F(MockAppCacheStorageTest, LoadCache_NearHit) {
109   // Attempt to load a cache that is currently in use
110   // and does not require loading from disk. This
111   // load should complete syncly.
112   MockAppCacheService service;
113
114   // Setup some preconditions. Make an 'unstored' cache for
115   // us to load. The ctor should put it in the working set.
116   int64 cache_id = service.storage()->NewCacheId();
117   scoped_refptr<AppCache> cache(new AppCache(service.storage(), cache_id));
118
119   // Conduct the test.
120   MockStorageDelegate delegate;
121   service.storage()->LoadCache(cache_id, &delegate);
122   EXPECT_EQ(cache_id, delegate.loaded_cache_id_);
123   EXPECT_EQ(cache.get(), delegate.loaded_cache_.get());
124 }
125
126 TEST_F(MockAppCacheStorageTest, CreateGroup) {
127   // Attempt to load/create a group that doesn't exist.
128   // Should complete asyncly.
129   MockAppCacheService service;
130   MockAppCacheStorage* storage =
131       reinterpret_cast<MockAppCacheStorage*>(service.storage());
132   MockStorageDelegate delegate;
133   GURL manifest_url("http://blah/");
134   service.storage()->LoadOrCreateGroup(manifest_url, &delegate);
135   EXPECT_NE(manifest_url, delegate.loaded_manifest_url_);
136   EXPECT_FALSE(delegate.loaded_group_.get());
137   base::RunLoop().RunUntilIdle();  // Do async task execution.
138   EXPECT_EQ(manifest_url, delegate.loaded_manifest_url_);
139   EXPECT_TRUE(delegate.loaded_group_.get());
140   EXPECT_TRUE(delegate.loaded_group_->HasOneRef());
141   EXPECT_FALSE(delegate.loaded_group_->newest_complete_cache());
142   EXPECT_TRUE(storage->stored_groups_.empty());
143 }
144
145 TEST_F(MockAppCacheStorageTest, LoadGroup_NearHit) {
146   // Attempt to load a group that is currently in use
147   // and does not require loading from disk. This
148   // load should complete syncly.
149   MockAppCacheService service;
150   MockStorageDelegate delegate;
151
152   // Setup some preconditions. Create a group that appears
153   // to be "unstored" and "currently in use".
154   GURL manifest_url("http://blah/");
155   service.storage()->LoadOrCreateGroup(manifest_url, &delegate);
156   base::RunLoop().RunUntilIdle();  // Do async task execution.
157   EXPECT_EQ(manifest_url, delegate.loaded_manifest_url_);
158   EXPECT_TRUE(delegate.loaded_group_.get());
159
160   // Reset our delegate, and take a reference to the new group.
161   scoped_refptr<AppCacheGroup> group;
162   group.swap(delegate.loaded_group_);
163   delegate.loaded_manifest_url_ = GURL();
164
165   // Conduct the test.
166   service.storage()->LoadOrCreateGroup(manifest_url, &delegate);
167   EXPECT_EQ(manifest_url, delegate.loaded_manifest_url_);
168   EXPECT_EQ(group.get(), delegate.loaded_group_.get());
169 }
170
171 TEST_F(MockAppCacheStorageTest, LoadGroupAndCache_FarHit) {
172   // Attempt to load a cache that is not currently in use
173   // and does require loading from disk. This
174   // load should complete asyncly.
175   MockAppCacheService service;
176   MockAppCacheStorage* storage =
177       reinterpret_cast<MockAppCacheStorage*>(service.storage());
178
179   // Setup some preconditions. Create a group and newest cache that
180   // appears to be "stored" and "not currently in use".
181   GURL manifest_url("http://blah/");
182   scoped_refptr<AppCacheGroup> group(
183       new AppCacheGroup(service.storage(), manifest_url, 111));
184   int64 cache_id = storage->NewCacheId();
185   scoped_refptr<AppCache> cache(new AppCache(service.storage(), cache_id));
186   cache->set_complete(true);
187   group->AddCache(cache.get());
188   storage->AddStoredGroup(group.get());
189   storage->AddStoredCache(cache.get());
190
191   // Drop the references from above so the only refs to these
192   // objects are from within the storage class. This is to make
193   // these objects appear as "not currently in use".
194   AppCache* cache_ptr = cache.get();
195   AppCacheGroup* group_ptr = group.get();
196   cache = NULL;
197   group = NULL;
198
199   // Setup a delegate to receive completion callbacks.
200   MockStorageDelegate delegate;
201
202   // Conduct the cache load test.
203   EXPECT_NE(cache_id, delegate.loaded_cache_id_);
204   EXPECT_NE(cache_ptr, delegate.loaded_cache_.get());
205   storage->LoadCache(cache_id, &delegate);
206   EXPECT_NE(cache_id, delegate.loaded_cache_id_);
207   EXPECT_NE(cache_ptr, delegate.loaded_cache_.get());
208   base::RunLoop().RunUntilIdle();  // Do async task execution.
209   EXPECT_EQ(cache_id, delegate.loaded_cache_id_);
210   EXPECT_EQ(cache_ptr, delegate.loaded_cache_.get());
211   delegate.loaded_cache_ = NULL;
212
213   // Conduct the group load test.
214   EXPECT_NE(manifest_url, delegate.loaded_manifest_url_);
215   EXPECT_FALSE(delegate.loaded_group_.get());
216   storage->LoadOrCreateGroup(manifest_url, &delegate);
217   EXPECT_NE(manifest_url, delegate.loaded_manifest_url_);
218   EXPECT_FALSE(delegate.loaded_group_.get());
219   base::RunLoop().RunUntilIdle();  // Do async task execution.
220   EXPECT_EQ(manifest_url, delegate.loaded_manifest_url_);
221   EXPECT_EQ(group_ptr, delegate.loaded_group_.get());
222 }
223
224 TEST_F(MockAppCacheStorageTest, StoreNewGroup) {
225   // Store a group and its newest cache. Should complete asyncly.
226   MockAppCacheService service;
227   MockAppCacheStorage* storage =
228       reinterpret_cast<MockAppCacheStorage*>(service.storage());
229
230   // Setup some preconditions. Create a group and newest cache that
231   // appears to be "unstored".
232   GURL manifest_url("http://blah/");
233   scoped_refptr<AppCacheGroup> group(
234       new AppCacheGroup(service.storage(), manifest_url, 111));
235   int64 cache_id = storage->NewCacheId();
236   scoped_refptr<AppCache> cache(new AppCache(service.storage(), cache_id));
237   // Hold a ref to the cache simulate the UpdateJob holding that ref,
238   // and hold a ref to the group to simulate the CacheHost holding that ref.
239
240   // Conduct the store test.
241   MockStorageDelegate delegate;
242   EXPECT_TRUE(storage->stored_caches_.empty());
243   EXPECT_TRUE(storage->stored_groups_.empty());
244   storage->StoreGroupAndNewestCache(group.get(), cache.get(), &delegate);
245   EXPECT_FALSE(delegate.stored_group_success_);
246   EXPECT_TRUE(storage->stored_caches_.empty());
247   EXPECT_TRUE(storage->stored_groups_.empty());
248   base::RunLoop().RunUntilIdle();  // Do async task execution.
249   EXPECT_TRUE(delegate.stored_group_success_);
250   EXPECT_FALSE(storage->stored_caches_.empty());
251   EXPECT_FALSE(storage->stored_groups_.empty());
252   EXPECT_EQ(cache, group->newest_complete_cache());
253   EXPECT_TRUE(cache->is_complete());
254 }
255
256 TEST_F(MockAppCacheStorageTest, StoreExistingGroup) {
257   // Store a group and its newest cache. Should complete asyncly.
258   MockAppCacheService service;
259   MockAppCacheStorage* storage =
260       reinterpret_cast<MockAppCacheStorage*>(service.storage());
261
262   // Setup some preconditions. Create a group and old complete cache
263   // that appear to be "stored", and a newest unstored complete cache.
264   GURL manifest_url("http://blah/");
265   scoped_refptr<AppCacheGroup> group(
266       new AppCacheGroup(service.storage(), manifest_url, 111));
267   int64 old_cache_id = storage->NewCacheId();
268   scoped_refptr<AppCache> old_cache(
269       new AppCache(service.storage(), old_cache_id));
270   old_cache->set_complete(true);
271   group->AddCache(old_cache.get());
272   storage->AddStoredGroup(group.get());
273   storage->AddStoredCache(old_cache.get());
274   int64 new_cache_id = storage->NewCacheId();
275   scoped_refptr<AppCache> new_cache(
276       new AppCache(service.storage(), new_cache_id));
277   // Hold our refs to simulate the UpdateJob holding these refs.
278
279   // Conduct the test.
280   MockStorageDelegate delegate;
281   EXPECT_EQ(size_t(1), storage->stored_caches_.size());
282   EXPECT_EQ(size_t(1), storage->stored_groups_.size());
283   EXPECT_TRUE(storage->IsCacheStored(old_cache.get()));
284   EXPECT_FALSE(storage->IsCacheStored(new_cache.get()));
285   storage->StoreGroupAndNewestCache(group.get(), new_cache.get(), &delegate);
286   EXPECT_FALSE(delegate.stored_group_success_);
287   EXPECT_EQ(size_t(1), storage->stored_caches_.size());
288   EXPECT_EQ(size_t(1), storage->stored_groups_.size());
289   EXPECT_TRUE(storage->IsCacheStored(old_cache.get()));
290   EXPECT_FALSE(storage->IsCacheStored(new_cache.get()));
291   base::RunLoop().RunUntilIdle();  // Do async task execution.
292   EXPECT_TRUE(delegate.stored_group_success_);
293   EXPECT_EQ(size_t(1), storage->stored_caches_.size());
294   EXPECT_EQ(size_t(1), storage->stored_groups_.size());
295   EXPECT_FALSE(storage->IsCacheStored(old_cache.get()));
296   EXPECT_TRUE(storage->IsCacheStored(new_cache.get()));
297   EXPECT_EQ(new_cache.get(), group->newest_complete_cache());
298   EXPECT_TRUE(new_cache->is_complete());
299 }
300
301 TEST_F(MockAppCacheStorageTest, StoreExistingGroupExistingCache) {
302   // Store a group with updates to its existing newest complete cache.
303   MockAppCacheService service;
304   MockAppCacheStorage* storage =
305       reinterpret_cast<MockAppCacheStorage*>(service.storage());
306
307   // Setup some preconditions. Create a group and a complete cache that
308   // appear to be "stored".
309   GURL manifest_url("http://blah");
310   scoped_refptr<AppCacheGroup> group(
311       new AppCacheGroup(service.storage(), manifest_url, 111));
312   int64 cache_id = storage->NewCacheId();
313   scoped_refptr<AppCache> cache(new AppCache(service.storage(), cache_id));
314   cache->set_complete(true);
315   group->AddCache(cache.get());
316   storage->AddStoredGroup(group.get());
317   storage->AddStoredCache(cache.get());
318   // Hold our refs to simulate the UpdateJob holding these refs.
319
320   // Change the group's newest cache.
321   EXPECT_EQ(cache, group->newest_complete_cache());
322   GURL entry_url("http://blah/blah");
323   cache->AddEntry(entry_url, AppCacheEntry(AppCacheEntry::MASTER));
324
325   // Conduct the test.
326   MockStorageDelegate delegate;
327   EXPECT_EQ(size_t(1), storage->stored_caches_.size());
328   EXPECT_EQ(size_t(1), storage->stored_groups_.size());
329   EXPECT_TRUE(storage->IsCacheStored(cache.get()));
330   storage->StoreGroupAndNewestCache(group.get(), cache.get(), &delegate);
331   EXPECT_FALSE(delegate.stored_group_success_);
332   EXPECT_EQ(size_t(1), storage->stored_caches_.size());
333   EXPECT_EQ(size_t(1), storage->stored_groups_.size());
334   base::RunLoop().RunUntilIdle();  // Do async task execution.
335   EXPECT_TRUE(delegate.stored_group_success_);
336   EXPECT_EQ(size_t(1), storage->stored_caches_.size());
337   EXPECT_EQ(size_t(1), storage->stored_groups_.size());
338   EXPECT_TRUE(storage->IsCacheStored(cache.get()));
339   EXPECT_EQ(cache, group->newest_complete_cache());
340   EXPECT_TRUE(cache->GetEntry(entry_url));
341 }
342
343 TEST_F(MockAppCacheStorageTest, MakeGroupObsolete) {
344   // Make a group obsolete, should complete asyncly.
345   MockAppCacheService service;
346   MockAppCacheStorage* storage =
347       reinterpret_cast<MockAppCacheStorage*>(service.storage());
348
349   // Setup some preconditions. Create a group and newest cache that
350   // appears to be "stored" and "currently in use".
351   GURL manifest_url("http://blah/");
352   scoped_refptr<AppCacheGroup> group(
353       new AppCacheGroup(service.storage(), manifest_url, 111));
354   int64 cache_id = storage->NewCacheId();
355   scoped_refptr<AppCache> cache(new AppCache(service.storage(), cache_id));
356   cache->set_complete(true);
357   group->AddCache(cache.get());
358   storage->AddStoredGroup(group.get());
359   storage->AddStoredCache(cache.get());
360   // Hold our refs to simulate the UpdateJob holding these refs.
361
362   // Conduct the test.
363   MockStorageDelegate delegate;
364   EXPECT_FALSE(group->is_obsolete());
365   EXPECT_EQ(size_t(1), storage->stored_caches_.size());
366   EXPECT_EQ(size_t(1), storage->stored_groups_.size());
367   EXPECT_FALSE(cache->HasOneRef());
368   EXPECT_FALSE(group->HasOneRef());
369   storage->MakeGroupObsolete(group.get(), &delegate, 0);
370   EXPECT_FALSE(group->is_obsolete());
371   EXPECT_EQ(size_t(1), storage->stored_caches_.size());
372   EXPECT_EQ(size_t(1), storage->stored_groups_.size());
373   EXPECT_FALSE(cache->HasOneRef());
374   EXPECT_FALSE(group->HasOneRef());
375   base::RunLoop().RunUntilIdle();  // Do async task execution.
376   EXPECT_TRUE(delegate.obsoleted_success_);
377   EXPECT_EQ(group.get(), delegate.obsoleted_group_.get());
378   EXPECT_TRUE(group->is_obsolete());
379   EXPECT_TRUE(storage->stored_caches_.empty());
380   EXPECT_TRUE(storage->stored_groups_.empty());
381   EXPECT_TRUE(cache->HasOneRef());
382   EXPECT_FALSE(group->HasOneRef());
383   delegate.obsoleted_group_ = NULL;
384   cache = NULL;
385   EXPECT_TRUE(group->HasOneRef());
386 }
387
388 TEST_F(MockAppCacheStorageTest, MarkEntryAsForeign) {
389   // Should complete syncly.
390   MockAppCacheService service;
391   MockAppCacheStorage* storage =
392       reinterpret_cast<MockAppCacheStorage*>(service.storage());
393
394   // Setup some preconditions. Create a cache with an entry.
395   GURL entry_url("http://blah/entry");
396   int64 cache_id = storage->NewCacheId();
397   scoped_refptr<AppCache> cache(new AppCache(service.storage(), cache_id));
398   cache->AddEntry(entry_url, AppCacheEntry(AppCacheEntry::EXPLICIT));
399
400   // Conduct the test.
401   MockStorageDelegate delegate;
402   EXPECT_FALSE(cache->GetEntry(entry_url)->IsForeign());
403   storage->MarkEntryAsForeign(entry_url, cache_id);
404   EXPECT_TRUE(cache->GetEntry(entry_url)->IsForeign());
405   EXPECT_TRUE(cache->GetEntry(entry_url)->IsExplicit());
406 }
407
408 TEST_F(MockAppCacheStorageTest, FindNoMainResponse) {
409   // Should complete asyncly.
410   MockAppCacheService service;
411   MockAppCacheStorage* storage =
412       reinterpret_cast<MockAppCacheStorage*>(service.storage());
413
414   // Conduct the test.
415   MockStorageDelegate delegate;
416   GURL url("http://blah/some_url");
417   EXPECT_NE(url, delegate.found_url_);
418   storage->FindResponseForMainRequest(url, GURL(), &delegate);
419   EXPECT_NE(url, delegate.found_url_);
420   base::RunLoop().RunUntilIdle();  // Do async task execution.
421   EXPECT_EQ(url, delegate.found_url_);
422   EXPECT_TRUE(delegate.found_manifest_url_.is_empty());
423   EXPECT_EQ(kNoCacheId, delegate.found_cache_id_);
424   EXPECT_EQ(kNoResponseId, delegate.found_entry_.response_id());
425   EXPECT_EQ(kNoResponseId, delegate.found_fallback_entry_.response_id());
426   EXPECT_TRUE(delegate.found_fallback_url_.is_empty());
427   EXPECT_EQ(0, delegate.found_entry_.types());
428   EXPECT_EQ(0, delegate.found_fallback_entry_.types());
429 }
430
431 TEST_F(MockAppCacheStorageTest, BasicFindMainResponse) {
432   // Should complete asyncly.
433   MockAppCacheService service;
434   MockAppCacheStorage* storage =
435       reinterpret_cast<MockAppCacheStorage*>(service.storage());
436
437   // Setup some preconditions. Create a complete cache with an entry.
438   const int64 kCacheId = storage->NewCacheId();
439   const GURL kEntryUrl("http://blah/entry");
440   const GURL kManifestUrl("http://blah/manifest");
441   const int64 kResponseId = 1;
442   scoped_refptr<AppCache> cache(new AppCache(service.storage(), kCacheId));
443   cache->AddEntry(
444       kEntryUrl, AppCacheEntry(AppCacheEntry::EXPLICIT, kResponseId));
445   cache->set_complete(true);
446   scoped_refptr<AppCacheGroup> group(
447       new AppCacheGroup(service.storage(), kManifestUrl, 111));
448   group->AddCache(cache.get());
449   storage->AddStoredGroup(group.get());
450   storage->AddStoredCache(cache.get());
451
452   // Conduct the test.
453   MockStorageDelegate delegate;
454   EXPECT_NE(kEntryUrl, delegate.found_url_);
455   storage->FindResponseForMainRequest(kEntryUrl, GURL(), &delegate);
456   EXPECT_NE(kEntryUrl, delegate.found_url_);
457   base::RunLoop().RunUntilIdle();  // Do async task execution.
458   EXPECT_EQ(kEntryUrl, delegate.found_url_);
459   EXPECT_EQ(kManifestUrl, delegate.found_manifest_url_);
460   EXPECT_EQ(kCacheId, delegate.found_cache_id_);
461   EXPECT_EQ(kResponseId, delegate.found_entry_.response_id());
462   EXPECT_TRUE(delegate.found_entry_.IsExplicit());
463   EXPECT_FALSE(delegate.found_fallback_entry_.has_response_id());
464 }
465
466 TEST_F(MockAppCacheStorageTest, BasicFindMainFallbackResponse) {
467   // Should complete asyncly.
468   MockAppCacheService service;
469   MockAppCacheStorage* storage =
470       reinterpret_cast<MockAppCacheStorage*>(service.storage());
471
472   // Setup some preconditions. Create a complete cache with a
473   // fallback namespace and entry.
474   const int64 kCacheId = storage->NewCacheId();
475   const GURL kFallbackEntryUrl1("http://blah/fallback_entry1");
476   const GURL kFallbackNamespaceUrl1("http://blah/fallback_namespace/");
477   const GURL kFallbackEntryUrl2("http://blah/fallback_entry2");
478   const GURL kFallbackNamespaceUrl2("http://blah/fallback_namespace/longer");
479   const GURL kManifestUrl("http://blah/manifest");
480   const int64 kResponseId1 = 1;
481   const int64 kResponseId2 = 2;
482
483   Manifest manifest;
484   manifest.fallback_namespaces.push_back(
485       Namespace(FALLBACK_NAMESPACE, kFallbackNamespaceUrl1,
486                 kFallbackEntryUrl1, false));
487   manifest.fallback_namespaces.push_back(
488       Namespace(FALLBACK_NAMESPACE, kFallbackNamespaceUrl2,
489                 kFallbackEntryUrl2, false));
490
491   scoped_refptr<AppCache> cache(new AppCache(service.storage(), kCacheId));
492   cache->InitializeWithManifest(&manifest);
493   cache->AddEntry(kFallbackEntryUrl1,
494                   AppCacheEntry(AppCacheEntry::FALLBACK, kResponseId1));
495   cache->AddEntry(kFallbackEntryUrl2,
496                   AppCacheEntry(AppCacheEntry::FALLBACK, kResponseId2));
497   cache->set_complete(true);
498
499   scoped_refptr<AppCacheGroup> group(
500       new AppCacheGroup(service.storage(), kManifestUrl, 111));
501   group->AddCache(cache.get());
502   storage->AddStoredGroup(group.get());
503   storage->AddStoredCache(cache.get());
504
505   // The test url is in both fallback namespace urls, but should match
506   // the longer of the two.
507   const GURL kTestUrl("http://blah/fallback_namespace/longer/test");
508
509   // Conduct the test.
510   MockStorageDelegate delegate;
511   EXPECT_NE(kTestUrl, delegate.found_url_);
512   storage->FindResponseForMainRequest(kTestUrl, GURL(), &delegate);
513   EXPECT_NE(kTestUrl, delegate.found_url_);
514   base::RunLoop().RunUntilIdle();  // Do async task execution.
515   EXPECT_EQ(kTestUrl, delegate.found_url_);
516   EXPECT_EQ(kManifestUrl, delegate.found_manifest_url_);
517   EXPECT_EQ(kCacheId, delegate.found_cache_id_);
518   EXPECT_FALSE(delegate.found_entry_.has_response_id());
519   EXPECT_EQ(kResponseId2, delegate.found_fallback_entry_.response_id());
520   EXPECT_EQ(kFallbackEntryUrl2, delegate.found_fallback_url_);
521   EXPECT_TRUE(delegate.found_fallback_entry_.IsFallback());
522 }
523
524 TEST_F(MockAppCacheStorageTest, FindMainResponseWithMultipleCandidates) {
525   // Should complete asyncly.
526   MockAppCacheService service;
527   MockAppCacheStorage* storage =
528       reinterpret_cast<MockAppCacheStorage*>(service.storage());
529
530   // Setup some preconditions. Create 2 complete caches with an entry
531   // for the same url.
532
533   const GURL kEntryUrl("http://blah/entry");
534   const int64 kCacheId1 = storage->NewCacheId();
535   const int64 kCacheId2 = storage->NewCacheId();
536   const GURL kManifestUrl1("http://blah/manifest1");
537   const GURL kManifestUrl2("http://blah/manifest2");
538   const int64 kResponseId1 = 1;
539   const int64 kResponseId2 = 2;
540
541   // The first cache.
542   scoped_refptr<AppCache> cache(new AppCache(service.storage(), kCacheId1));
543   cache->AddEntry(
544       kEntryUrl, AppCacheEntry(AppCacheEntry::EXPLICIT, kResponseId1));
545   cache->set_complete(true);
546   scoped_refptr<AppCacheGroup> group(
547       new AppCacheGroup(service.storage(), kManifestUrl1, 111));
548   group->AddCache(cache.get());
549   storage->AddStoredGroup(group.get());
550   storage->AddStoredCache(cache.get());
551   // Drop our references to cache1 so it appears as "not in use".
552   cache = NULL;
553   group = NULL;
554
555   // The second cache.
556   cache = new AppCache(service.storage(), kCacheId2);
557   cache->AddEntry(
558       kEntryUrl, AppCacheEntry(AppCacheEntry::EXPLICIT, kResponseId2));
559   cache->set_complete(true);
560   group = new AppCacheGroup(service.storage(), kManifestUrl2, 222);
561   group->AddCache(cache.get());
562   storage->AddStoredGroup(group.get());
563   storage->AddStoredCache(cache.get());
564
565   // Conduct the test, we should find the response from the second cache
566   // since it's "in use".
567   MockStorageDelegate delegate;
568   EXPECT_NE(kEntryUrl, delegate.found_url_);
569   storage->FindResponseForMainRequest(kEntryUrl, GURL(), &delegate);
570   EXPECT_NE(kEntryUrl, delegate.found_url_);
571   base::RunLoop().RunUntilIdle();  // Do async task execution.
572   EXPECT_EQ(kEntryUrl, delegate.found_url_);
573   EXPECT_EQ(kManifestUrl2, delegate.found_manifest_url_);
574   EXPECT_EQ(kCacheId2, delegate.found_cache_id_);
575   EXPECT_EQ(kResponseId2, delegate.found_entry_.response_id());
576   EXPECT_TRUE(delegate.found_entry_.IsExplicit());
577   EXPECT_FALSE(delegate.found_fallback_entry_.has_response_id());
578 }
579
580 TEST_F(MockAppCacheStorageTest, FindMainResponseExclusions) {
581   // Should complete asyncly.
582   MockAppCacheService service;
583   MockAppCacheStorage* storage =
584       reinterpret_cast<MockAppCacheStorage*>(service.storage());
585
586   // Setup some preconditions. Create a complete cache with a
587   // foreign entry and an online namespace.
588
589   const int64 kCacheId = storage->NewCacheId();
590   const GURL kEntryUrl("http://blah/entry");
591   const GURL kManifestUrl("http://blah/manifest");
592   const GURL kOnlineNamespaceUrl("http://blah/online_namespace");
593   const int64 kResponseId = 1;
594
595   Manifest manifest;
596   manifest.online_whitelist_namespaces.push_back(
597       Namespace(NETWORK_NAMESPACE, kOnlineNamespaceUrl,
598                 GURL(), false));
599   scoped_refptr<AppCache> cache(new AppCache(service.storage(), kCacheId));
600   cache->InitializeWithManifest(&manifest);
601   cache->AddEntry(
602       kEntryUrl,
603       AppCacheEntry(AppCacheEntry::EXPLICIT | AppCacheEntry::FOREIGN,
604                     kResponseId));
605   cache->set_complete(true);
606   scoped_refptr<AppCacheGroup> group(
607       new AppCacheGroup(service.storage(), kManifestUrl, 111));
608   group->AddCache(cache.get());
609   storage->AddStoredGroup(group.get());
610   storage->AddStoredCache(cache.get());
611
612   MockStorageDelegate delegate;
613
614   // We should not find anything for the foreign entry.
615   EXPECT_NE(kEntryUrl, delegate.found_url_);
616   storage->FindResponseForMainRequest(kEntryUrl, GURL(), &delegate);
617   EXPECT_NE(kEntryUrl, delegate.found_url_);
618   base::RunLoop().RunUntilIdle();  // Do async task execution.
619   EXPECT_EQ(kEntryUrl, delegate.found_url_);
620   EXPECT_TRUE(delegate.found_manifest_url_.is_empty());
621   EXPECT_EQ(kNoCacheId, delegate.found_cache_id_);
622   EXPECT_EQ(kNoResponseId, delegate.found_entry_.response_id());
623   EXPECT_EQ(kNoResponseId, delegate.found_fallback_entry_.response_id());
624   EXPECT_TRUE(delegate.found_fallback_url_.is_empty());
625   EXPECT_EQ(0, delegate.found_entry_.types());
626   EXPECT_EQ(0, delegate.found_fallback_entry_.types());
627
628   // We should not find anything for the online namespace.
629   EXPECT_NE(kOnlineNamespaceUrl, delegate.found_url_);
630   storage->FindResponseForMainRequest(kOnlineNamespaceUrl, GURL(), &delegate);
631   EXPECT_NE(kOnlineNamespaceUrl, delegate.found_url_);
632   base::RunLoop().RunUntilIdle();  // Do async task execution.
633   EXPECT_EQ(kOnlineNamespaceUrl, delegate.found_url_);
634   EXPECT_TRUE(delegate.found_manifest_url_.is_empty());
635   EXPECT_EQ(kNoCacheId, delegate.found_cache_id_);
636   EXPECT_EQ(kNoResponseId, delegate.found_entry_.response_id());
637   EXPECT_EQ(kNoResponseId, delegate.found_fallback_entry_.response_id());
638   EXPECT_TRUE(delegate.found_fallback_url_.is_empty());
639   EXPECT_EQ(0, delegate.found_entry_.types());
640   EXPECT_EQ(0, delegate.found_fallback_entry_.types());
641 }
642
643 }  // namespace content