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