Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / content / browser / appcache / appcache_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/appcache/mock_appcache_service.h"
6 #include "testing/gtest/include/gtest/gtest.h"
7 #include "webkit/browser/appcache/appcache.h"
8 #include "webkit/browser/appcache/appcache_host.h"
9
10 using appcache::AppCache;
11 using appcache::AppCacheDatabase;
12 using appcache::AppCacheEntry;
13 using appcache::AppCacheFrontend;
14 using appcache::AppCacheGroup;
15 using appcache::AppCacheHost;
16 using appcache::AppCacheInfo;
17 using appcache::ErrorDetails;
18 using appcache::EventID;
19 using appcache::FALLBACK_NAMESPACE;
20 using appcache::INTERCEPT_NAMESPACE;
21 using appcache::LogLevel;
22 using appcache::Manifest;
23 using appcache::Namespace;
24 using appcache::NamespaceVector;
25 using appcache::NETWORK_NAMESPACE;
26 using appcache::PARSE_MANIFEST_ALLOWING_INTERCEPTS;
27 using appcache::PARSE_MANIFEST_PER_STANDARD;
28 using appcache::Status;
29
30 namespace content {
31
32 namespace {
33
34 class MockAppCacheFrontend : public AppCacheFrontend {
35  public:
36   virtual void OnCacheSelected(int host_id, const AppCacheInfo& info) OVERRIDE {
37   }
38   virtual void OnStatusChanged(const std::vector<int>& host_ids,
39                                Status status) OVERRIDE {}
40   virtual void OnEventRaised(const std::vector<int>& host_ids,
41                              EventID event_id) OVERRIDE {}
42   virtual void OnProgressEventRaised(
43       const std::vector<int>& host_ids,
44       const GURL& url,
45       int num_total, int num_complete) OVERRIDE {}
46   virtual void OnErrorEventRaised(const std::vector<int>& host_ids,
47                                   const ErrorDetails& details) OVERRIDE {}
48   virtual void OnLogMessage(int host_id, LogLevel log_level,
49                             const std::string& message) OVERRIDE {}
50   virtual void OnContentBlocked(
51       int host_id, const GURL& manifest_url) OVERRIDE {}
52 };
53
54 }  // namespace
55
56 class AppCacheTest : public testing::Test {
57 };
58
59 TEST(AppCacheTest, CleanupUnusedCache) {
60   MockAppCacheService service;
61   MockAppCacheFrontend frontend;
62   scoped_refptr<AppCache> cache(new AppCache(service.storage(), 111));
63   cache->set_complete(true);
64   scoped_refptr<AppCacheGroup> group(
65       new AppCacheGroup(service.storage(), GURL("http://blah/manifest"), 111));
66   group->AddCache(cache.get());
67
68   AppCacheHost host1(1, &frontend, &service);
69   AppCacheHost host2(2, &frontend, &service);
70
71   host1.AssociateCompleteCache(cache.get());
72   host2.AssociateCompleteCache(cache.get());
73
74   host1.AssociateNoCache(GURL());
75   host2.AssociateNoCache(GURL());
76 }
77
78 TEST(AppCacheTest, AddModifyRemoveEntry) {
79   MockAppCacheService service;
80   scoped_refptr<AppCache> cache(new AppCache(service.storage(), 111));
81
82   EXPECT_TRUE(cache->entries().empty());
83   EXPECT_EQ(0L, cache->cache_size());
84
85   const GURL kFooUrl("http://foo.com");
86   const int64 kFooResponseId = 1;
87   const int64 kFooSize = 100;
88   AppCacheEntry entry1(AppCacheEntry::MASTER, kFooResponseId, kFooSize);
89   cache->AddEntry(kFooUrl, entry1);
90   EXPECT_EQ(entry1.types(), cache->GetEntry(kFooUrl)->types());
91   EXPECT_EQ(1UL, cache->entries().size());
92   EXPECT_EQ(kFooSize, cache->cache_size());
93
94   const GURL kBarUrl("http://bar.com");
95   const int64 kBarResponseId = 2;
96   const int64 kBarSize = 200;
97   AppCacheEntry entry2(AppCacheEntry::FALLBACK, kBarResponseId, kBarSize);
98   EXPECT_TRUE(cache->AddOrModifyEntry(kBarUrl, entry2));
99   EXPECT_EQ(entry2.types(), cache->GetEntry(kBarUrl)->types());
100   EXPECT_EQ(2UL, cache->entries().size());
101   EXPECT_EQ(kFooSize + kBarSize, cache->cache_size());
102
103   // Expected to return false when an existing entry is modified.
104   AppCacheEntry entry3(AppCacheEntry::EXPLICIT);
105   EXPECT_FALSE(cache->AddOrModifyEntry(kFooUrl, entry3));
106   EXPECT_EQ((AppCacheEntry::MASTER | AppCacheEntry::EXPLICIT),
107             cache->GetEntry(kFooUrl)->types());
108   // Only the type should be modified.
109   EXPECT_EQ(kFooResponseId, cache->GetEntry(kFooUrl)->response_id());
110   EXPECT_EQ(kFooSize, cache->GetEntry(kFooUrl)->response_size());
111   EXPECT_EQ(kFooSize + kBarSize, cache->cache_size());
112
113   EXPECT_EQ(entry2.types(), cache->GetEntry(kBarUrl)->types());  // unchanged
114
115   cache->RemoveEntry(kBarUrl);
116   EXPECT_EQ(kFooSize, cache->cache_size());
117   cache->RemoveEntry(kFooUrl);
118   EXPECT_EQ(0L, cache->cache_size());
119   EXPECT_TRUE(cache->entries().empty());
120 }
121
122 TEST(AppCacheTest, InitializeWithManifest) {
123   MockAppCacheService service;
124
125   scoped_refptr<AppCache> cache(new AppCache(service.storage(), 1234));
126   EXPECT_TRUE(cache->fallback_namespaces_.empty());
127   EXPECT_TRUE(cache->online_whitelist_namespaces_.empty());
128   EXPECT_FALSE(cache->online_whitelist_all_);
129
130   Manifest manifest;
131   manifest.explicit_urls.insert("http://one.com");
132   manifest.explicit_urls.insert("http://two.com");
133   manifest.fallback_namespaces.push_back(
134       Namespace(FALLBACK_NAMESPACE, GURL("http://fb1.com"),
135                 GURL("http://fbone.com"), true));
136   manifest.online_whitelist_namespaces.push_back(
137       Namespace(NETWORK_NAMESPACE, GURL("http://w1.com"), GURL(), false));
138   manifest.online_whitelist_namespaces.push_back(
139       Namespace(NETWORK_NAMESPACE, GURL("http://w2.com"), GURL(), false));
140   manifest.online_whitelist_all = true;
141
142   cache->InitializeWithManifest(&manifest);
143   const std::vector<Namespace>& fallbacks =
144       cache->fallback_namespaces_;
145   size_t expected = 1;
146   EXPECT_EQ(expected, fallbacks.size());
147   EXPECT_EQ(GURL("http://fb1.com"), fallbacks[0].namespace_url);
148   EXPECT_EQ(GURL("http://fbone.com"), fallbacks[0].target_url);
149   EXPECT_TRUE(fallbacks[0].is_pattern);
150   const NamespaceVector& whitelist = cache->online_whitelist_namespaces_;
151   expected = 2;
152   EXPECT_EQ(expected, whitelist.size());
153   EXPECT_EQ(GURL("http://w1.com"), whitelist[0].namespace_url);
154   EXPECT_EQ(GURL("http://w2.com"), whitelist[1].namespace_url);
155   EXPECT_TRUE(cache->online_whitelist_all_);
156
157   // Ensure collections in manifest were taken over by the cache rather than
158   // copied.
159   EXPECT_TRUE(manifest.fallback_namespaces.empty());
160   EXPECT_TRUE(manifest.online_whitelist_namespaces.empty());
161 }
162
163 TEST(AppCacheTest, FindResponseForRequest) {
164   MockAppCacheService service;
165
166   const GURL kOnlineNamespaceUrl("http://blah/online_namespace");
167   const GURL kFallbackEntryUrl1("http://blah/fallback_entry1");
168   const GURL kFallbackNamespaceUrl1("http://blah/fallback_namespace/");
169   const GURL kFallbackEntryUrl2("http://blah/fallback_entry2");
170   const GURL kFallbackNamespaceUrl2("http://blah/fallback_namespace/longer");
171   const GURL kManifestUrl("http://blah/manifest");
172   const GURL kForeignExplicitEntryUrl("http://blah/foreign");
173   const GURL kInOnlineNamespaceUrl(
174       "http://blah/online_namespace/network");
175   const GURL kExplicitInOnlineNamespaceUrl(
176       "http://blah/online_namespace/explicit");
177   const GURL kFallbackTestUrl1("http://blah/fallback_namespace/1");
178   const GURL kFallbackTestUrl2("http://blah/fallback_namespace/longer2");
179   const GURL kInterceptNamespace("http://blah/intercept_namespace/");
180   const GURL kInterceptNamespaceWithinFallback(
181       "http://blah/fallback_namespace/intercept_namespace/");
182   const GURL kInterceptNamespaceEntry("http://blah/intercept_entry");
183   const GURL kOnlineNamespaceWithinOtherNamespaces(
184       "http://blah/fallback_namespace/intercept_namespace/1/online");
185
186   const int64 kFallbackResponseId1 = 1;
187   const int64 kFallbackResponseId2 = 2;
188   const int64 kManifestResponseId = 3;
189   const int64 kForeignExplicitResponseId = 4;
190   const int64 kExplicitInOnlineNamespaceResponseId = 5;
191   const int64 kInterceptResponseId = 6;
192
193   Manifest manifest;
194   manifest.online_whitelist_namespaces.push_back(
195       Namespace(NETWORK_NAMESPACE, kOnlineNamespaceUrl,
196                 GURL(), false));
197   manifest.online_whitelist_namespaces.push_back(
198       Namespace(NETWORK_NAMESPACE, kOnlineNamespaceWithinOtherNamespaces,
199                 GURL(), false));
200   manifest.fallback_namespaces.push_back(
201       Namespace(FALLBACK_NAMESPACE, kFallbackNamespaceUrl1,
202                 kFallbackEntryUrl1, false));
203   manifest.fallback_namespaces.push_back(
204       Namespace(FALLBACK_NAMESPACE, kFallbackNamespaceUrl2,
205                 kFallbackEntryUrl2, false));
206   manifest.intercept_namespaces.push_back(
207       Namespace(INTERCEPT_NAMESPACE, kInterceptNamespace,
208                 kInterceptNamespaceEntry, false));
209   manifest.intercept_namespaces.push_back(
210       Namespace(INTERCEPT_NAMESPACE, kInterceptNamespaceWithinFallback,
211                 kInterceptNamespaceEntry, false));
212
213   // Create a cache with some namespaces and entries.
214   scoped_refptr<AppCache> cache(new AppCache(service.storage(), 1234));
215   cache->InitializeWithManifest(&manifest);
216   cache->AddEntry(
217       kFallbackEntryUrl1,
218       AppCacheEntry(AppCacheEntry::FALLBACK, kFallbackResponseId1));
219   cache->AddEntry(
220       kFallbackEntryUrl2,
221       AppCacheEntry(AppCacheEntry::FALLBACK, kFallbackResponseId2));
222   cache->AddEntry(
223       kManifestUrl,
224       AppCacheEntry(AppCacheEntry::MANIFEST, kManifestResponseId));
225   cache->AddEntry(
226       kForeignExplicitEntryUrl,
227       AppCacheEntry(AppCacheEntry::EXPLICIT | AppCacheEntry::FOREIGN,
228                     kForeignExplicitResponseId));
229   cache->AddEntry(
230       kExplicitInOnlineNamespaceUrl,
231       AppCacheEntry(AppCacheEntry::EXPLICIT,
232                     kExplicitInOnlineNamespaceResponseId));
233   cache->AddEntry(
234       kInterceptNamespaceEntry,
235       AppCacheEntry(AppCacheEntry::INTERCEPT, kInterceptResponseId));
236   cache->set_complete(true);
237
238   // See that we get expected results from FindResponseForRequest
239
240   bool found = false;
241   AppCacheEntry entry;
242   AppCacheEntry fallback_entry;
243   GURL intercept_namespace;
244   GURL fallback_namespace;
245   bool network_namespace = false;
246
247   found = cache->FindResponseForRequest(GURL("http://blah/miss"),
248       &entry, &intercept_namespace,
249       &fallback_entry, &fallback_namespace,
250       &network_namespace);
251   EXPECT_FALSE(found);
252
253   found = cache->FindResponseForRequest(kForeignExplicitEntryUrl,
254       &entry, &intercept_namespace,
255       &fallback_entry, &fallback_namespace,
256       &network_namespace);
257   EXPECT_TRUE(found);
258   EXPECT_EQ(kForeignExplicitResponseId, entry.response_id());
259   EXPECT_FALSE(fallback_entry.has_response_id());
260   EXPECT_FALSE(network_namespace);
261
262   entry = AppCacheEntry();  // reset
263
264   found = cache->FindResponseForRequest(kManifestUrl,
265       &entry, &intercept_namespace,
266       &fallback_entry, &fallback_namespace,
267       &network_namespace);
268   EXPECT_TRUE(found);
269   EXPECT_EQ(kManifestResponseId, entry.response_id());
270   EXPECT_FALSE(fallback_entry.has_response_id());
271   EXPECT_FALSE(network_namespace);
272
273   entry = AppCacheEntry();  // reset
274
275   found = cache->FindResponseForRequest(kInOnlineNamespaceUrl,
276       &entry, &intercept_namespace,
277       &fallback_entry, &fallback_namespace,
278       &network_namespace);
279   EXPECT_TRUE(found);
280   EXPECT_FALSE(entry.has_response_id());
281   EXPECT_FALSE(fallback_entry.has_response_id());
282   EXPECT_TRUE(network_namespace);
283
284   network_namespace = false;  // reset
285
286   found = cache->FindResponseForRequest(kExplicitInOnlineNamespaceUrl,
287       &entry, &intercept_namespace,
288       &fallback_entry, &fallback_namespace,
289       &network_namespace);
290   EXPECT_TRUE(found);
291   EXPECT_EQ(kExplicitInOnlineNamespaceResponseId, entry.response_id());
292   EXPECT_FALSE(fallback_entry.has_response_id());
293   EXPECT_FALSE(network_namespace);
294
295   entry = AppCacheEntry();  // reset
296
297   found = cache->FindResponseForRequest(kFallbackTestUrl1,
298       &entry, &intercept_namespace,
299       &fallback_entry, &fallback_namespace,
300       &network_namespace);
301   EXPECT_TRUE(found);
302   EXPECT_FALSE(entry.has_response_id());
303   EXPECT_EQ(kFallbackResponseId1, fallback_entry.response_id());
304   EXPECT_EQ(kFallbackEntryUrl1,
305             cache->GetFallbackEntryUrl(fallback_namespace));
306   EXPECT_FALSE(network_namespace);
307
308   fallback_entry = AppCacheEntry();  // reset
309
310   found = cache->FindResponseForRequest(kFallbackTestUrl2,
311       &entry, &intercept_namespace,
312       &fallback_entry, &fallback_namespace,
313       &network_namespace);
314   EXPECT_TRUE(found);
315   EXPECT_FALSE(entry.has_response_id());
316   EXPECT_EQ(kFallbackResponseId2, fallback_entry.response_id());
317   EXPECT_EQ(kFallbackEntryUrl2,
318             cache->GetFallbackEntryUrl(fallback_namespace));
319   EXPECT_FALSE(network_namespace);
320
321   fallback_entry = AppCacheEntry();  // reset
322
323   found = cache->FindResponseForRequest(kOnlineNamespaceWithinOtherNamespaces,
324       &entry, &intercept_namespace,
325       &fallback_entry, &fallback_namespace,
326       &network_namespace);
327   EXPECT_TRUE(found);
328   EXPECT_FALSE(entry.has_response_id());
329   EXPECT_FALSE(fallback_entry.has_response_id());
330   EXPECT_TRUE(network_namespace);
331
332   fallback_entry = AppCacheEntry();  // reset
333
334   found = cache->FindResponseForRequest(
335       kOnlineNamespaceWithinOtherNamespaces.Resolve("online_resource"),
336       &entry, &intercept_namespace,
337       &fallback_entry, &fallback_namespace,
338       &network_namespace);
339   EXPECT_TRUE(found);
340   EXPECT_FALSE(entry.has_response_id());
341   EXPECT_FALSE(fallback_entry.has_response_id());
342   EXPECT_TRUE(network_namespace);
343
344   fallback_namespace = GURL();
345
346   found = cache->FindResponseForRequest(
347       kInterceptNamespace.Resolve("intercept_me"),
348       &entry, &intercept_namespace,
349       &fallback_entry, &fallback_namespace,
350       &network_namespace);
351   EXPECT_TRUE(found);
352   EXPECT_EQ(kInterceptResponseId, entry.response_id());
353   EXPECT_EQ(kInterceptNamespaceEntry,
354             cache->GetInterceptEntryUrl(intercept_namespace));
355   EXPECT_FALSE(fallback_entry.has_response_id());
356   EXPECT_TRUE(fallback_namespace.is_empty());
357   EXPECT_FALSE(network_namespace);
358
359   entry = AppCacheEntry();  // reset
360
361   found = cache->FindResponseForRequest(
362       kInterceptNamespaceWithinFallback.Resolve("intercept_me"),
363       &entry, &intercept_namespace,
364       &fallback_entry, &fallback_namespace,
365       &network_namespace);
366   EXPECT_TRUE(found);
367   EXPECT_EQ(kInterceptResponseId, entry.response_id());
368   EXPECT_EQ(kInterceptNamespaceEntry,
369             cache->GetInterceptEntryUrl(intercept_namespace));
370   EXPECT_FALSE(fallback_entry.has_response_id());
371   EXPECT_TRUE(fallback_namespace.is_empty());
372   EXPECT_FALSE(network_namespace);
373 }
374
375 TEST(AppCacheTest, FindInterceptPatternResponseForRequest) {
376   MockAppCacheService service;
377
378   // Setup an appcache with an intercept namespace that uses pattern matching.
379   const GURL kInterceptNamespaceBase("http://blah/intercept_namespace/");
380   const GURL kInterceptPatternNamespace(
381       kInterceptNamespaceBase.Resolve("*.hit*"));
382   const GURL kInterceptNamespaceEntry("http://blah/intercept_resource");
383   const int64 kInterceptResponseId = 1;
384   Manifest manifest;
385   manifest.intercept_namespaces.push_back(
386       Namespace(INTERCEPT_NAMESPACE, kInterceptPatternNamespace,
387                 kInterceptNamespaceEntry, true));
388   scoped_refptr<AppCache> cache(new AppCache(service.storage(), 1234));
389   cache->InitializeWithManifest(&manifest);
390   cache->AddEntry(
391       kInterceptNamespaceEntry,
392       AppCacheEntry(AppCacheEntry::INTERCEPT, kInterceptResponseId));
393   cache->set_complete(true);
394
395   // See that the pattern match works.
396   bool found = false;
397   AppCacheEntry entry;
398   AppCacheEntry fallback_entry;
399   GURL intercept_namespace;
400   GURL fallback_namespace;
401   bool network_namespace = false;
402
403   found = cache->FindResponseForRequest(
404       GURL("http://blah/miss"),
405       &entry, &intercept_namespace,
406       &fallback_entry, &fallback_namespace,
407       &network_namespace);
408   EXPECT_FALSE(found);
409
410   found = cache->FindResponseForRequest(
411       GURL("http://blah/intercept_namespace/another_miss"),
412       &entry, &intercept_namespace,
413       &fallback_entry, &fallback_namespace,
414       &network_namespace);
415   EXPECT_FALSE(found);
416
417   found = cache->FindResponseForRequest(
418       GURL("http://blah/intercept_namespace/path.hit"),
419       &entry, &intercept_namespace,
420       &fallback_entry, &fallback_namespace,
421       &network_namespace);
422   EXPECT_TRUE(found);
423   EXPECT_EQ(kInterceptResponseId, entry.response_id());
424   EXPECT_EQ(kInterceptNamespaceEntry,
425             cache->GetInterceptEntryUrl(intercept_namespace));
426   EXPECT_FALSE(fallback_entry.has_response_id());
427   EXPECT_TRUE(fallback_namespace.is_empty());
428   EXPECT_FALSE(network_namespace);
429
430   entry = AppCacheEntry();  // reset
431
432   found = cache->FindResponseForRequest(
433       GURL("http://blah/intercept_namespace/longer/path.hit?arg=ok"),
434       &entry, &intercept_namespace,
435       &fallback_entry, &fallback_namespace,
436       &network_namespace);
437   EXPECT_TRUE(found);
438   EXPECT_EQ(kInterceptResponseId, entry.response_id());
439   EXPECT_EQ(kInterceptNamespaceEntry,
440             cache->GetInterceptEntryUrl(intercept_namespace));
441   EXPECT_FALSE(fallback_entry.has_response_id());
442   EXPECT_TRUE(fallback_namespace.is_empty());
443   EXPECT_FALSE(network_namespace);
444 }
445
446 TEST(AppCacheTest, FindFallbackPatternResponseForRequest) {
447   MockAppCacheService service;
448
449   // Setup an appcache with a fallback namespace that uses pattern matching.
450   const GURL kFallbackNamespaceBase("http://blah/fallback_namespace/");
451   const GURL kFallbackPatternNamespace(
452       kFallbackNamespaceBase.Resolve("*.hit*"));
453   const GURL kFallbackNamespaceEntry("http://blah/fallback_resource");
454   const int64 kFallbackResponseId = 1;
455   Manifest manifest;
456   manifest.fallback_namespaces.push_back(
457       Namespace(FALLBACK_NAMESPACE, kFallbackPatternNamespace,
458                 kFallbackNamespaceEntry, true));
459   scoped_refptr<AppCache> cache(new AppCache(service.storage(), 1234));
460   cache->InitializeWithManifest(&manifest);
461   cache->AddEntry(
462       kFallbackNamespaceEntry,
463       AppCacheEntry(AppCacheEntry::FALLBACK, kFallbackResponseId));
464   cache->set_complete(true);
465
466   // See that the pattern match works.
467   bool found = false;
468   AppCacheEntry entry;
469   AppCacheEntry fallback_entry;
470   GURL intercept_namespace;
471   GURL fallback_namespace;
472   bool network_namespace = false;
473
474   found = cache->FindResponseForRequest(
475       GURL("http://blah/miss"),
476       &entry, &intercept_namespace,
477       &fallback_entry, &fallback_namespace,
478       &network_namespace);
479   EXPECT_FALSE(found);
480
481   found = cache->FindResponseForRequest(
482       GURL("http://blah/fallback_namespace/another_miss"),
483       &entry, &intercept_namespace,
484       &fallback_entry, &fallback_namespace,
485       &network_namespace);
486   EXPECT_FALSE(found);
487
488   found = cache->FindResponseForRequest(
489       GURL("http://blah/fallback_namespace/path.hit"),
490       &entry, &intercept_namespace,
491       &fallback_entry, &fallback_namespace,
492       &network_namespace);
493   EXPECT_TRUE(found);
494   EXPECT_FALSE(entry.has_response_id());
495   EXPECT_EQ(kFallbackResponseId, fallback_entry.response_id());
496   EXPECT_EQ(kFallbackNamespaceEntry,
497             cache->GetFallbackEntryUrl(fallback_namespace));
498   EXPECT_FALSE(network_namespace);
499
500   fallback_entry = AppCacheEntry();
501   fallback_namespace = GURL();
502
503   found = cache->FindResponseForRequest(
504       GURL("http://blah/fallback_namespace/longer/path.hit?arg=ok"),
505       &entry, &intercept_namespace,
506       &fallback_entry, &fallback_namespace,
507       &network_namespace);
508   EXPECT_TRUE(found);
509   EXPECT_FALSE(entry.has_response_id());
510   EXPECT_EQ(kFallbackResponseId, fallback_entry.response_id());
511   EXPECT_EQ(kFallbackNamespaceEntry,
512             cache->GetFallbackEntryUrl(fallback_namespace));
513   EXPECT_TRUE(intercept_namespace.is_empty());
514   EXPECT_FALSE(network_namespace);
515 }
516
517
518 TEST(AppCacheTest, FindNetworkNamespacePatternResponseForRequest) {
519   MockAppCacheService service;
520
521   // Setup an appcache with a network namespace that uses pattern matching.
522   const GURL kNetworkNamespaceBase("http://blah/network_namespace/");
523   const GURL kNetworkPatternNamespace(
524       kNetworkNamespaceBase.Resolve("*.hit*"));
525   Manifest manifest;
526   manifest.online_whitelist_namespaces.push_back(
527       Namespace(NETWORK_NAMESPACE, kNetworkPatternNamespace,
528                 GURL(), true));
529   manifest.online_whitelist_all = false;
530   scoped_refptr<AppCache> cache(new AppCache(service.storage(), 1234));
531   cache->InitializeWithManifest(&manifest);
532   cache->set_complete(true);
533
534   // See that the pattern match works.
535   bool found = false;
536   AppCacheEntry entry;
537   AppCacheEntry fallback_entry;
538   GURL intercept_namespace;
539   GURL fallback_namespace;
540   bool network_namespace = false;
541
542   found = cache->FindResponseForRequest(
543       GURL("http://blah/miss"),
544       &entry, &intercept_namespace,
545       &fallback_entry, &fallback_namespace,
546       &network_namespace);
547   EXPECT_FALSE(found);
548
549   found = cache->FindResponseForRequest(
550       GURL("http://blah/network_namespace/path.hit"),
551       &entry, &intercept_namespace,
552       &fallback_entry, &fallback_namespace,
553       &network_namespace);
554   EXPECT_TRUE(found);
555   EXPECT_TRUE(network_namespace);
556   EXPECT_FALSE(entry.has_response_id());
557   EXPECT_FALSE(fallback_entry.has_response_id());
558 }
559
560 TEST(AppCacheTest, ToFromDatabaseRecords) {
561   // Setup a cache with some entries.
562   const int64 kCacheId = 1234;
563   const int64 kGroupId = 4321;
564   const GURL kManifestUrl("http://foo.com/manifest");
565   const GURL kInterceptUrl("http://foo.com/intercept.html");
566   const GURL kFallbackUrl("http://foo.com/fallback.html");
567   const GURL kWhitelistUrl("http://foo.com/whitelist*");
568   const std::string kData(
569     "CACHE MANIFEST\r"
570     "CHROMIUM-INTERCEPT:\r"
571     "/intercept return /intercept.html\r"
572     "FALLBACK:\r"
573     "/ /fallback.html\r"
574     "NETWORK:\r"
575     "/whitelist* isPattern\r"
576     "*\r");
577   MockAppCacheService service;
578   scoped_refptr<AppCacheGroup> group =
579       new AppCacheGroup(service.storage(), kManifestUrl, kGroupId);
580   scoped_refptr<AppCache> cache(new AppCache(service.storage(), kCacheId));
581   Manifest manifest;
582   EXPECT_TRUE(ParseManifest(kManifestUrl, kData.c_str(), kData.length(),
583                             PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest));
584   cache->InitializeWithManifest(&manifest);
585   EXPECT_EQ(NETWORK_NAMESPACE, cache->online_whitelist_namespaces_[0].type);
586   EXPECT_TRUE(cache->online_whitelist_namespaces_[0].is_pattern);
587   EXPECT_EQ(kWhitelistUrl,
588             cache->online_whitelist_namespaces_[0].namespace_url);
589   cache->AddEntry(
590       kManifestUrl,
591       AppCacheEntry(AppCacheEntry::MANIFEST, 1, 1));
592   cache->AddEntry(
593       kInterceptUrl,
594       AppCacheEntry(AppCacheEntry::INTERCEPT, 3, 3));
595   cache->AddEntry(
596       kFallbackUrl,
597       AppCacheEntry(AppCacheEntry::FALLBACK, 2, 2));
598
599   // Get it to produce database records and verify them.
600   AppCacheDatabase::CacheRecord cache_record;
601   std::vector<AppCacheDatabase::EntryRecord> entries;
602   std::vector<AppCacheDatabase::NamespaceRecord> intercepts;
603   std::vector<AppCacheDatabase::NamespaceRecord> fallbacks;
604   std::vector<AppCacheDatabase::OnlineWhiteListRecord> whitelists;
605   cache->ToDatabaseRecords(group.get(),
606                            &cache_record,
607                            &entries,
608                            &intercepts,
609                            &fallbacks,
610                            &whitelists);
611   EXPECT_EQ(kCacheId, cache_record.cache_id);
612   EXPECT_EQ(kGroupId, cache_record.group_id);
613   EXPECT_TRUE(cache_record.online_wildcard);
614   EXPECT_EQ(1 + 2 + 3, cache_record.cache_size);
615   EXPECT_EQ(3u, entries.size());
616   EXPECT_EQ(1u, intercepts.size());
617   EXPECT_EQ(1u, fallbacks.size());
618   EXPECT_EQ(1u, whitelists.size());
619   cache = NULL;
620
621   // Create a new AppCache and populate it with those records and verify.
622   cache = new AppCache(service.storage(), kCacheId);
623   cache->InitializeWithDatabaseRecords(
624       cache_record, entries, intercepts,
625       fallbacks, whitelists);
626   EXPECT_TRUE(cache->online_whitelist_all_);
627   EXPECT_EQ(3u, cache->entries().size());
628   EXPECT_TRUE(cache->GetEntry(kManifestUrl));
629   EXPECT_TRUE(cache->GetEntry(kInterceptUrl));
630   EXPECT_TRUE(cache->GetEntry(kFallbackUrl));
631   EXPECT_EQ(kInterceptUrl,
632             cache->GetInterceptEntryUrl(GURL("http://foo.com/intercept")));
633   EXPECT_EQ(kFallbackUrl,
634             cache->GetFallbackEntryUrl(GURL("http://foo.com/")));
635   EXPECT_EQ(1 + 2 + 3, cache->cache_size());
636   EXPECT_EQ(NETWORK_NAMESPACE, cache->online_whitelist_namespaces_[0].type);
637   EXPECT_TRUE(cache->online_whitelist_namespaces_[0].is_pattern);
638   EXPECT_EQ(kWhitelistUrl,
639             cache->online_whitelist_namespaces_[0].namespace_url);
640 }
641
642 TEST(AppCacheTest, IsNamespaceMatch) {
643   Namespace prefix;
644   prefix.namespace_url = GURL("http://foo.com/prefix");
645   prefix.is_pattern = false;
646   EXPECT_TRUE(prefix.IsMatch(
647       GURL("http://foo.com/prefix_and_anothing_goes")));
648   EXPECT_FALSE(prefix.IsMatch(
649       GURL("http://foo.com/nope")));
650
651   Namespace bar_no_star;
652   bar_no_star.namespace_url = GURL("http://foo.com/bar");
653   bar_no_star.is_pattern = true;
654   EXPECT_TRUE(bar_no_star.IsMatch(
655       GURL("http://foo.com/bar")));
656   EXPECT_FALSE(bar_no_star.IsMatch(
657       GURL("http://foo.com/bar/nope")));
658
659   Namespace bar_star;
660   bar_star.namespace_url = GURL("http://foo.com/bar/*");
661   bar_star.is_pattern = true;
662   EXPECT_TRUE(bar_star.IsMatch(
663       GURL("http://foo.com/bar/")));
664   EXPECT_TRUE(bar_star.IsMatch(
665       GURL("http://foo.com/bar/should_match")));
666   EXPECT_FALSE(bar_star.IsMatch(
667       GURL("http://foo.com/not_bar/should_not_match")));
668
669   Namespace star_bar_star;
670   star_bar_star.namespace_url = GURL("http://foo.com/*/bar/*");
671   star_bar_star.is_pattern = true;
672   EXPECT_TRUE(star_bar_star.IsMatch(
673       GURL("http://foo.com/any/bar/should_match")));
674   EXPECT_TRUE(star_bar_star.IsMatch(
675       GURL("http://foo.com/any/bar/")));
676   EXPECT_FALSE(star_bar_star.IsMatch(
677       GURL("http://foo.com/any/not_bar/no_match")));
678
679   Namespace query_star_edit;
680   query_star_edit.namespace_url = GURL("http://foo.com/query?id=*&verb=edit*");
681   query_star_edit.is_pattern = true;
682   EXPECT_TRUE(query_star_edit.IsMatch(
683       GURL("http://foo.com/query?id=1234&verb=edit&option=blue")));
684   EXPECT_TRUE(query_star_edit.IsMatch(
685       GURL("http://foo.com/query?id=12345&option=blue&verb=edit")));
686   EXPECT_FALSE(query_star_edit.IsMatch(
687       GURL("http://foo.com/query?id=12345&option=blue&verb=print")));
688   EXPECT_TRUE(query_star_edit.IsMatch(
689       GURL("http://foo.com/query?id=123&verb=print&verb=edit")));
690
691   Namespace star_greediness;
692   star_greediness.namespace_url = GURL("http://foo.com/*/b");
693   star_greediness.is_pattern = true;
694   EXPECT_TRUE(star_greediness.IsMatch(
695       GURL("http://foo.com/a/b")));
696   EXPECT_TRUE(star_greediness.IsMatch(
697       GURL("http://foo.com/a/wxy/z/b")));
698   EXPECT_TRUE(star_greediness.IsMatch(
699       GURL("http://foo.com/a/b/b")));
700   EXPECT_TRUE(star_greediness.IsMatch(
701       GURL("http://foo.com/b/b")));
702   EXPECT_TRUE(star_greediness.IsMatch(
703       GURL("http://foo.com/a/b/b/b/b/b")));
704   EXPECT_TRUE(star_greediness.IsMatch(
705       GURL("http://foo.com/a/b/b/b/a/b")));
706   EXPECT_TRUE(star_greediness.IsMatch(
707       GURL("http://foo.com/a/b/01234567890abcdef/b")));
708   EXPECT_TRUE(star_greediness.IsMatch(
709       GURL("http://foo.com/a/b/01234567890abcdef/b01234567890abcdef/b")));
710   EXPECT_TRUE(star_greediness.IsMatch(
711       GURL("http://foo.com/a/b/01234567890abcdef_eat_some_more_characters_"
712            "/and_even_more_for_the_heck_of_it/01234567890abcdef/b")));
713 }
714
715 }  // namespace content