mock_appcache_storage_unittest.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
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
13using appcache::AppCache;
14using appcache::AppCacheEntry;
15using appcache::AppCacheGroup;
16using appcache::AppCacheStorage;
17using appcache::APPCACHE_FALLBACK_NAMESPACE;
18using appcache::APPCACHE_INTERCEPT_NAMESPACE;
19using appcache::kAppCacheNoCacheId;
20using appcache::kAppCacheNoResponseId;
21using appcache::Manifest;
22using appcache::Namespace;
23using appcache::APPCACHE_NETWORK_NAMESPACE;
24
25namespace content {
26
27class 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_(kAppCacheNoCacheId) {
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
96TEST_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
108TEST_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
126TEST_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
145TEST_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
171TEST_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
224TEST_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
256TEST_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
301TEST_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
343TEST_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
388TEST_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
408TEST_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(kAppCacheNoCacheId, delegate.found_cache_id_);
424  EXPECT_EQ(kAppCacheNoResponseId, delegate.found_entry_.response_id());
425  EXPECT_EQ(kAppCacheNoResponseId,
426            delegate.found_fallback_entry_.response_id());
427  EXPECT_TRUE(delegate.found_fallback_url_.is_empty());
428  EXPECT_EQ(0, delegate.found_entry_.types());
429  EXPECT_EQ(0, delegate.found_fallback_entry_.types());
430}
431
432TEST_F(MockAppCacheStorageTest, BasicFindMainResponse) {
433  // Should complete asyncly.
434  MockAppCacheService service;
435  MockAppCacheStorage* storage =
436      reinterpret_cast<MockAppCacheStorage*>(service.storage());
437
438  // Setup some preconditions. Create a complete cache with an entry.
439  const int64 kCacheId = storage->NewCacheId();
440  const GURL kEntryUrl("http://blah/entry");
441  const GURL kManifestUrl("http://blah/manifest");
442  const int64 kResponseId = 1;
443  scoped_refptr<AppCache> cache(new AppCache(service.storage(), kCacheId));
444  cache->AddEntry(
445      kEntryUrl, AppCacheEntry(AppCacheEntry::EXPLICIT, kResponseId));
446  cache->set_complete(true);
447  scoped_refptr<AppCacheGroup> group(
448      new AppCacheGroup(service.storage(), kManifestUrl, 111));
449  group->AddCache(cache.get());
450  storage->AddStoredGroup(group.get());
451  storage->AddStoredCache(cache.get());
452
453  // Conduct the test.
454  MockStorageDelegate delegate;
455  EXPECT_NE(kEntryUrl, delegate.found_url_);
456  storage->FindResponseForMainRequest(kEntryUrl, GURL(), &delegate);
457  EXPECT_NE(kEntryUrl, delegate.found_url_);
458  base::RunLoop().RunUntilIdle();  // Do async task execution.
459  EXPECT_EQ(kEntryUrl, delegate.found_url_);
460  EXPECT_EQ(kManifestUrl, delegate.found_manifest_url_);
461  EXPECT_EQ(kCacheId, delegate.found_cache_id_);
462  EXPECT_EQ(kResponseId, delegate.found_entry_.response_id());
463  EXPECT_TRUE(delegate.found_entry_.IsExplicit());
464  EXPECT_FALSE(delegate.found_fallback_entry_.has_response_id());
465}
466
467TEST_F(MockAppCacheStorageTest, BasicFindMainFallbackResponse) {
468  // Should complete asyncly.
469  MockAppCacheService service;
470  MockAppCacheStorage* storage =
471      reinterpret_cast<MockAppCacheStorage*>(service.storage());
472
473  // Setup some preconditions. Create a complete cache with a
474  // fallback namespace and entry.
475  const int64 kCacheId = storage->NewCacheId();
476  const GURL kFallbackEntryUrl1("http://blah/fallback_entry1");
477  const GURL kFallbackNamespaceUrl1("http://blah/fallback_namespace/");
478  const GURL kFallbackEntryUrl2("http://blah/fallback_entry2");
479  const GURL kFallbackNamespaceUrl2("http://blah/fallback_namespace/longer");
480  const GURL kManifestUrl("http://blah/manifest");
481  const int64 kResponseId1 = 1;
482  const int64 kResponseId2 = 2;
483
484  Manifest manifest;
485  manifest.fallback_namespaces.push_back(
486      Namespace(APPCACHE_FALLBACK_NAMESPACE, kFallbackNamespaceUrl1,
487                kFallbackEntryUrl1, false));
488  manifest.fallback_namespaces.push_back(
489      Namespace(APPCACHE_FALLBACK_NAMESPACE, kFallbackNamespaceUrl2,
490                kFallbackEntryUrl2, false));
491
492  scoped_refptr<AppCache> cache(new AppCache(service.storage(), kCacheId));
493  cache->InitializeWithManifest(&manifest);
494  cache->AddEntry(kFallbackEntryUrl1,
495                  AppCacheEntry(AppCacheEntry::FALLBACK, kResponseId1));
496  cache->AddEntry(kFallbackEntryUrl2,
497                  AppCacheEntry(AppCacheEntry::FALLBACK, kResponseId2));
498  cache->set_complete(true);
499
500  scoped_refptr<AppCacheGroup> group(
501      new AppCacheGroup(service.storage(), kManifestUrl, 111));
502  group->AddCache(cache.get());
503  storage->AddStoredGroup(group.get());
504  storage->AddStoredCache(cache.get());
505
506  // The test url is in both fallback namespace urls, but should match
507  // the longer of the two.
508  const GURL kTestUrl("http://blah/fallback_namespace/longer/test");
509
510  // Conduct the test.
511  MockStorageDelegate delegate;
512  EXPECT_NE(kTestUrl, delegate.found_url_);
513  storage->FindResponseForMainRequest(kTestUrl, GURL(), &delegate);
514  EXPECT_NE(kTestUrl, delegate.found_url_);
515  base::RunLoop().RunUntilIdle();  // Do async task execution.
516  EXPECT_EQ(kTestUrl, delegate.found_url_);
517  EXPECT_EQ(kManifestUrl, delegate.found_manifest_url_);
518  EXPECT_EQ(kCacheId, delegate.found_cache_id_);
519  EXPECT_FALSE(delegate.found_entry_.has_response_id());
520  EXPECT_EQ(kResponseId2, delegate.found_fallback_entry_.response_id());
521  EXPECT_EQ(kFallbackEntryUrl2, delegate.found_fallback_url_);
522  EXPECT_TRUE(delegate.found_fallback_entry_.IsFallback());
523}
524
525TEST_F(MockAppCacheStorageTest, FindMainResponseWithMultipleCandidates) {
526  // Should complete asyncly.
527  MockAppCacheService service;
528  MockAppCacheStorage* storage =
529      reinterpret_cast<MockAppCacheStorage*>(service.storage());
530
531  // Setup some preconditions. Create 2 complete caches with an entry
532  // for the same url.
533
534  const GURL kEntryUrl("http://blah/entry");
535  const int64 kCacheId1 = storage->NewCacheId();
536  const int64 kCacheId2 = storage->NewCacheId();
537  const GURL kManifestUrl1("http://blah/manifest1");
538  const GURL kManifestUrl2("http://blah/manifest2");
539  const int64 kResponseId1 = 1;
540  const int64 kResponseId2 = 2;
541
542  // The first cache.
543  scoped_refptr<AppCache> cache(new AppCache(service.storage(), kCacheId1));
544  cache->AddEntry(
545      kEntryUrl, AppCacheEntry(AppCacheEntry::EXPLICIT, kResponseId1));
546  cache->set_complete(true);
547  scoped_refptr<AppCacheGroup> group(
548      new AppCacheGroup(service.storage(), kManifestUrl1, 111));
549  group->AddCache(cache.get());
550  storage->AddStoredGroup(group.get());
551  storage->AddStoredCache(cache.get());
552  // Drop our references to cache1 so it appears as "not in use".
553  cache = NULL;
554  group = NULL;
555
556  // The second cache.
557  cache = new AppCache(service.storage(), kCacheId2);
558  cache->AddEntry(
559      kEntryUrl, AppCacheEntry(AppCacheEntry::EXPLICIT, kResponseId2));
560  cache->set_complete(true);
561  group = new AppCacheGroup(service.storage(), kManifestUrl2, 222);
562  group->AddCache(cache.get());
563  storage->AddStoredGroup(group.get());
564  storage->AddStoredCache(cache.get());
565
566  // Conduct the test, we should find the response from the second cache
567  // since it's "in use".
568  MockStorageDelegate delegate;
569  EXPECT_NE(kEntryUrl, delegate.found_url_);
570  storage->FindResponseForMainRequest(kEntryUrl, GURL(), &delegate);
571  EXPECT_NE(kEntryUrl, delegate.found_url_);
572  base::RunLoop().RunUntilIdle();  // Do async task execution.
573  EXPECT_EQ(kEntryUrl, delegate.found_url_);
574  EXPECT_EQ(kManifestUrl2, delegate.found_manifest_url_);
575  EXPECT_EQ(kCacheId2, delegate.found_cache_id_);
576  EXPECT_EQ(kResponseId2, delegate.found_entry_.response_id());
577  EXPECT_TRUE(delegate.found_entry_.IsExplicit());
578  EXPECT_FALSE(delegate.found_fallback_entry_.has_response_id());
579}
580
581TEST_F(MockAppCacheStorageTest, FindMainResponseExclusions) {
582  // Should complete asyncly.
583  MockAppCacheService service;
584  MockAppCacheStorage* storage =
585      reinterpret_cast<MockAppCacheStorage*>(service.storage());
586
587  // Setup some preconditions. Create a complete cache with a
588  // foreign entry and an online namespace.
589
590  const int64 kCacheId = storage->NewCacheId();
591  const GURL kEntryUrl("http://blah/entry");
592  const GURL kManifestUrl("http://blah/manifest");
593  const GURL kOnlineNamespaceUrl("http://blah/online_namespace");
594  const int64 kResponseId = 1;
595
596  Manifest manifest;
597  manifest.online_whitelist_namespaces.push_back(
598      Namespace(APPCACHE_NETWORK_NAMESPACE, kOnlineNamespaceUrl,
599                GURL(), false));
600  scoped_refptr<AppCache> cache(new AppCache(service.storage(), kCacheId));
601  cache->InitializeWithManifest(&manifest);
602  cache->AddEntry(
603      kEntryUrl,
604      AppCacheEntry(AppCacheEntry::EXPLICIT | AppCacheEntry::FOREIGN,
605                    kResponseId));
606  cache->set_complete(true);
607  scoped_refptr<AppCacheGroup> group(
608      new AppCacheGroup(service.storage(), kManifestUrl, 111));
609  group->AddCache(cache.get());
610  storage->AddStoredGroup(group.get());
611  storage->AddStoredCache(cache.get());
612
613  MockStorageDelegate delegate;
614
615  // We should not find anything for the foreign entry.
616  EXPECT_NE(kEntryUrl, delegate.found_url_);
617  storage->FindResponseForMainRequest(kEntryUrl, GURL(), &delegate);
618  EXPECT_NE(kEntryUrl, delegate.found_url_);
619  base::RunLoop().RunUntilIdle();  // Do async task execution.
620  EXPECT_EQ(kEntryUrl, delegate.found_url_);
621  EXPECT_TRUE(delegate.found_manifest_url_.is_empty());
622  EXPECT_EQ(kAppCacheNoCacheId, delegate.found_cache_id_);
623  EXPECT_EQ(kAppCacheNoResponseId, delegate.found_entry_.response_id());
624  EXPECT_EQ(kAppCacheNoResponseId,
625            delegate.found_fallback_entry_.response_id());
626  EXPECT_TRUE(delegate.found_fallback_url_.is_empty());
627  EXPECT_EQ(0, delegate.found_entry_.types());
628  EXPECT_EQ(0, delegate.found_fallback_entry_.types());
629
630  // We should not find anything for the online namespace.
631  EXPECT_NE(kOnlineNamespaceUrl, delegate.found_url_);
632  storage->FindResponseForMainRequest(kOnlineNamespaceUrl, GURL(), &delegate);
633  EXPECT_NE(kOnlineNamespaceUrl, delegate.found_url_);
634  base::RunLoop().RunUntilIdle();  // Do async task execution.
635  EXPECT_EQ(kOnlineNamespaceUrl, delegate.found_url_);
636  EXPECT_TRUE(delegate.found_manifest_url_.is_empty());
637  EXPECT_EQ(kAppCacheNoCacheId, delegate.found_cache_id_);
638  EXPECT_EQ(kAppCacheNoResponseId, delegate.found_entry_.response_id());
639  EXPECT_EQ(kAppCacheNoResponseId,
640            delegate.found_fallback_entry_.response_id());
641  EXPECT_TRUE(delegate.found_fallback_url_.is_empty());
642  EXPECT_EQ(0, delegate.found_entry_.types());
643  EXPECT_EQ(0, delegate.found_fallback_entry_.types());
644}
645
646}  // namespace content
647