Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / browser / appcache / appcache_update_job_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/bind.h"
6 #include "base/bind_helpers.h"
7 #include "base/stl_util.h"
8 #include "base/synchronization/waitable_event.h"
9 #include "base/threading/thread.h"
10 #include "content/browser/appcache/appcache_group.h"
11 #include "content/browser/appcache/appcache_host.h"
12 #include "content/browser/appcache/appcache_response.h"
13 #include "content/browser/appcache/appcache_update_job.h"
14 #include "content/browser/appcache/mock_appcache_service.h"
15 #include "net/base/net_errors.h"
16 #include "net/http/http_response_headers.h"
17 #include "net/url_request/url_request_error_job.h"
18 #include "net/url_request/url_request_job_factory_impl.h"
19 #include "net/url_request/url_request_test_job.h"
20 #include "net/url_request/url_request_test_util.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22
23 namespace content {
24 class AppCacheUpdateJobTest;
25
26 namespace {
27
28 const char kManifest1Contents[] =
29     "CACHE MANIFEST\n"
30     "explicit1\n"
31     "FALLBACK:\n"
32     "fallback1 fallback1a\n"
33     "NETWORK:\n"
34     "*\n";
35
36 // There are a handful of http accessible resources that we need to conduct
37 // these tests. Instead of running a seperate server to host these resources,
38 // we mock them up.
39 class MockHttpServer {
40  public:
41   static GURL GetMockUrl(const std::string& path) {
42     return GURL("http://mockhost/" + path);
43   }
44
45   static GURL GetMockHttpsUrl(const std::string& path) {
46     return GURL("https://mockhost/" + path);
47   }
48
49   static GURL GetMockCrossOriginHttpsUrl(const std::string& path) {
50     return GURL("https://cross_origin_host/" + path);
51   }
52
53   static net::URLRequestJob* JobFactory(
54       net::URLRequest* request, net::NetworkDelegate* network_delegate) {
55     if (request->url().host() != "mockhost" &&
56         request->url().host() != "cross_origin_host")
57       return new net::URLRequestErrorJob(request, network_delegate, -100);
58
59     std::string headers, body;
60     GetMockResponse(request->url().path(), &headers, &body);
61     return new net::URLRequestTestJob(
62         request, network_delegate, headers, body, true);
63   }
64
65  private:
66   static void GetMockResponse(const std::string& path,
67                               std::string* headers,
68                               std::string* body) {
69     const char ok_headers[] =
70         "HTTP/1.1 200 OK\0"
71         "\0";
72     const char error_headers[] =
73         "HTTP/1.1 500 BOO HOO\0"
74         "\0";
75     const char manifest_headers[] =
76         "HTTP/1.1 200 OK\0"
77         "Content-type: text/cache-manifest\0"
78         "\0";
79     const char not_modified_headers[] =
80         "HTTP/1.1 304 NOT MODIFIED\0"
81         "\0";
82     const char gone_headers[] =
83         "HTTP/1.1 410 GONE\0"
84         "\0";
85     const char not_found_headers[] =
86         "HTTP/1.1 404 NOT FOUND\0"
87         "\0";
88     const char no_store_headers[] =
89         "HTTP/1.1 200 OK\0"
90         "Cache-Control: no-store\0"
91         "\0";
92
93     if (path == "/files/missing-mime-manifest") {
94       (*headers) = std::string(ok_headers, arraysize(ok_headers));
95       (*body) = "CACHE MANIFEST\n";
96     } else if (path == "/files/bad-manifest") {
97       (*headers) = std::string(manifest_headers, arraysize(manifest_headers));
98       (*body) = "BAD CACHE MANIFEST";
99     } else if (path == "/files/empty1") {
100       (*headers) = std::string(ok_headers, arraysize(ok_headers));
101       (*body) = "";
102     } else if (path == "/files/empty-file-manifest") {
103       (*headers) = std::string(manifest_headers, arraysize(manifest_headers));
104       (*body) = "CACHE MANIFEST\n"
105                 "empty1\n";
106     } else if (path == "/files/empty-manifest") {
107       (*headers) = std::string(manifest_headers, arraysize(manifest_headers));
108       (*body) = "CACHE MANIFEST\n";
109     } else if (path == "/files/explicit1") {
110       (*headers) = std::string(ok_headers, arraysize(ok_headers));
111       (*body) = "explicit1";
112     } else if (path == "/files/explicit2") {
113       (*headers) = std::string(ok_headers, arraysize(ok_headers));
114       (*body) = "explicit2";
115     } else if (path == "/files/fallback1a") {
116       (*headers) = std::string(ok_headers, arraysize(ok_headers));
117       (*body) = "fallback1a";
118     } else if (path == "/files/intercept1a") {
119       (*headers) = std::string(ok_headers, arraysize(ok_headers));
120       (*body) = "intercept1a";
121     } else if (path == "/files/gone") {
122       (*headers) = std::string(gone_headers, arraysize(gone_headers));
123       (*body) = "";
124     } else if (path == "/files/manifest1") {
125       (*headers) = std::string(manifest_headers, arraysize(manifest_headers));
126       (*body) = kManifest1Contents;
127     } else if (path == "/files/manifest1-with-notmodified") {
128       (*headers) = std::string(manifest_headers, arraysize(manifest_headers));
129       (*body) = kManifest1Contents;
130       (*body).append("CACHE:\n"
131                      "notmodified\n");
132     } else if (path == "/files/manifest-fb-404") {
133       (*headers) = std::string(manifest_headers, arraysize(manifest_headers));
134       (*body) = "CACHE MANIFEST\n"
135                 "explicit1\n"
136                 "FALLBACK:\n"
137                 "fallback1 fallback1a\n"
138                 "fallback404 fallback-404\n"
139                 "NETWORK:\n"
140                 "online1\n";
141     } else if (path == "/files/manifest-merged-types") {
142       (*headers) = std::string(manifest_headers, arraysize(manifest_headers));
143       (*body) = "CACHE MANIFEST\n"
144                 "explicit1\n"
145                 "# manifest is also an explicit entry\n"
146                 "manifest-merged-types\n"
147                 "FALLBACK:\n"
148                 "# fallback is also explicit entry\n"
149                 "fallback1 explicit1\n"
150                 "NETWORK:\n"
151                 "online1\n";
152     } else if (path == "/files/manifest-with-404") {
153       (*headers) = std::string(manifest_headers, arraysize(manifest_headers));
154       (*body) = "CACHE MANIFEST\n"
155                 "explicit-404\n"
156                 "explicit1\n"
157                 "explicit2\n"
158                 "explicit3\n"
159                 "FALLBACK:\n"
160                 "fallback1 fallback1a\n"
161                 "NETWORK:\n"
162                 "online1\n";
163     } else if (path == "/files/manifest-with-intercept") {
164       (*headers) = std::string(manifest_headers, arraysize(manifest_headers));
165       (*body) = "CACHE MANIFEST\n"
166                 "CHROMIUM-INTERCEPT:\n"
167                 "intercept1 return intercept1a\n";
168     } else if (path == "/files/notmodified") {
169       (*headers) = std::string(not_modified_headers,
170                                arraysize(not_modified_headers));
171       (*body) = "";
172     } else if (path == "/files/servererror") {
173       (*headers) = std::string(error_headers,
174                                arraysize(error_headers));
175       (*body) = "error";
176     } else if (path == "/files/valid_cross_origin_https_manifest") {
177       (*headers) = std::string(manifest_headers, arraysize(manifest_headers));
178       (*body) = "CACHE MANIFEST\n"
179                 "https://cross_origin_host/files/explicit1\n";
180     } else if (path == "/files/invalid_cross_origin_https_manifest") {
181       (*headers) = std::string(manifest_headers, arraysize(manifest_headers));
182       (*body) = "CACHE MANIFEST\n"
183                 "https://cross_origin_host/files/no-store-headers\n";
184     } else if (path == "/files/no-store-headers") {
185       (*headers) = std::string(no_store_headers, arraysize(no_store_headers));
186       (*body) = "no-store";
187     } else {
188       (*headers) = std::string(not_found_headers,
189                                arraysize(not_found_headers));
190       (*body) = "";
191     }
192   }
193 };
194
195 class MockHttpServerJobFactory
196     : public net::URLRequestJobFactory::ProtocolHandler {
197  public:
198   net::URLRequestJob* MaybeCreateJob(
199       net::URLRequest* request,
200       net::NetworkDelegate* network_delegate) const override {
201     return MockHttpServer::JobFactory(request, network_delegate);
202   }
203 };
204
205 inline bool operator==(const AppCacheNamespace& lhs,
206     const AppCacheNamespace& rhs) {
207   return lhs.type == rhs.type &&
208          lhs.namespace_url == rhs.namespace_url &&
209          lhs.target_url == rhs.target_url;
210 }
211
212 }  // namespace
213
214 class MockFrontend : public AppCacheFrontend {
215  public:
216   MockFrontend()
217       : ignore_progress_events_(false), verify_progress_events_(false),
218         last_progress_total_(-1), last_progress_complete_(-1),
219         start_update_trigger_(APPCACHE_CHECKING_EVENT), update_(NULL) {
220   }
221
222   void OnCacheSelected(int host_id, const AppCacheInfo& info) override {}
223
224   void OnStatusChanged(const std::vector<int>& host_ids,
225                        AppCacheStatus status) override {}
226
227   void OnEventRaised(const std::vector<int>& host_ids,
228                      AppCacheEventID event_id) override {
229     raised_events_.push_back(RaisedEvent(host_ids, event_id));
230
231     // Trigger additional updates if requested.
232     if (event_id == start_update_trigger_ && update_) {
233       for (std::vector<AppCacheHost*>::iterator it = update_hosts_.begin();
234            it != update_hosts_.end(); ++it) {
235         AppCacheHost* host = *it;
236         update_->StartUpdate(host,
237             (host ? host->pending_master_entry_url() : GURL()));
238       }
239       update_hosts_.clear();  // only trigger once
240     }
241   }
242
243   void OnErrorEventRaised(const std::vector<int>& host_ids,
244                           const AppCacheErrorDetails& details) override {
245     error_message_ = details.message;
246     OnEventRaised(host_ids, APPCACHE_ERROR_EVENT);
247   }
248
249   void OnProgressEventRaised(const std::vector<int>& host_ids,
250                              const GURL& url,
251                              int num_total,
252                              int num_complete) override {
253     if (!ignore_progress_events_)
254       OnEventRaised(host_ids, APPCACHE_PROGRESS_EVENT);
255
256     if (verify_progress_events_) {
257       EXPECT_GE(num_total, num_complete);
258       EXPECT_GE(num_complete, 0);
259
260       if (last_progress_total_ == -1) {
261         // Should start at zero.
262         EXPECT_EQ(0, num_complete);
263       } else {
264         // Total should be stable and complete should bump up by one at a time.
265         EXPECT_EQ(last_progress_total_, num_total);
266         EXPECT_EQ(last_progress_complete_ + 1, num_complete);
267       }
268
269       // Url should be valid for all except the 'final' event.
270       if (num_total == num_complete)
271         EXPECT_TRUE(url.is_empty());
272       else
273         EXPECT_TRUE(url.is_valid());
274
275       last_progress_total_ = num_total;
276       last_progress_complete_ = num_complete;
277     }
278   }
279
280   void OnLogMessage(int host_id,
281                     AppCacheLogLevel log_level,
282                     const std::string& message) override {}
283
284   void OnContentBlocked(int host_id, const GURL& manifest_url) override {}
285
286   void AddExpectedEvent(const std::vector<int>& host_ids,
287       AppCacheEventID event_id) {
288     DCHECK(!ignore_progress_events_ || event_id != APPCACHE_PROGRESS_EVENT);
289     expected_events_.push_back(RaisedEvent(host_ids, event_id));
290   }
291
292   void SetIgnoreProgressEvents(bool ignore) {
293     // Some tests involve joining new hosts to an already running update job
294     // or intentionally failing. The timing and sequencing of the progress
295     // events generated by an update job are dependent on the behavior of
296     // an external HTTP server. For jobs that do not run fully till completion,
297     // due to either joining late or early exit, we skip monitoring the
298     // progress events to avoid flakiness.
299     ignore_progress_events_ = ignore;
300   }
301
302   void SetVerifyProgressEvents(bool verify) {
303     verify_progress_events_ = verify;
304   }
305
306   void TriggerAdditionalUpdates(AppCacheEventID trigger_event,
307                                 AppCacheUpdateJob* update) {
308     start_update_trigger_ = trigger_event;
309     update_ = update;
310   }
311
312   void AdditionalUpdateHost(AppCacheHost* host) {
313     update_hosts_.push_back(host);
314   }
315
316   typedef std::vector<int> HostIds;
317   typedef std::pair<HostIds, AppCacheEventID> RaisedEvent;
318   typedef std::vector<RaisedEvent> RaisedEvents;
319   RaisedEvents raised_events_;
320   std::string error_message_;
321
322   // Set the expected events if verification needs to happen asynchronously.
323   RaisedEvents expected_events_;
324   std::string expected_error_message_;
325
326   bool ignore_progress_events_;
327
328   bool verify_progress_events_;
329   int last_progress_total_;
330   int last_progress_complete_;
331
332   // Add ability for frontend to add master entries to an inprogress update.
333   AppCacheEventID start_update_trigger_;
334   AppCacheUpdateJob* update_;
335   std::vector<AppCacheHost*> update_hosts_;
336 };
337
338 // Helper factories to simulate redirected URL responses for tests.
339 class RedirectFactory : public net::URLRequestJobFactory::ProtocolHandler {
340  public:
341   net::URLRequestJob* MaybeCreateJob(
342       net::URLRequest* request,
343       net::NetworkDelegate* network_delegate) const override {
344     return new net::URLRequestTestJob(
345         request,
346         network_delegate,
347         net::URLRequestTestJob::test_redirect_headers(),
348         net::URLRequestTestJob::test_data_1(),
349         true);
350   }
351 };
352
353 // Helper class to simulate a URL that returns retry or success.
354 class RetryRequestTestJob : public net::URLRequestTestJob {
355  public:
356   enum RetryHeader {
357     NO_RETRY_AFTER,
358     NONZERO_RETRY_AFTER,
359     RETRY_AFTER_0,
360   };
361
362   static const GURL kRetryUrl;
363
364   // Call this at the start of each retry test.
365   static void Initialize(int num_retry_responses, RetryHeader header,
366       int expected_requests) {
367     num_requests_ = 0;
368     num_retries_ = num_retry_responses;
369     retry_after_ = header;
370     expected_requests_ = expected_requests;
371   }
372
373   // Verifies results at end of test and resets counters.
374   static void Verify() {
375     EXPECT_EQ(expected_requests_, num_requests_);
376     num_requests_ = 0;
377     expected_requests_ = 0;
378   }
379
380   static net::URLRequestJob* RetryFactory(
381       net::URLRequest* request, net::NetworkDelegate* network_delegate) {
382     ++num_requests_;
383     if (num_retries_ > 0 && request->original_url() == kRetryUrl) {
384       --num_retries_;
385       return new RetryRequestTestJob(
386           request, network_delegate, RetryRequestTestJob::retry_headers(), 503);
387     } else {
388       return new RetryRequestTestJob(
389           request,
390           network_delegate,
391           RetryRequestTestJob::manifest_headers(), 200);
392     }
393   }
394
395   int GetResponseCode() const override { return response_code_; }
396
397  private:
398   ~RetryRequestTestJob() override {}
399
400   static std::string retry_headers() {
401     const char no_retry_after[] =
402         "HTTP/1.1 503 BOO HOO\0"
403         "\0";
404     const char nonzero[] =
405         "HTTP/1.1 503 BOO HOO\0"
406         "Retry-After: 60\0"
407         "\0";
408     const char retry_after_0[] =
409         "HTTP/1.1 503 BOO HOO\0"
410         "Retry-After: 0\0"
411         "\0";
412
413     switch (retry_after_) {
414       case NO_RETRY_AFTER:
415         return std::string(no_retry_after, arraysize(no_retry_after));
416       case NONZERO_RETRY_AFTER:
417         return std::string(nonzero, arraysize(nonzero));
418       case RETRY_AFTER_0:
419       default:
420         return std::string(retry_after_0, arraysize(retry_after_0));
421     }
422   }
423
424   static std::string manifest_headers() {
425     const char headers[] =
426         "HTTP/1.1 200 OK\0"
427         "Content-type: text/cache-manifest\0"
428         "\0";
429     return std::string(headers, arraysize(headers));
430   }
431
432   static std::string data() {
433     return std::string("CACHE MANIFEST\r"
434         "http://retry\r");  // must be same as kRetryUrl
435   }
436
437   RetryRequestTestJob(net::URLRequest* request,
438                       net::NetworkDelegate* network_delegate,
439                       const std::string& headers,
440                       int response_code)
441       : net::URLRequestTestJob(
442             request, network_delegate, headers, data(), true),
443         response_code_(response_code) {
444   }
445
446   int response_code_;
447
448   static int num_requests_;
449   static int num_retries_;
450   static RetryHeader retry_after_;
451   static int expected_requests_;
452 };
453
454 class RetryRequestTestJobFactory
455     : public net::URLRequestJobFactory::ProtocolHandler {
456  public:
457   net::URLRequestJob* MaybeCreateJob(
458       net::URLRequest* request,
459       net::NetworkDelegate* network_delegate) const override {
460     return RetryRequestTestJob::RetryFactory(request, network_delegate);
461   }
462 };
463
464 // static
465 const GURL RetryRequestTestJob::kRetryUrl("http://retry");
466 int RetryRequestTestJob::num_requests_ = 0;
467 int RetryRequestTestJob::num_retries_;
468 RetryRequestTestJob::RetryHeader RetryRequestTestJob::retry_after_;
469 int RetryRequestTestJob::expected_requests_ = 0;
470
471 // Helper class to check for certain HTTP headers.
472 class HttpHeadersRequestTestJob : public net::URLRequestTestJob {
473  public:
474   // Call this at the start of each HTTP header-related test.
475   static void Initialize(const std::string& expect_if_modified_since,
476                          const std::string& expect_if_none_match) {
477     expect_if_modified_since_ = expect_if_modified_since;
478     expect_if_none_match_ = expect_if_none_match;
479   }
480
481   // Verifies results at end of test and resets class.
482   static void Verify() {
483     if (!expect_if_modified_since_.empty())
484       EXPECT_TRUE(saw_if_modified_since_);
485     if (!expect_if_none_match_.empty())
486       EXPECT_TRUE(saw_if_none_match_);
487
488     // Reset.
489     expect_if_modified_since_.clear();
490     saw_if_modified_since_ = false;
491     expect_if_none_match_.clear();
492     saw_if_none_match_ = false;
493     already_checked_ = false;
494   }
495
496   static net::URLRequestJob* IfModifiedSinceFactory(
497       net::URLRequest* request, net::NetworkDelegate* network_delegate) {
498     if (!already_checked_) {
499       already_checked_ = true;  // only check once for a test
500       const net::HttpRequestHeaders& extra_headers =
501           request->extra_request_headers();
502       std::string header_value;
503       saw_if_modified_since_ =
504           extra_headers.GetHeader(
505               net::HttpRequestHeaders::kIfModifiedSince, &header_value) &&
506           header_value == expect_if_modified_since_;
507
508       saw_if_none_match_ =
509           extra_headers.GetHeader(
510               net::HttpRequestHeaders::kIfNoneMatch, &header_value) &&
511           header_value == expect_if_none_match_;
512     }
513     return MockHttpServer::JobFactory(request, network_delegate);
514   }
515
516  protected:
517   ~HttpHeadersRequestTestJob() override {}
518
519  private:
520   static std::string expect_if_modified_since_;
521   static bool saw_if_modified_since_;
522   static std::string expect_if_none_match_;
523   static bool saw_if_none_match_;
524   static bool already_checked_;
525 };
526
527 // static
528 std::string HttpHeadersRequestTestJob::expect_if_modified_since_;
529 bool HttpHeadersRequestTestJob::saw_if_modified_since_ = false;
530 std::string HttpHeadersRequestTestJob::expect_if_none_match_;
531 bool HttpHeadersRequestTestJob::saw_if_none_match_ = false;
532 bool HttpHeadersRequestTestJob::already_checked_ = false;
533
534 class IfModifiedSinceJobFactory
535     : public net::URLRequestJobFactory::ProtocolHandler {
536  public:
537   net::URLRequestJob* MaybeCreateJob(
538       net::URLRequest* request,
539       net::NetworkDelegate* network_delegate) const override {
540     return HttpHeadersRequestTestJob::IfModifiedSinceFactory(
541         request, network_delegate);
542   }
543 };
544
545 class IOThread : public base::Thread {
546  public:
547   explicit IOThread(const char* name)
548       : base::Thread(name) {
549   }
550
551   ~IOThread() override { Stop(); }
552
553   net::URLRequestContext* request_context() {
554     return request_context_.get();
555   }
556
557   void SetNewJobFactory(net::URLRequestJobFactory* job_factory) {
558     DCHECK(job_factory);
559     job_factory_.reset(job_factory);
560     request_context_->set_job_factory(job_factory_.get());
561   }
562
563   void Init() override {
564     scoped_ptr<net::URLRequestJobFactoryImpl> factory(
565         new net::URLRequestJobFactoryImpl());
566     factory->SetProtocolHandler("http", new MockHttpServerJobFactory);
567     factory->SetProtocolHandler("https", new MockHttpServerJobFactory);
568     job_factory_ = factory.Pass();
569     request_context_.reset(new net::TestURLRequestContext());
570     request_context_->set_job_factory(job_factory_.get());
571   }
572
573   void CleanUp() override {
574     request_context_.reset();
575     job_factory_.reset();
576   }
577
578  private:
579   scoped_ptr<net::URLRequestJobFactory> job_factory_;
580   scoped_ptr<net::URLRequestContext> request_context_;
581 };
582
583 class AppCacheUpdateJobTest : public testing::Test,
584                               public AppCacheGroup::UpdateObserver {
585  public:
586   AppCacheUpdateJobTest()
587       : do_checks_after_update_finished_(false),
588         expect_group_obsolete_(false),
589         expect_group_has_cache_(false),
590         expect_group_is_being_deleted_(false),
591         expect_old_cache_(NULL),
592         expect_newest_cache_(NULL),
593         expect_non_null_update_time_(false),
594         tested_manifest_(NONE),
595         tested_manifest_path_override_(NULL) {
596     io_thread_.reset(new IOThread("AppCacheUpdateJob IO test thread"));
597     base::Thread::Options options(base::MessageLoop::TYPE_IO, 0);
598     io_thread_->StartWithOptions(options);
599   }
600
601   // Use a separate IO thread to run a test. Thread will be destroyed
602   // when it goes out of scope.
603   template <class Method>
604   void RunTestOnIOThread(Method method) {
605     event_.reset(new base::WaitableEvent(false, false));
606     io_thread_->message_loop()->PostTask(
607         FROM_HERE, base::Bind(method, base::Unretained(this)));
608
609     // Wait until task is done before exiting the test.
610     event_->Wait();
611   }
612
613   void StartCacheAttemptTest() {
614     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
615
616     MakeService();
617     group_ = new AppCacheGroup(service_->storage(), GURL("http://failme"),
618                                service_->storage()->NewGroupId());
619
620     AppCacheUpdateJob* update =
621         new AppCacheUpdateJob(service_.get(), group_.get());
622     group_->update_job_ = update;
623
624     MockFrontend mock_frontend;
625     AppCacheHost host(1, &mock_frontend, service_.get());
626
627     update->StartUpdate(&host, GURL());
628
629     // Verify state.
630     EXPECT_EQ(AppCacheUpdateJob::CACHE_ATTEMPT, update->update_type_);
631     EXPECT_EQ(AppCacheUpdateJob::FETCH_MANIFEST, update->internal_state_);
632     EXPECT_EQ(AppCacheGroup::CHECKING, group_->update_status());
633
634     // Verify notifications.
635     MockFrontend::RaisedEvents& events = mock_frontend.raised_events_;
636     size_t expected = 1;
637     EXPECT_EQ(expected, events.size());
638     EXPECT_EQ(expected, events[0].first.size());
639     EXPECT_EQ(host.host_id(), events[0].first[0]);
640     EXPECT_EQ(APPCACHE_CHECKING_EVENT, events[0].second);
641
642     // Abort as we're not testing actual URL fetches in this test.
643     delete update;
644     UpdateFinished();
645   }
646
647   void StartUpgradeAttemptTest() {
648     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
649
650     {
651       MakeService();
652       group_ = new AppCacheGroup(service_->storage(), GURL("http://failme"),
653                                  service_->storage()->NewGroupId());
654
655       // Give the group some existing caches.
656       AppCache* cache1 = MakeCacheForGroup(1, 111);
657       AppCache* cache2 = MakeCacheForGroup(2, 222);
658
659       // Associate some hosts with caches in the group.
660       MockFrontend mock_frontend1;
661       MockFrontend mock_frontend2;
662       MockFrontend mock_frontend3;
663
664       AppCacheHost host1(1, &mock_frontend1, service_.get());
665       host1.AssociateCompleteCache(cache1);
666
667       AppCacheHost host2(2, &mock_frontend2, service_.get());
668       host2.AssociateCompleteCache(cache2);
669
670       AppCacheHost host3(3, &mock_frontend1, service_.get());
671       host3.AssociateCompleteCache(cache1);
672
673       AppCacheHost host4(4, &mock_frontend3, service_.get());
674
675       AppCacheUpdateJob* update =
676           new AppCacheUpdateJob(service_.get(), group_.get());
677       group_->update_job_ = update;
678       update->StartUpdate(&host4, GURL());
679
680       // Verify state after starting an update.
681       EXPECT_EQ(AppCacheUpdateJob::UPGRADE_ATTEMPT, update->update_type_);
682       EXPECT_EQ(AppCacheUpdateJob::FETCH_MANIFEST, update->internal_state_);
683       EXPECT_EQ(AppCacheGroup::CHECKING, group_->update_status());
684
685       // Verify notifications.
686       MockFrontend::RaisedEvents& events = mock_frontend1.raised_events_;
687       size_t expected = 1;
688       EXPECT_EQ(expected, events.size());
689       expected = 2;  // 2 hosts using frontend1
690       EXPECT_EQ(expected, events[0].first.size());
691       MockFrontend::HostIds& host_ids = events[0].first;
692       EXPECT_TRUE(std::find(host_ids.begin(), host_ids.end(), host1.host_id())
693           != host_ids.end());
694       EXPECT_TRUE(std::find(host_ids.begin(), host_ids.end(), host3.host_id())
695           != host_ids.end());
696       EXPECT_EQ(APPCACHE_CHECKING_EVENT, events[0].second);
697
698       events = mock_frontend2.raised_events_;
699       expected = 1;
700       EXPECT_EQ(expected, events.size());
701       EXPECT_EQ(expected, events[0].first.size());  // 1 host using frontend2
702       EXPECT_EQ(host2.host_id(), events[0].first[0]);
703       EXPECT_EQ(APPCACHE_CHECKING_EVENT, events[0].second);
704
705       events = mock_frontend3.raised_events_;
706       EXPECT_TRUE(events.empty());
707
708       // Abort as we're not testing actual URL fetches in this test.
709       delete update;
710     }
711     UpdateFinished();
712   }
713
714   void CacheAttemptFetchManifestFailTest() {
715     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
716
717     MakeService();
718     group_ = new AppCacheGroup(service_->storage(), GURL("http://failme"),
719                                service_->storage()->NewGroupId());
720     AppCacheUpdateJob* update =
721         new AppCacheUpdateJob(service_.get(), group_.get());
722     group_->update_job_ = update;
723
724     MockFrontend* frontend = MakeMockFrontend();
725     AppCacheHost* host = MakeHost(1, frontend);
726     update->StartUpdate(host, GURL());
727     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
728
729     update->manifest_fetcher_->request()->CancelWithError(-100);
730
731     // Set up checks for when update job finishes.
732     do_checks_after_update_finished_ = true;
733     expect_group_obsolete_ = false;
734     expect_group_has_cache_ = false;
735     frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()),
736                                APPCACHE_CHECKING_EVENT);
737
738     WaitForUpdateToFinish();
739   }
740
741   void UpgradeFetchManifestFailTest() {
742     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
743
744     MakeService();
745     group_ = new AppCacheGroup(service_->storage(), GURL("http://failme"),
746                                service_->storage()->NewGroupId());
747     AppCacheUpdateJob* update =
748         new AppCacheUpdateJob(service_.get(), group_.get());
749     group_->update_job_ = update;
750
751     AppCache* cache = MakeCacheForGroup(1, 111);
752     MockFrontend* frontend1 = MakeMockFrontend();
753     MockFrontend* frontend2 = MakeMockFrontend();
754     AppCacheHost* host1 = MakeHost(1, frontend1);
755     AppCacheHost* host2 = MakeHost(2, frontend2);
756     host1->AssociateCompleteCache(cache);
757     host2->AssociateCompleteCache(cache);
758
759     update->StartUpdate(NULL, GURL());
760     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
761
762     update->manifest_fetcher_->request()->CancelWithError(-100);
763
764     // Set up checks for when update job finishes.
765     do_checks_after_update_finished_ = true;
766     expect_group_obsolete_ = false;
767     expect_group_has_cache_ = true;
768     expect_newest_cache_ = cache;  // newest cache unaffected by update
769     MockFrontend::HostIds ids1(1, host1->host_id());
770     frontend1->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
771     frontend1->AddExpectedEvent(ids1, APPCACHE_ERROR_EVENT);
772     MockFrontend::HostIds ids2(1, host2->host_id());
773     frontend2->AddExpectedEvent(ids2, APPCACHE_CHECKING_EVENT);
774     frontend2->AddExpectedEvent(ids2, APPCACHE_ERROR_EVENT);
775
776     WaitForUpdateToFinish();
777   }
778
779   void ManifestRedirectTest() {
780     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
781
782     net::URLRequestJobFactoryImpl* new_factory(
783         new net::URLRequestJobFactoryImpl);
784     new_factory->SetProtocolHandler("http", new RedirectFactory);
785     io_thread_->SetNewJobFactory(new_factory);
786
787     MakeService();
788     group_ = new AppCacheGroup(service_->storage(), GURL("http://testme"),
789                                service_->storage()->NewGroupId());
790     AppCacheUpdateJob* update =
791         new AppCacheUpdateJob(service_.get(), group_.get());
792     group_->update_job_ = update;
793
794     MockFrontend* frontend = MakeMockFrontend();
795     AppCacheHost* host = MakeHost(1, frontend);
796     update->StartUpdate(host, GURL());
797     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
798
799     // Set up checks for when update job finishes.
800     do_checks_after_update_finished_ = true;
801     expect_group_obsolete_ = false;
802     expect_group_has_cache_ = false;  // redirect is like a failed request
803     frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()),
804                                APPCACHE_CHECKING_EVENT);
805
806     WaitForUpdateToFinish();
807   }
808
809   void ManifestMissingMimeTypeTest() {
810     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
811
812     MakeService();
813     group_ = new AppCacheGroup(
814         service_->storage(),
815         MockHttpServer::GetMockUrl("files/missing-mime-manifest"),
816         service_->storage()->NewGroupId());
817     AppCacheUpdateJob* update =
818         new AppCacheUpdateJob(service_.get(), group_.get());
819     group_->update_job_ = update;
820
821     AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 33);
822     MockFrontend* frontend = MakeMockFrontend();
823     AppCacheHost* host = MakeHost(1, frontend);
824     host->AssociateCompleteCache(cache);
825
826     frontend->SetVerifyProgressEvents(true);
827
828     update->StartUpdate(NULL, GURL());
829     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
830
831     // Set up checks for when update job finishes.
832     do_checks_after_update_finished_ = true;
833     expect_group_obsolete_ = false;
834     expect_group_has_cache_ = true;
835     expect_old_cache_ = cache;
836     tested_manifest_ = EMPTY_MANIFEST;
837     tested_manifest_path_override_ = "files/missing-mime-manifest";
838     MockFrontend::HostIds ids(1, host->host_id());
839     frontend->AddExpectedEvent(ids, APPCACHE_CHECKING_EVENT);
840     frontend->AddExpectedEvent(ids, APPCACHE_DOWNLOADING_EVENT);
841     frontend->AddExpectedEvent(ids, APPCACHE_PROGRESS_EVENT);  // final
842     frontend->AddExpectedEvent(ids, APPCACHE_UPDATE_READY_EVENT);
843
844     WaitForUpdateToFinish();
845   }
846
847   void ManifestNotFoundTest() {
848     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
849
850     MakeService();
851     group_ = new AppCacheGroup(
852         service_->storage(), MockHttpServer::GetMockUrl("files/nosuchfile"),
853         service_->storage()->NewGroupId());
854     AppCacheUpdateJob* update =
855         new AppCacheUpdateJob(service_.get(), group_.get());
856     group_->update_job_ = update;
857
858     AppCache* cache = MakeCacheForGroup(1, 111);
859     MockFrontend* frontend1 = MakeMockFrontend();
860     MockFrontend* frontend2 = MakeMockFrontend();
861     AppCacheHost* host1 = MakeHost(1, frontend1);
862     AppCacheHost* host2 = MakeHost(2, frontend2);
863     host1->AssociateCompleteCache(cache);
864     host2->AssociateCompleteCache(cache);
865
866     update->StartUpdate(NULL, GURL());
867     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
868
869     // Set up checks for when update job finishes.
870     do_checks_after_update_finished_ = true;
871     expect_group_obsolete_ = true;
872     expect_group_has_cache_ = true;
873     expect_newest_cache_ = cache;  // newest cache unaffected by update
874     MockFrontend::HostIds ids1(1, host1->host_id());
875     frontend1->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
876     frontend1->AddExpectedEvent(ids1, APPCACHE_OBSOLETE_EVENT);
877     MockFrontend::HostIds ids2(1, host2->host_id());
878     frontend2->AddExpectedEvent(ids2, APPCACHE_CHECKING_EVENT);
879     frontend2->AddExpectedEvent(ids2, APPCACHE_OBSOLETE_EVENT);
880
881     WaitForUpdateToFinish();
882   }
883
884   void ManifestGoneTest() {
885     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
886
887     MakeService();
888     group_ = new AppCacheGroup(
889         service_->storage(), MockHttpServer::GetMockUrl("files/gone"),
890         service_->storage()->NewGroupId());
891     AppCacheUpdateJob* update =
892         new AppCacheUpdateJob(service_.get(), group_.get());
893     group_->update_job_ = update;
894
895     MockFrontend* frontend = MakeMockFrontend();
896     AppCacheHost* host = MakeHost(1, frontend);
897     update->StartUpdate(host, GURL());
898     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
899
900     // Set up checks for when update job finishes.
901     do_checks_after_update_finished_ = true;
902     expect_group_obsolete_ = false;
903     expect_group_has_cache_ = false;
904     frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()),
905                                APPCACHE_CHECKING_EVENT);
906
907     WaitForUpdateToFinish();
908   }
909
910   void CacheAttemptNotModifiedTest() {
911     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
912
913     MakeService();
914     group_ = new AppCacheGroup(
915         service_->storage(), MockHttpServer::GetMockUrl("files/notmodified"),
916         service_->storage()->NewGroupId());
917     AppCacheUpdateJob* update =
918         new AppCacheUpdateJob(service_.get(), group_.get());
919     group_->update_job_ = update;
920
921     MockFrontend* frontend = MakeMockFrontend();
922     AppCacheHost* host = MakeHost(1, frontend);
923     update->StartUpdate(host, GURL());
924     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
925
926     // Set up checks for when update job finishes.
927     do_checks_after_update_finished_ = true;
928     expect_group_obsolete_ = false;
929     expect_group_has_cache_ = false;  // treated like cache failure
930     frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()),
931                                APPCACHE_CHECKING_EVENT);
932
933     WaitForUpdateToFinish();
934   }
935
936   void UpgradeNotModifiedTest() {
937     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
938
939     MakeService();
940     group_ = new AppCacheGroup(
941         service_->storage(), MockHttpServer::GetMockUrl("files/notmodified"),
942         service_->storage()->NewGroupId());
943     AppCacheUpdateJob* update =
944         new AppCacheUpdateJob(service_.get(), group_.get());
945     group_->update_job_ = update;
946
947     AppCache* cache = MakeCacheForGroup(1, 111);
948     MockFrontend* frontend1 = MakeMockFrontend();
949     MockFrontend* frontend2 = MakeMockFrontend();
950     AppCacheHost* host1 = MakeHost(1, frontend1);
951     AppCacheHost* host2 = MakeHost(2, frontend2);
952     host1->AssociateCompleteCache(cache);
953     host2->AssociateCompleteCache(cache);
954
955     update->StartUpdate(NULL, GURL());
956     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
957
958     // Set up checks for when update job finishes.
959     do_checks_after_update_finished_ = true;
960     expect_group_obsolete_ = false;
961     expect_group_has_cache_ = true;
962     expect_newest_cache_ = cache;  // newest cache unaffected by update
963     MockFrontend::HostIds ids1(1, host1->host_id());
964     frontend1->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
965     frontend1->AddExpectedEvent(ids1, APPCACHE_NO_UPDATE_EVENT);
966     MockFrontend::HostIds ids2(1, host2->host_id());
967     frontend2->AddExpectedEvent(ids2, APPCACHE_CHECKING_EVENT);
968     frontend2->AddExpectedEvent(ids2, APPCACHE_NO_UPDATE_EVENT);
969
970     WaitForUpdateToFinish();
971   }
972
973   void UpgradeManifestDataUnchangedTest() {
974     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
975
976     MakeService();
977     group_ = new AppCacheGroup(
978         service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"),
979         service_->storage()->NewGroupId());
980     AppCacheUpdateJob* update =
981         new AppCacheUpdateJob(service_.get(), group_.get());
982     group_->update_job_ = update;
983
984     // Create response writer to get a response id.
985     response_writer_.reset(
986         service_->storage()->CreateResponseWriter(group_->manifest_url(),
987                                                   group_->group_id()));
988
989     AppCache* cache = MakeCacheForGroup(1, response_writer_->response_id());
990     MockFrontend* frontend1 = MakeMockFrontend();
991     MockFrontend* frontend2 = MakeMockFrontend();
992     AppCacheHost* host1 = MakeHost(1, frontend1);
993     AppCacheHost* host2 = MakeHost(2, frontend2);
994     host1->AssociateCompleteCache(cache);
995     host2->AssociateCompleteCache(cache);
996
997     // Set up checks for when update job finishes.
998     do_checks_after_update_finished_ = true;
999     expect_group_obsolete_ = false;
1000     expect_group_has_cache_ = true;
1001     expect_newest_cache_ = cache;  // newest cache unaffected by update
1002     MockFrontend::HostIds ids1(1, host1->host_id());
1003     frontend1->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
1004     frontend1->AddExpectedEvent(ids1, APPCACHE_NO_UPDATE_EVENT);
1005     MockFrontend::HostIds ids2(1, host2->host_id());
1006     frontend2->AddExpectedEvent(ids2, APPCACHE_CHECKING_EVENT);
1007     frontend2->AddExpectedEvent(ids2, APPCACHE_NO_UPDATE_EVENT);
1008
1009     // Seed storage with expected manifest data.
1010     const std::string seed_data(kManifest1Contents);
1011     scoped_refptr<net::StringIOBuffer> io_buffer(
1012         new net::StringIOBuffer(seed_data));
1013     response_writer_->WriteData(
1014         io_buffer.get(),
1015         seed_data.length(),
1016         base::Bind(&AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData,
1017                    base::Unretained(this)));
1018
1019     // Start update after data write completes asynchronously.
1020   }
1021
1022   // See http://code.google.com/p/chromium/issues/detail?id=95101
1023   void Bug95101Test() {
1024     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
1025
1026     MakeService();
1027     group_ = new AppCacheGroup(
1028         service_->storage(), MockHttpServer::GetMockUrl("files/empty-manifest"),
1029         service_->storage()->NewGroupId());
1030     AppCacheUpdateJob* update =
1031         new AppCacheUpdateJob(service_.get(), group_.get());
1032     group_->update_job_ = update;
1033
1034     // Create a malformed cache with a missing manifest entry.
1035     GURL wrong_manifest_url =
1036         MockHttpServer::GetMockUrl("files/missing-mime-manifest");
1037     AppCache* cache = MakeCacheForGroup(1, wrong_manifest_url, 111);
1038     MockFrontend* frontend = MakeMockFrontend();
1039     AppCacheHost* host = MakeHost(1, frontend);
1040     host->AssociateCompleteCache(cache);
1041
1042     update->StartUpdate(NULL, GURL());
1043     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
1044
1045     // Set up checks for when update job finishes.
1046     do_checks_after_update_finished_ = true;
1047     expect_group_is_being_deleted_ = true;
1048     expect_group_has_cache_ = true;
1049     expect_newest_cache_ = cache;  // newest cache unaffected by update
1050     MockFrontend::HostIds id(1, host->host_id());
1051     frontend->AddExpectedEvent(id, APPCACHE_CHECKING_EVENT);
1052     frontend->AddExpectedEvent(id, APPCACHE_ERROR_EVENT);
1053     frontend->expected_error_message_ =
1054         "Manifest entry not found in existing cache";
1055     WaitForUpdateToFinish();
1056   }
1057
1058   void StartUpdateAfterSeedingStorageData(int result) {
1059     ASSERT_GT(result, 0);
1060     response_writer_.reset();
1061
1062     AppCacheUpdateJob* update = group_->update_job_;
1063     update->StartUpdate(NULL, GURL());
1064     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
1065
1066     WaitForUpdateToFinish();
1067   }
1068
1069   void BasicCacheAttemptSuccessTest() {
1070     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
1071
1072     GURL manifest_url = MockHttpServer::GetMockUrl("files/manifest1");
1073
1074     MakeService();
1075     group_ = new AppCacheGroup(
1076         service_->storage(), manifest_url,
1077         service_->storage()->NewGroupId());
1078     AppCacheUpdateJob* update =
1079         new AppCacheUpdateJob(service_.get(), group_.get());
1080     group_->update_job_ = update;
1081
1082     MockFrontend* frontend = MakeMockFrontend();
1083     AppCacheHost* host = MakeHost(1, frontend);
1084     update->StartUpdate(host, GURL());
1085
1086     // Set up checks for when update job finishes.
1087     do_checks_after_update_finished_ = true;
1088     expect_group_obsolete_ = false;
1089     expect_group_has_cache_ = true;
1090     tested_manifest_ = MANIFEST1;
1091     frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()),
1092                                APPCACHE_CHECKING_EVENT);
1093
1094     WaitForUpdateToFinish();
1095   }
1096
1097   void DownloadInterceptEntriesTest() {
1098     // Ensures we download intercept entries too.
1099     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
1100     GURL manifest_url =
1101         MockHttpServer::GetMockUrl("files/manifest-with-intercept");
1102     MakeService();
1103     group_ = new AppCacheGroup(
1104         service_->storage(), manifest_url,
1105         service_->storage()->NewGroupId());
1106     AppCacheUpdateJob* update =
1107         new AppCacheUpdateJob(service_.get(), group_.get());
1108     group_->update_job_ = update;
1109
1110     MockFrontend* frontend = MakeMockFrontend();
1111     AppCacheHost* host = MakeHost(1, frontend);
1112     update->StartUpdate(host, GURL());
1113
1114     // Set up checks for when update job finishes.
1115     do_checks_after_update_finished_ = true;
1116     expect_group_obsolete_ = false;
1117     expect_group_has_cache_ = true;
1118     tested_manifest_ = MANIFEST_WITH_INTERCEPT;
1119     frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()),
1120                                APPCACHE_CHECKING_EVENT);
1121
1122     WaitForUpdateToFinish();
1123   }
1124
1125   void BasicUpgradeSuccessTest() {
1126     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
1127
1128     MakeService();
1129     group_ = new AppCacheGroup(
1130         service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"),
1131         service_->storage()->NewGroupId());
1132     AppCacheUpdateJob* update =
1133         new AppCacheUpdateJob(service_.get(), group_.get());
1134     group_->update_job_ = update;
1135
1136     // Create a response writer to get a response id.
1137     response_writer_.reset(
1138         service_->storage()->CreateResponseWriter(group_->manifest_url(),
1139                                                   group_->group_id()));
1140
1141     AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(),
1142                                         response_writer_->response_id());
1143     MockFrontend* frontend1 = MakeMockFrontend();
1144     MockFrontend* frontend2 = MakeMockFrontend();
1145     AppCacheHost* host1 = MakeHost(1, frontend1);
1146     AppCacheHost* host2 = MakeHost(2, frontend2);
1147     host1->AssociateCompleteCache(cache);
1148     host2->AssociateCompleteCache(cache);
1149     frontend1->SetVerifyProgressEvents(true);
1150     frontend2->SetVerifyProgressEvents(true);
1151
1152     // Set up checks for when update job finishes.
1153     do_checks_after_update_finished_ = true;
1154     expect_group_obsolete_ = false;
1155     expect_group_has_cache_ = true;
1156     expect_old_cache_ = cache;
1157     tested_manifest_ = MANIFEST1;
1158     MockFrontend::HostIds ids1(1, host1->host_id());
1159     frontend1->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
1160     frontend1->AddExpectedEvent(ids1, APPCACHE_DOWNLOADING_EVENT);
1161     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);
1162     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);
1163     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // final
1164     frontend1->AddExpectedEvent(ids1, APPCACHE_UPDATE_READY_EVENT);
1165     MockFrontend::HostIds ids2(1, host2->host_id());
1166     frontend2->AddExpectedEvent(ids2, APPCACHE_CHECKING_EVENT);
1167     frontend2->AddExpectedEvent(ids2, APPCACHE_DOWNLOADING_EVENT);
1168     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);
1169     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);
1170     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);  // final
1171     frontend2->AddExpectedEvent(ids2, APPCACHE_UPDATE_READY_EVENT);
1172
1173     // Seed storage with expected manifest data different from manifest1.
1174     const std::string seed_data("different");
1175     scoped_refptr<net::StringIOBuffer> io_buffer(
1176         new net::StringIOBuffer(seed_data));
1177     response_writer_->WriteData(
1178         io_buffer.get(),
1179         seed_data.length(),
1180         base::Bind(&AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData,
1181                    base::Unretained(this)));
1182
1183     // Start update after data write completes asynchronously.
1184   }
1185
1186   void UpgradeLoadFromNewestCacheTest() {
1187     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
1188
1189     MakeService();
1190     group_ = new AppCacheGroup(
1191         service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"),
1192         service_->storage()->NewGroupId());
1193     AppCacheUpdateJob* update =
1194         new AppCacheUpdateJob(service_.get(), group_.get());
1195     group_->update_job_ = update;
1196
1197     AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 42);
1198     MockFrontend* frontend = MakeMockFrontend();
1199     AppCacheHost* host = MakeHost(1, frontend);
1200     host->AssociateCompleteCache(cache);
1201
1202     // Give the newest cache an entry that is in storage.
1203     response_writer_.reset(
1204         service_->storage()->CreateResponseWriter(group_->manifest_url(),
1205                                                   group_->group_id()));
1206     cache->AddEntry(MockHttpServer::GetMockUrl("files/explicit1"),
1207                     AppCacheEntry(AppCacheEntry::EXPLICIT,
1208                                   response_writer_->response_id()));
1209
1210     // Set up checks for when update job finishes.
1211     do_checks_after_update_finished_ = true;
1212     expect_group_obsolete_ = false;
1213     expect_group_has_cache_ = true;
1214     expect_old_cache_ = cache;
1215     expect_response_ids_.insert(
1216         std::map<GURL, int64>::value_type(
1217             MockHttpServer::GetMockUrl("files/explicit1"),
1218             response_writer_->response_id()));
1219     tested_manifest_ = MANIFEST1;
1220     MockFrontend::HostIds ids(1, host->host_id());
1221     frontend->AddExpectedEvent(ids, APPCACHE_CHECKING_EVENT);
1222     frontend->AddExpectedEvent(ids, APPCACHE_DOWNLOADING_EVENT);
1223     frontend->AddExpectedEvent(ids, APPCACHE_PROGRESS_EVENT);
1224     frontend->AddExpectedEvent(ids, APPCACHE_PROGRESS_EVENT);
1225     frontend->AddExpectedEvent(ids, APPCACHE_PROGRESS_EVENT);  // final
1226     frontend->AddExpectedEvent(ids, APPCACHE_UPDATE_READY_EVENT);
1227
1228     // Seed storage with expected http response info for entry. Allow reuse.
1229     const char data[] =
1230         "HTTP/1.1 200 OK\0"
1231         "Cache-Control: max-age=8675309\0"
1232         "\0";
1233     net::HttpResponseHeaders* headers =
1234         new net::HttpResponseHeaders(std::string(data, arraysize(data)));
1235     net::HttpResponseInfo* response_info = new net::HttpResponseInfo();
1236     response_info->request_time = base::Time::Now();
1237     response_info->response_time = base::Time::Now();
1238     response_info->headers = headers;  // adds ref to headers
1239     scoped_refptr<HttpResponseInfoIOBuffer> io_buffer(
1240         new HttpResponseInfoIOBuffer(response_info));  // adds ref to info
1241     response_writer_->WriteInfo(
1242         io_buffer.get(),
1243         base::Bind(&AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData,
1244                    base::Unretained(this)));
1245
1246     // Start update after data write completes asynchronously.
1247   }
1248
1249   void UpgradeNoLoadFromNewestCacheTest() {
1250     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
1251
1252     MakeService();
1253     group_ = new AppCacheGroup(
1254         service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"),
1255         service_->storage()->NewGroupId());
1256     AppCacheUpdateJob* update =
1257         new AppCacheUpdateJob(service_.get(), group_.get());
1258     group_->update_job_ = update;
1259
1260     AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 42);
1261     MockFrontend* frontend = MakeMockFrontend();
1262     AppCacheHost* host = MakeHost(1, frontend);
1263     host->AssociateCompleteCache(cache);
1264
1265     // Give the newest cache an entry that is in storage.
1266     response_writer_.reset(
1267         service_->storage()->CreateResponseWriter(group_->manifest_url(),
1268                                                   group_->group_id()));
1269     cache->AddEntry(MockHttpServer::GetMockUrl("files/explicit1"),
1270                     AppCacheEntry(AppCacheEntry::EXPLICIT,
1271                                   response_writer_->response_id()));
1272
1273     // Set up checks for when update job finishes.
1274     do_checks_after_update_finished_ = true;
1275     expect_group_obsolete_ = false;
1276     expect_group_has_cache_ = true;
1277     expect_old_cache_ = cache;
1278     tested_manifest_ = MANIFEST1;
1279     MockFrontend::HostIds ids(1, host->host_id());
1280     frontend->AddExpectedEvent(ids, APPCACHE_CHECKING_EVENT);
1281     frontend->AddExpectedEvent(ids, APPCACHE_DOWNLOADING_EVENT);
1282     frontend->AddExpectedEvent(ids, APPCACHE_PROGRESS_EVENT);
1283     frontend->AddExpectedEvent(ids, APPCACHE_PROGRESS_EVENT);
1284     frontend->AddExpectedEvent(ids, APPCACHE_PROGRESS_EVENT);  // final
1285     frontend->AddExpectedEvent(ids, APPCACHE_UPDATE_READY_EVENT);
1286
1287     // Seed storage with expected http response info for entry. Do NOT
1288     // allow reuse by setting an expires header in the past.
1289     const char data[] =
1290         "HTTP/1.1 200 OK\0"
1291         "Expires: Thu, 01 Dec 1994 16:00:00 GMT\0"
1292         "\0";
1293     net::HttpResponseHeaders* headers =
1294         new net::HttpResponseHeaders(std::string(data, arraysize(data)));
1295     net::HttpResponseInfo* response_info = new net::HttpResponseInfo();
1296     response_info->request_time = base::Time::Now();
1297     response_info->response_time = base::Time::Now();
1298     response_info->headers = headers;  // adds ref to headers
1299     scoped_refptr<HttpResponseInfoIOBuffer> io_buffer(
1300         new HttpResponseInfoIOBuffer(response_info));  // adds ref to info
1301     response_writer_->WriteInfo(
1302         io_buffer.get(),
1303         base::Bind(&AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData,
1304                    base::Unretained(this)));
1305
1306     // Start update after data write completes asynchronously.
1307   }
1308
1309   void UpgradeLoadFromNewestCacheVaryHeaderTest() {
1310     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
1311
1312     MakeService();
1313     group_ = new AppCacheGroup(
1314         service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"),
1315         service_->storage()->NewGroupId());
1316     AppCacheUpdateJob* update =
1317         new AppCacheUpdateJob(service_.get(), group_.get());
1318     group_->update_job_ = update;
1319
1320     AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 42);
1321     MockFrontend* frontend = MakeMockFrontend();
1322     AppCacheHost* host = MakeHost(1, frontend);
1323     host->AssociateCompleteCache(cache);
1324
1325     // Give the newest cache an entry that is in storage.
1326     response_writer_.reset(
1327         service_->storage()->CreateResponseWriter(group_->manifest_url(),
1328                                                   group_->group_id()));
1329     cache->AddEntry(MockHttpServer::GetMockUrl("files/explicit1"),
1330                     AppCacheEntry(AppCacheEntry::EXPLICIT,
1331                                   response_writer_->response_id()));
1332
1333     // Set up checks for when update job finishes.
1334     do_checks_after_update_finished_ = true;
1335     expect_group_obsolete_ = false;
1336     expect_group_has_cache_ = true;
1337     expect_old_cache_ = cache;
1338     tested_manifest_ = MANIFEST1;
1339     MockFrontend::HostIds ids(1, host->host_id());
1340     frontend->AddExpectedEvent(ids, APPCACHE_CHECKING_EVENT);
1341     frontend->AddExpectedEvent(ids, APPCACHE_DOWNLOADING_EVENT);
1342     frontend->AddExpectedEvent(ids, APPCACHE_PROGRESS_EVENT);
1343     frontend->AddExpectedEvent(ids, APPCACHE_PROGRESS_EVENT);
1344     frontend->AddExpectedEvent(ids, APPCACHE_PROGRESS_EVENT);  // final
1345     frontend->AddExpectedEvent(ids, APPCACHE_UPDATE_READY_EVENT);
1346
1347     // Seed storage with expected http response info for entry: a vary header.
1348     const char data[] =
1349         "HTTP/1.1 200 OK\0"
1350         "Cache-Control: max-age=8675309\0"
1351         "Vary: blah\0"
1352         "\0";
1353     net::HttpResponseHeaders* headers =
1354         new net::HttpResponseHeaders(std::string(data, arraysize(data)));
1355     net::HttpResponseInfo* response_info = new net::HttpResponseInfo();
1356     response_info->request_time = base::Time::Now();
1357     response_info->response_time = base::Time::Now();
1358     response_info->headers = headers;  // adds ref to headers
1359     scoped_refptr<HttpResponseInfoIOBuffer> io_buffer(
1360         new HttpResponseInfoIOBuffer(response_info));  // adds ref to info
1361     response_writer_->WriteInfo(
1362         io_buffer.get(),
1363         base::Bind(&AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData,
1364                    base::Unretained(this)));
1365
1366     // Start update after data write completes asynchronously.
1367   }
1368
1369   void UpgradeSuccessMergedTypesTest() {
1370     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
1371
1372     MakeService();
1373     group_ = new AppCacheGroup(service_->storage(),
1374         MockHttpServer::GetMockUrl("files/manifest-merged-types"),
1375         service_->storage()->NewGroupId());
1376     AppCacheUpdateJob* update =
1377         new AppCacheUpdateJob(service_.get(), group_.get());
1378     group_->update_job_ = update;
1379
1380     AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 42);
1381     MockFrontend* frontend1 = MakeMockFrontend();
1382     MockFrontend* frontend2 = MakeMockFrontend();
1383     AppCacheHost* host1 = MakeHost(1, frontend1);
1384     AppCacheHost* host2 = MakeHost(2, frontend2);
1385     host1->AssociateCompleteCache(cache);
1386     host2->AssociateCompleteCache(cache);
1387
1388     // Give the newest cache a master entry that is also one of the explicit
1389     // entries in the manifest.
1390     cache->AddEntry(MockHttpServer::GetMockUrl("files/explicit1"),
1391                     AppCacheEntry(AppCacheEntry::MASTER, 111));
1392
1393     update->StartUpdate(NULL, GURL());
1394     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
1395
1396     // Set up checks for when update job finishes.
1397     do_checks_after_update_finished_ = true;
1398     expect_group_obsolete_ = false;
1399     expect_group_has_cache_ = true;
1400     expect_old_cache_ = cache;
1401     tested_manifest_ = MANIFEST_MERGED_TYPES;
1402     MockFrontend::HostIds ids1(1, host1->host_id());
1403     frontend1->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
1404     frontend1->AddExpectedEvent(ids1, APPCACHE_DOWNLOADING_EVENT);
1405     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // explicit1
1406     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // manifest
1407     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // final
1408     frontend1->AddExpectedEvent(ids1, APPCACHE_UPDATE_READY_EVENT);
1409     MockFrontend::HostIds ids2(1, host2->host_id());
1410     frontend2->AddExpectedEvent(ids2, APPCACHE_CHECKING_EVENT);
1411     frontend2->AddExpectedEvent(ids2, APPCACHE_DOWNLOADING_EVENT);
1412     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);
1413     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);
1414     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);  // final
1415     frontend2->AddExpectedEvent(ids2, APPCACHE_UPDATE_READY_EVENT);
1416
1417     WaitForUpdateToFinish();
1418   }
1419
1420   void CacheAttemptFailUrlFetchTest() {
1421     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
1422
1423     MakeService();
1424     group_ = new AppCacheGroup(service_->storage(),
1425         MockHttpServer::GetMockUrl("files/manifest-with-404"),
1426         service_->storage()->NewGroupId());
1427     AppCacheUpdateJob* update =
1428         new AppCacheUpdateJob(service_.get(), group_.get());
1429     group_->update_job_ = update;
1430
1431     MockFrontend* frontend = MakeMockFrontend();
1432     AppCacheHost* host = MakeHost(1, frontend);
1433     update->StartUpdate(host, GURL());
1434     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
1435
1436     // Set up checks for when update job finishes.
1437     do_checks_after_update_finished_ = true;
1438     expect_group_obsolete_ = false;
1439     expect_group_has_cache_ = false;  // 404 explicit url is cache failure
1440     frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()),
1441                                APPCACHE_CHECKING_EVENT);
1442
1443     WaitForUpdateToFinish();
1444   }
1445
1446   void UpgradeFailUrlFetchTest() {
1447     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
1448
1449     MakeService();
1450     group_ = new AppCacheGroup(service_->storage(),
1451         MockHttpServer::GetMockUrl("files/manifest-fb-404"),
1452         service_->storage()->NewGroupId());
1453     AppCacheUpdateJob* update =
1454         new AppCacheUpdateJob(service_.get(), group_.get());
1455     group_->update_job_ = update;
1456
1457     AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 99);
1458     MockFrontend* frontend1 = MakeMockFrontend();
1459     MockFrontend* frontend2 = MakeMockFrontend();
1460     frontend1->SetIgnoreProgressEvents(true);
1461     frontend2->SetIgnoreProgressEvents(true);
1462     AppCacheHost* host1 = MakeHost(1, frontend1);
1463     AppCacheHost* host2 = MakeHost(2, frontend2);
1464     host1->AssociateCompleteCache(cache);
1465     host2->AssociateCompleteCache(cache);
1466
1467     update->StartUpdate(NULL, GURL());
1468     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
1469
1470     // Set up checks for when update job finishes.
1471     do_checks_after_update_finished_ = true;
1472     expect_group_obsolete_ = false;
1473     expect_group_has_cache_ = true;
1474     expect_newest_cache_ = cache;  // newest cache unaffectd by failed update
1475     MockFrontend::HostIds ids1(1, host1->host_id());
1476     frontend1->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
1477     frontend1->AddExpectedEvent(ids1, APPCACHE_DOWNLOADING_EVENT);
1478     frontend1->AddExpectedEvent(ids1, APPCACHE_ERROR_EVENT);
1479     MockFrontend::HostIds ids2(1, host2->host_id());
1480     frontend2->AddExpectedEvent(ids2, APPCACHE_CHECKING_EVENT);
1481     frontend2->AddExpectedEvent(ids2, APPCACHE_DOWNLOADING_EVENT);
1482     frontend2->AddExpectedEvent(ids2, APPCACHE_ERROR_EVENT);
1483
1484     WaitForUpdateToFinish();
1485   }
1486
1487   void UpgradeFailMasterUrlFetchTest() {
1488     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
1489
1490     tested_manifest_path_override_ = "files/manifest1-with-notmodified";
1491
1492     MakeService();
1493     const GURL kManifestUrl =
1494         MockHttpServer::GetMockUrl(tested_manifest_path_override_);
1495     group_ = new AppCacheGroup(
1496         service_->storage(), kManifestUrl,
1497         service_->storage()->NewGroupId());
1498     AppCacheUpdateJob* update =
1499         new AppCacheUpdateJob(service_.get(), group_.get());
1500     group_->update_job_ = update;
1501
1502     AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 25);
1503     MockFrontend* frontend1 = MakeMockFrontend();
1504     MockFrontend* frontend2 = MakeMockFrontend();
1505     AppCacheHost* host1 = MakeHost(1, frontend1);
1506     AppCacheHost* host2 = MakeHost(2, frontend2);
1507     host1->AssociateCompleteCache(cache);
1508     host2->AssociateCompleteCache(cache);
1509
1510     // Give the newest cache some existing entries; one will fail with a 404.
1511     cache->AddEntry(
1512         MockHttpServer::GetMockUrl("files/notfound"),
1513         AppCacheEntry(AppCacheEntry::MASTER, 222));
1514     cache->AddEntry(
1515         MockHttpServer::GetMockUrl("files/explicit2"),
1516         AppCacheEntry(AppCacheEntry::MASTER | AppCacheEntry::FOREIGN, 333));
1517     cache->AddEntry(
1518         MockHttpServer::GetMockUrl("files/servererror"),
1519         AppCacheEntry(AppCacheEntry::MASTER, 444));
1520     cache->AddEntry(
1521         MockHttpServer::GetMockUrl("files/notmodified"),
1522         AppCacheEntry(AppCacheEntry::EXPLICIT, 555));
1523
1524     // Seed the response_info working set with canned data for
1525     // files/servererror and for files/notmodified to test that the
1526     // existing entries for those resource are reused by the update job.
1527     const char kData[] =
1528         "HTTP/1.1 200 OK\0"
1529         "Last-Modified: Sat, 29 Oct 1994 19:43:31 GMT\0"
1530         "\0";
1531     const std::string kRawHeaders(kData, arraysize(kData));
1532     MakeAppCacheResponseInfo(kManifestUrl, 444, kRawHeaders);
1533     MakeAppCacheResponseInfo(kManifestUrl, 555, kRawHeaders);
1534
1535     update->StartUpdate(NULL, GURL());
1536     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
1537
1538     // Set up checks for when update job finishes.
1539     do_checks_after_update_finished_ = true;
1540     expect_group_obsolete_ = false;
1541     expect_group_has_cache_ = true;
1542     expect_old_cache_ = cache;
1543     tested_manifest_ = MANIFEST1;
1544     expect_extra_entries_.insert(AppCache::EntryMap::value_type(
1545         MockHttpServer::GetMockUrl("files/explicit2"),
1546         AppCacheEntry(AppCacheEntry::MASTER)));  // foreign flag is dropped
1547     expect_extra_entries_.insert(AppCache::EntryMap::value_type(
1548         MockHttpServer::GetMockUrl("files/servererror"),
1549         AppCacheEntry(AppCacheEntry::MASTER)));
1550     expect_extra_entries_.insert(AppCache::EntryMap::value_type(
1551         MockHttpServer::GetMockUrl("files/notmodified"),
1552         AppCacheEntry(AppCacheEntry::EXPLICIT)));
1553     expect_response_ids_.insert(std::map<GURL, int64>::value_type(
1554         MockHttpServer::GetMockUrl("files/servererror"), 444));  // copied
1555     expect_response_ids_.insert(std::map<GURL, int64>::value_type(
1556         MockHttpServer::GetMockUrl("files/notmodified"), 555));  // copied
1557     MockFrontend::HostIds ids1(1, host1->host_id());
1558     frontend1->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
1559     frontend1->AddExpectedEvent(ids1, APPCACHE_DOWNLOADING_EVENT);
1560     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // explicit1
1561     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // fallback1a
1562     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // notfound
1563     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // explicit2
1564     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // servererror
1565     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // notmodified
1566     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // final
1567     frontend1->AddExpectedEvent(ids1, APPCACHE_UPDATE_READY_EVENT);
1568     MockFrontend::HostIds ids2(1, host2->host_id());
1569     frontend2->AddExpectedEvent(ids2, APPCACHE_CHECKING_EVENT);
1570     frontend2->AddExpectedEvent(ids2, APPCACHE_DOWNLOADING_EVENT);
1571     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);  // explicit1
1572     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);  // fallback1a
1573     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);  // notfound
1574     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);  // explicit2
1575     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);  // servererror
1576     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);  // notmodified
1577     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);  // final
1578     frontend2->AddExpectedEvent(ids2, APPCACHE_UPDATE_READY_EVENT);
1579
1580     WaitForUpdateToFinish();
1581   }
1582
1583   void EmptyManifestTest() {
1584     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
1585
1586     MakeService();
1587     group_ = new AppCacheGroup(
1588         service_->storage(), MockHttpServer::GetMockUrl("files/empty-manifest"),
1589         service_->storage()->NewGroupId());
1590     AppCacheUpdateJob* update =
1591         new AppCacheUpdateJob(service_.get(), group_.get());
1592     group_->update_job_ = update;
1593
1594     AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 33);
1595     MockFrontend* frontend1 = MakeMockFrontend();
1596     MockFrontend* frontend2 = MakeMockFrontend();
1597     AppCacheHost* host1 = MakeHost(1, frontend1);
1598     AppCacheHost* host2 = MakeHost(2, frontend2);
1599     host1->AssociateCompleteCache(cache);
1600     host2->AssociateCompleteCache(cache);
1601
1602     frontend1->SetVerifyProgressEvents(true);
1603
1604     update->StartUpdate(NULL, GURL());
1605     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
1606
1607     // Set up checks for when update job finishes.
1608     do_checks_after_update_finished_ = true;
1609     expect_group_obsolete_ = false;
1610     expect_group_has_cache_ = true;
1611     expect_old_cache_ = cache;
1612     tested_manifest_ = EMPTY_MANIFEST;
1613     MockFrontend::HostIds ids1(1, host1->host_id());
1614     frontend1->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
1615     frontend1->AddExpectedEvent(ids1, APPCACHE_DOWNLOADING_EVENT);
1616     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // final
1617     frontend1->AddExpectedEvent(ids1, APPCACHE_UPDATE_READY_EVENT);
1618     MockFrontend::HostIds ids2(1, host2->host_id());
1619     frontend2->AddExpectedEvent(ids2, APPCACHE_CHECKING_EVENT);
1620     frontend2->AddExpectedEvent(ids2, APPCACHE_DOWNLOADING_EVENT);
1621     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);  // final
1622     frontend2->AddExpectedEvent(ids2, APPCACHE_UPDATE_READY_EVENT);
1623
1624     WaitForUpdateToFinish();
1625   }
1626
1627   void EmptyFileTest() {
1628     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
1629
1630     MakeService();
1631     group_ = new AppCacheGroup(service_->storage(),
1632         MockHttpServer::GetMockUrl("files/empty-file-manifest"),
1633         service_->storage()->NewGroupId());
1634     AppCacheUpdateJob* update =
1635         new AppCacheUpdateJob(service_.get(), group_.get());
1636     group_->update_job_ = update;
1637
1638     AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 22);
1639     MockFrontend* frontend = MakeMockFrontend();
1640     AppCacheHost* host = MakeHost(1, frontend);
1641     host->AssociateCompleteCache(cache);
1642     frontend->SetVerifyProgressEvents(true);
1643
1644     update->StartUpdate(host, GURL());
1645     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
1646
1647     // Set up checks for when update job finishes.
1648     do_checks_after_update_finished_ = true;
1649     expect_group_obsolete_ = false;
1650     expect_group_has_cache_ = true;
1651     tested_manifest_ = EMPTY_FILE_MANIFEST;
1652     MockFrontend::HostIds ids1(1, host->host_id());
1653     frontend->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
1654     frontend->AddExpectedEvent(ids1, APPCACHE_DOWNLOADING_EVENT);
1655     frontend->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);
1656     frontend->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // final
1657     frontend->AddExpectedEvent(ids1, APPCACHE_UPDATE_READY_EVENT);
1658
1659     WaitForUpdateToFinish();
1660   }
1661
1662   void RetryRequestTest() {
1663     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
1664
1665     // Set some large number of times to return retry.
1666     // Expect 1 manifest fetch and 3 retries.
1667     RetryRequestTestJob::Initialize(5, RetryRequestTestJob::RETRY_AFTER_0, 4);
1668     net::URLRequestJobFactoryImpl* new_factory(
1669         new net::URLRequestJobFactoryImpl);
1670     new_factory->SetProtocolHandler("http", new RetryRequestTestJobFactory);
1671     io_thread_->SetNewJobFactory(new_factory);
1672
1673     MakeService();
1674     group_ = new AppCacheGroup(service_->storage(),
1675                                RetryRequestTestJob::kRetryUrl,
1676                                service_->storage()->NewGroupId());
1677     AppCacheUpdateJob* update =
1678         new AppCacheUpdateJob(service_.get(), group_.get());
1679     group_->update_job_ = update;
1680
1681     MockFrontend* frontend = MakeMockFrontend();
1682     AppCacheHost* host = MakeHost(1, frontend);
1683     update->StartUpdate(host, GURL());
1684     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
1685
1686     // Set up checks for when update job finishes.
1687     do_checks_after_update_finished_ = true;
1688     expect_group_obsolete_ = false;
1689     expect_group_has_cache_ = false;
1690     frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()),
1691                                APPCACHE_CHECKING_EVENT);
1692
1693     WaitForUpdateToFinish();
1694   }
1695
1696   void RetryNoRetryAfterTest() {
1697     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
1698
1699     // Set some large number of times to return retry.
1700     // Expect 1 manifest fetch and 0 retries.
1701     RetryRequestTestJob::Initialize(5, RetryRequestTestJob::NO_RETRY_AFTER, 1);
1702     net::URLRequestJobFactoryImpl* new_factory(
1703         new net::URLRequestJobFactoryImpl);
1704     new_factory->SetProtocolHandler("http", new RetryRequestTestJobFactory);
1705     io_thread_->SetNewJobFactory(new_factory);
1706
1707     MakeService();
1708     group_ = new AppCacheGroup(service_->storage(),
1709                                RetryRequestTestJob::kRetryUrl,
1710                                service_->storage()->NewGroupId());
1711     AppCacheUpdateJob* update =
1712         new AppCacheUpdateJob(service_.get(), group_.get());
1713     group_->update_job_ = update;
1714
1715     MockFrontend* frontend = MakeMockFrontend();
1716     AppCacheHost* host = MakeHost(1, frontend);
1717     update->StartUpdate(host, GURL());
1718     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
1719
1720     // Set up checks for when update job finishes.
1721     do_checks_after_update_finished_ = true;
1722     expect_group_obsolete_ = false;
1723     expect_group_has_cache_ = false;
1724     frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()),
1725                                APPCACHE_CHECKING_EVENT);
1726
1727     WaitForUpdateToFinish();
1728   }
1729
1730   void RetryNonzeroRetryAfterTest() {
1731     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
1732
1733     // Set some large number of times to return retry.
1734     // Expect 1 request and 0 retry attempts.
1735     RetryRequestTestJob::Initialize(
1736         5, RetryRequestTestJob::NONZERO_RETRY_AFTER, 1);
1737     net::URLRequestJobFactoryImpl* new_factory(
1738         new net::URLRequestJobFactoryImpl);
1739     new_factory->SetProtocolHandler("http", new RetryRequestTestJobFactory);
1740     io_thread_->SetNewJobFactory(new_factory);
1741
1742     MakeService();
1743     group_ = new AppCacheGroup(service_->storage(),
1744                                RetryRequestTestJob::kRetryUrl,
1745                                service_->storage()->NewGroupId());
1746     AppCacheUpdateJob* update =
1747         new AppCacheUpdateJob(service_.get(), group_.get());
1748     group_->update_job_ = update;
1749
1750     MockFrontend* frontend = MakeMockFrontend();
1751     AppCacheHost* host = MakeHost(1, frontend);
1752     update->StartUpdate(host, GURL());
1753     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
1754
1755     // Set up checks for when update job finishes.
1756     do_checks_after_update_finished_ = true;
1757     expect_group_obsolete_ = false;
1758     expect_group_has_cache_ = false;
1759     frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()),
1760                                APPCACHE_CHECKING_EVENT);
1761
1762     WaitForUpdateToFinish();
1763   }
1764
1765   void RetrySuccessTest() {
1766     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
1767
1768     // Set 2 as the retry limit (does not exceed the max).
1769     // Expect 1 manifest fetch, 2 retries, 1 url fetch, 1 manifest refetch.
1770     RetryRequestTestJob::Initialize(2, RetryRequestTestJob::RETRY_AFTER_0, 5);
1771     net::URLRequestJobFactoryImpl* new_factory(
1772         new net::URLRequestJobFactoryImpl);
1773     new_factory->SetProtocolHandler("http", new RetryRequestTestJobFactory);
1774     io_thread_->SetNewJobFactory(new_factory);
1775
1776     MakeService();
1777     group_ = new AppCacheGroup(service_->storage(),
1778                                RetryRequestTestJob::kRetryUrl,
1779                                service_->storage()->NewGroupId());
1780     AppCacheUpdateJob* update =
1781         new AppCacheUpdateJob(service_.get(), group_.get());
1782     group_->update_job_ = update;
1783
1784     MockFrontend* frontend = MakeMockFrontend();
1785     AppCacheHost* host = MakeHost(1, frontend);
1786     update->StartUpdate(host, GURL());
1787     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
1788
1789     // Set up checks for when update job finishes.
1790     do_checks_after_update_finished_ = true;
1791     expect_group_obsolete_ = false;
1792     expect_group_has_cache_ = true;
1793     frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()),
1794                                APPCACHE_CHECKING_EVENT);
1795
1796     WaitForUpdateToFinish();
1797   }
1798
1799   void RetryUrlTest() {
1800     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
1801
1802     // Set 1 as the retry limit (does not exceed the max).
1803     // Expect 1 manifest fetch, 1 url fetch, 1 url retry, 1 manifest refetch.
1804     RetryRequestTestJob::Initialize(1, RetryRequestTestJob::RETRY_AFTER_0, 4);
1805     net::URLRequestJobFactoryImpl* new_factory(
1806         new net::URLRequestJobFactoryImpl);
1807     new_factory->SetProtocolHandler("http", new RetryRequestTestJobFactory);
1808     io_thread_->SetNewJobFactory(new_factory);
1809
1810     MakeService();
1811     group_ = new AppCacheGroup(service_->storage(), GURL("http://retryurl"),
1812                                service_->storage()->NewGroupId());
1813     AppCacheUpdateJob* update =
1814         new AppCacheUpdateJob(service_.get(), group_.get());
1815     group_->update_job_ = update;
1816
1817     MockFrontend* frontend = MakeMockFrontend();
1818     AppCacheHost* host = MakeHost(1, frontend);
1819     update->StartUpdate(host, GURL());
1820     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
1821
1822     // Set up checks for when update job finishes.
1823     do_checks_after_update_finished_ = true;
1824     expect_group_obsolete_ = false;
1825     expect_group_has_cache_ = true;
1826     frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()),
1827                                APPCACHE_CHECKING_EVENT);
1828
1829     WaitForUpdateToFinish();
1830   }
1831
1832   void FailStoreNewestCacheTest() {
1833     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
1834
1835     MakeService();
1836     MockAppCacheStorage* storage =
1837         reinterpret_cast<MockAppCacheStorage*>(service_->storage());
1838     storage->SimulateStoreGroupAndNewestCacheFailure();
1839
1840     group_ = new AppCacheGroup(
1841         service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"),
1842         service_->storage()->NewGroupId());
1843     AppCacheUpdateJob* update =
1844         new AppCacheUpdateJob(service_.get(), group_.get());
1845     group_->update_job_ = update;
1846
1847     MockFrontend* frontend = MakeMockFrontend();
1848     AppCacheHost* host = MakeHost(1, frontend);
1849     update->StartUpdate(host, GURL());
1850
1851     // Set up checks for when update job finishes.
1852     do_checks_after_update_finished_ = true;
1853     expect_group_obsolete_ = false;
1854     expect_group_has_cache_ = false;  // storage failed
1855     frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()),
1856                                APPCACHE_CHECKING_EVENT);
1857
1858     WaitForUpdateToFinish();
1859   }
1860
1861   void UpgradeFailStoreNewestCacheTest() {
1862     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
1863
1864     MakeService();
1865     MockAppCacheStorage* storage =
1866         reinterpret_cast<MockAppCacheStorage*>(service_->storage());
1867     storage->SimulateStoreGroupAndNewestCacheFailure();
1868
1869     group_ = new AppCacheGroup(
1870         service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"),
1871         service_->storage()->NewGroupId());
1872     AppCacheUpdateJob* update =
1873         new AppCacheUpdateJob(service_.get(), group_.get());
1874     group_->update_job_ = update;
1875
1876     AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 11);
1877     MockFrontend* frontend1 = MakeMockFrontend();
1878     MockFrontend* frontend2 = MakeMockFrontend();
1879     AppCacheHost* host1 = MakeHost(1, frontend1);
1880     AppCacheHost* host2 = MakeHost(2, frontend2);
1881     host1->AssociateCompleteCache(cache);
1882     host2->AssociateCompleteCache(cache);
1883
1884     update->StartUpdate(NULL, GURL());
1885
1886     // Set up checks for when update job finishes.
1887     do_checks_after_update_finished_ = true;
1888     expect_group_obsolete_ = false;
1889     expect_group_has_cache_ = true;
1890     expect_newest_cache_ = cache;  // unchanged
1891     MockFrontend::HostIds ids1(1, host1->host_id());
1892     frontend1->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
1893     frontend1->AddExpectedEvent(ids1, APPCACHE_DOWNLOADING_EVENT);
1894     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);
1895     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);
1896     frontend1->AddExpectedEvent(ids1, APPCACHE_ERROR_EVENT);
1897     MockFrontend::HostIds ids2(1, host2->host_id());
1898     frontend2->AddExpectedEvent(ids2, APPCACHE_CHECKING_EVENT);
1899     frontend2->AddExpectedEvent(ids2, APPCACHE_DOWNLOADING_EVENT);
1900     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);
1901     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);
1902     frontend2->AddExpectedEvent(ids2, APPCACHE_ERROR_EVENT);
1903
1904     WaitForUpdateToFinish();
1905   }
1906
1907   void MasterEntryFailStoreNewestCacheTest() {
1908     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
1909
1910     MakeService();
1911     MockAppCacheStorage* storage =
1912         reinterpret_cast<MockAppCacheStorage*>(service_->storage());
1913     storage->SimulateStoreGroupAndNewestCacheFailure();
1914
1915     const GURL kManifestUrl = MockHttpServer::GetMockUrl("files/notmodified");
1916     const int64 kManifestResponseId = 11;
1917
1918     // Seed the response_info working set with canned data for
1919     // files/servererror and for files/notmodified to test that the
1920     // existing entries for those resource are reused by the update job.
1921     const char kData[] =
1922         "HTTP/1.1 200 OK\0"
1923         "Content-type: text/cache-manifest\0"
1924         "Last-Modified: Sat, 29 Oct 1994 19:43:31 GMT\0"
1925         "\0";
1926     const std::string kRawHeaders(kData, arraysize(kData));
1927     MakeAppCacheResponseInfo(kManifestUrl, kManifestResponseId, kRawHeaders);
1928
1929     group_ = new AppCacheGroup(
1930         service_->storage(), kManifestUrl,
1931         service_->storage()->NewGroupId());
1932     scoped_refptr<AppCache> cache(
1933         MakeCacheForGroup(service_->storage()->NewCacheId(),
1934                           kManifestResponseId));
1935
1936     MockFrontend* frontend = MakeMockFrontend();
1937     AppCacheHost* host = MakeHost(1, frontend);
1938     host->first_party_url_ = kManifestUrl;
1939     host->SelectCache(MockHttpServer::GetMockUrl("files/empty1"),
1940                       kAppCacheNoCacheId, kManifestUrl);
1941
1942     // Set up checks for when update job finishes.
1943     do_checks_after_update_finished_ = true;
1944     tested_manifest_ = EMPTY_MANIFEST;
1945     tested_manifest_path_override_ = "files/notmodified";
1946     expect_group_obsolete_ = false;
1947     expect_group_has_cache_ = true;
1948     expect_newest_cache_ = cache.get();  // unchanged
1949     MockFrontend::HostIds ids1(1, host->host_id());
1950     frontend->AddExpectedEvent(ids1, APPCACHE_ERROR_EVENT);
1951     frontend->expected_error_message_ =
1952         "Failed to commit new cache to storage";
1953
1954     WaitForUpdateToFinish();
1955   }
1956
1957   void UpgradeFailMakeGroupObsoleteTest() {
1958     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
1959
1960     MakeService();
1961     MockAppCacheStorage* storage =
1962         reinterpret_cast<MockAppCacheStorage*>(service_->storage());
1963     storage->SimulateMakeGroupObsoleteFailure();
1964
1965     group_ = new AppCacheGroup(
1966         service_->storage(), MockHttpServer::GetMockUrl("files/nosuchfile"),
1967         service_->storage()->NewGroupId());
1968     AppCacheUpdateJob* update =
1969         new AppCacheUpdateJob(service_.get(), group_.get());
1970     group_->update_job_ = update;
1971
1972     AppCache* cache = MakeCacheForGroup(1, 111);
1973     MockFrontend* frontend1 = MakeMockFrontend();
1974     MockFrontend* frontend2 = MakeMockFrontend();
1975     AppCacheHost* host1 = MakeHost(1, frontend1);
1976     AppCacheHost* host2 = MakeHost(2, frontend2);
1977     host1->AssociateCompleteCache(cache);
1978     host2->AssociateCompleteCache(cache);
1979
1980     update->StartUpdate(NULL, GURL());
1981     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
1982
1983     // Set up checks for when update job finishes.
1984     do_checks_after_update_finished_ = true;
1985     expect_group_obsolete_ = false;
1986     expect_group_has_cache_ = true;
1987     expect_newest_cache_ = cache;  // newest cache unaffected by update
1988     MockFrontend::HostIds ids1(1, host1->host_id());
1989     frontend1->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
1990     frontend1->AddExpectedEvent(ids1, APPCACHE_ERROR_EVENT);
1991     MockFrontend::HostIds ids2(1, host2->host_id());
1992     frontend2->AddExpectedEvent(ids2, APPCACHE_CHECKING_EVENT);
1993     frontend2->AddExpectedEvent(ids2, APPCACHE_ERROR_EVENT);
1994
1995     WaitForUpdateToFinish();
1996   }
1997
1998   void MasterEntryFetchManifestFailTest() {
1999     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
2000
2001     MakeService();
2002     group_ = new AppCacheGroup(service_->storage(), GURL("http://failme"), 111);
2003     AppCacheUpdateJob* update =
2004         new AppCacheUpdateJob(service_.get(), group_.get());
2005     group_->update_job_ = update;
2006
2007     MockFrontend* frontend = MakeMockFrontend();
2008     AppCacheHost* host = MakeHost(1, frontend);
2009     host->new_master_entry_url_ = GURL("http://failme/blah");
2010     update->StartUpdate(host, host->new_master_entry_url_);
2011     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
2012
2013     update->manifest_fetcher_->request()->CancelWithError(-100);
2014
2015     // Set up checks for when update job finishes.
2016     do_checks_after_update_finished_ = true;
2017     expect_group_obsolete_ = false;
2018     expect_group_has_cache_ = false;
2019     MockFrontend::HostIds ids1(1, host->host_id());
2020     frontend->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
2021     frontend->AddExpectedEvent(ids1, APPCACHE_ERROR_EVENT);
2022
2023     WaitForUpdateToFinish();
2024   }
2025
2026   void MasterEntryBadManifestTest() {
2027     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
2028
2029     MakeService();
2030     group_ = new AppCacheGroup(service_->storage(),
2031         MockHttpServer::GetMockUrl("files/bad-manifest"), 111);
2032     AppCacheUpdateJob* update =
2033         new AppCacheUpdateJob(service_.get(), group_.get());
2034     group_->update_job_ = update;
2035
2036     MockFrontend* frontend = MakeMockFrontend();
2037     AppCacheHost* host = MakeHost(1, frontend);
2038     host->new_master_entry_url_ = MockHttpServer::GetMockUrl("files/blah");
2039     update->StartUpdate(host, host->new_master_entry_url_);
2040     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
2041
2042     // Set up checks for when update job finishes.
2043     do_checks_after_update_finished_ = true;
2044     expect_group_obsolete_ = false;
2045     expect_group_has_cache_ = false;
2046     MockFrontend::HostIds ids1(1, host->host_id());
2047     frontend->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
2048     frontend->AddExpectedEvent(ids1, APPCACHE_ERROR_EVENT);
2049
2050     WaitForUpdateToFinish();
2051   }
2052
2053   void MasterEntryManifestNotFoundTest() {
2054     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
2055
2056     MakeService();
2057     group_ = new AppCacheGroup(
2058         service_->storage(),
2059         MockHttpServer::GetMockUrl("files/nosuchfile"),
2060         111);
2061     AppCacheUpdateJob* update =
2062         new AppCacheUpdateJob(service_.get(), group_.get());
2063     group_->update_job_ = update;
2064
2065     MockFrontend* frontend = MakeMockFrontend();
2066     AppCacheHost* host = MakeHost(1, frontend);
2067     host->new_master_entry_url_ = MockHttpServer::GetMockUrl("files/blah");
2068
2069     update->StartUpdate(host, host->new_master_entry_url_);
2070     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
2071
2072     // Set up checks for when update job finishes.
2073     do_checks_after_update_finished_ = true;
2074     expect_group_obsolete_ = false;
2075     expect_group_has_cache_ = false;
2076     MockFrontend::HostIds ids1(1, host->host_id());
2077     frontend->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
2078     frontend->AddExpectedEvent(ids1, APPCACHE_ERROR_EVENT);
2079
2080     WaitForUpdateToFinish();
2081   }
2082
2083   void MasterEntryFailUrlFetchTest() {
2084     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
2085
2086     MakeService();
2087     group_ = new AppCacheGroup(service_->storage(),
2088         MockHttpServer::GetMockUrl("files/manifest-fb-404"), 111);
2089     AppCacheUpdateJob* update =
2090         new AppCacheUpdateJob(service_.get(), group_.get());
2091     group_->update_job_ = update;
2092
2093     MockFrontend* frontend = MakeMockFrontend();
2094     frontend->SetIgnoreProgressEvents(true);
2095     AppCacheHost* host = MakeHost(1, frontend);
2096     host->new_master_entry_url_ =
2097         MockHttpServer::GetMockUrl("files/explicit1");
2098
2099     update->StartUpdate(host, host->new_master_entry_url_);
2100     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
2101
2102     // Set up checks for when update job finishes.
2103     do_checks_after_update_finished_ = true;
2104     expect_group_obsolete_ = false;
2105     expect_group_has_cache_ = false;  // 404 fallback url is cache failure
2106     MockFrontend::HostIds ids1(1, host->host_id());
2107     frontend->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
2108     frontend->AddExpectedEvent(ids1, APPCACHE_DOWNLOADING_EVENT);
2109     frontend->AddExpectedEvent(ids1, APPCACHE_ERROR_EVENT);
2110
2111     WaitForUpdateToFinish();
2112   }
2113
2114   void MasterEntryAllFailTest() {
2115     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
2116
2117     MakeService();
2118     group_ = new AppCacheGroup(
2119         service_->storage(),
2120         MockHttpServer::GetMockUrl("files/manifest1"),
2121         111);
2122     AppCacheUpdateJob* update =
2123         new AppCacheUpdateJob(service_.get(), group_.get());
2124     group_->update_job_ = update;
2125
2126     MockFrontend* frontend1 = MakeMockFrontend();
2127     frontend1->SetIgnoreProgressEvents(true);
2128     AppCacheHost* host1 = MakeHost(1, frontend1);
2129     host1->new_master_entry_url_ =
2130         MockHttpServer::GetMockUrl("files/nosuchfile");
2131     update->StartUpdate(host1, host1->new_master_entry_url_);
2132
2133     MockFrontend* frontend2 = MakeMockFrontend();
2134     frontend2->SetIgnoreProgressEvents(true);
2135     AppCacheHost* host2 = MakeHost(2, frontend2);
2136     host2->new_master_entry_url_ =
2137         MockHttpServer::GetMockUrl("files/servererror");
2138     update->StartUpdate(host2, host2->new_master_entry_url_);
2139
2140     // Set up checks for when update job finishes.
2141     do_checks_after_update_finished_ = true;
2142     expect_group_obsolete_ = false;
2143     expect_group_has_cache_ = false;  // all pending masters failed
2144     MockFrontend::HostIds ids1(1, host1->host_id());
2145     frontend1->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
2146     frontend1->AddExpectedEvent(ids1, APPCACHE_DOWNLOADING_EVENT);
2147     frontend1->AddExpectedEvent(ids1, APPCACHE_ERROR_EVENT);
2148     MockFrontend::HostIds ids2(1, host2->host_id());
2149     frontend2->AddExpectedEvent(ids2, APPCACHE_CHECKING_EVENT);
2150     frontend2->AddExpectedEvent(ids2, APPCACHE_DOWNLOADING_EVENT);
2151     frontend2->AddExpectedEvent(ids2, APPCACHE_ERROR_EVENT);
2152
2153     WaitForUpdateToFinish();
2154   }
2155
2156   void UpgradeMasterEntryAllFailTest() {
2157     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
2158
2159     MakeService();
2160     group_ = new AppCacheGroup(
2161         service_->storage(),
2162         MockHttpServer::GetMockUrl("files/manifest1"),
2163         111);
2164     AppCacheUpdateJob* update =
2165         new AppCacheUpdateJob(service_.get(), group_.get());
2166     group_->update_job_ = update;
2167
2168     AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 42);
2169     MockFrontend* frontend1 = MakeMockFrontend();
2170     AppCacheHost* host1 = MakeHost(1, frontend1);
2171     host1->AssociateCompleteCache(cache);
2172
2173     MockFrontend* frontend2 = MakeMockFrontend();
2174     frontend2->SetIgnoreProgressEvents(true);
2175     AppCacheHost* host2 = MakeHost(2, frontend2);
2176     host2->new_master_entry_url_ =
2177         MockHttpServer::GetMockUrl("files/nosuchfile");
2178     update->StartUpdate(host2, host2->new_master_entry_url_);
2179
2180     MockFrontend* frontend3 = MakeMockFrontend();
2181     frontend3->SetIgnoreProgressEvents(true);
2182     AppCacheHost* host3 = MakeHost(3, frontend3);
2183     host3->new_master_entry_url_ =
2184         MockHttpServer::GetMockUrl("files/servererror");
2185     update->StartUpdate(host3, host3->new_master_entry_url_);
2186
2187     // Set up checks for when update job finishes.
2188     do_checks_after_update_finished_ = true;
2189     expect_group_obsolete_ = false;
2190     expect_group_has_cache_ = true;
2191     expect_old_cache_ = cache;
2192     tested_manifest_ = MANIFEST1;
2193     MockFrontend::HostIds ids1(1, host1->host_id());
2194     frontend1->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
2195     frontend1->AddExpectedEvent(ids1, APPCACHE_DOWNLOADING_EVENT);
2196     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);
2197     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);
2198     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // final
2199     frontend1->AddExpectedEvent(ids1, APPCACHE_UPDATE_READY_EVENT);
2200     MockFrontend::HostIds ids2(1, host2->host_id());
2201     frontend2->AddExpectedEvent(ids2, APPCACHE_DOWNLOADING_EVENT);
2202     frontend2->AddExpectedEvent(ids2, APPCACHE_ERROR_EVENT);
2203     MockFrontend::HostIds ids3(1, host3->host_id());
2204     frontend3->AddExpectedEvent(ids3, APPCACHE_CHECKING_EVENT);
2205     frontend3->AddExpectedEvent(ids3, APPCACHE_DOWNLOADING_EVENT);
2206     frontend3->AddExpectedEvent(ids3, APPCACHE_ERROR_EVENT);
2207
2208     WaitForUpdateToFinish();
2209   }
2210
2211   void MasterEntrySomeFailTest() {
2212     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
2213
2214     MakeService();
2215     group_ = new AppCacheGroup(
2216         service_->storage(),
2217         MockHttpServer::GetMockUrl("files/manifest1"),
2218         111);
2219     AppCacheUpdateJob* update =
2220         new AppCacheUpdateJob(service_.get(), group_.get());
2221     group_->update_job_ = update;
2222
2223     MockFrontend* frontend1 = MakeMockFrontend();
2224     frontend1->SetIgnoreProgressEvents(true);
2225     AppCacheHost* host1 = MakeHost(1, frontend1);
2226     host1->new_master_entry_url_ =
2227         MockHttpServer::GetMockUrl("files/nosuchfile");
2228     update->StartUpdate(host1, host1->new_master_entry_url_);
2229
2230     MockFrontend* frontend2 = MakeMockFrontend();
2231     AppCacheHost* host2 = MakeHost(2, frontend2);
2232     host2->new_master_entry_url_ =
2233         MockHttpServer::GetMockUrl("files/explicit2");
2234     update->StartUpdate(host2, host2->new_master_entry_url_);
2235
2236     // Set up checks for when update job finishes.
2237     do_checks_after_update_finished_ = true;
2238     expect_group_obsolete_ = false;
2239     expect_group_has_cache_ = true;  // as long as one pending master succeeds
2240     tested_manifest_ = MANIFEST1;
2241     expect_extra_entries_.insert(AppCache::EntryMap::value_type(
2242         MockHttpServer::GetMockUrl("files/explicit2"),
2243         AppCacheEntry(AppCacheEntry::MASTER)));
2244     MockFrontend::HostIds ids1(1, host1->host_id());
2245     frontend1->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
2246     frontend1->AddExpectedEvent(ids1, APPCACHE_DOWNLOADING_EVENT);
2247     frontend1->AddExpectedEvent(ids1, APPCACHE_ERROR_EVENT);
2248     MockFrontend::HostIds ids2(1, host2->host_id());
2249     frontend2->AddExpectedEvent(ids2, APPCACHE_CHECKING_EVENT);
2250     frontend2->AddExpectedEvent(ids2, APPCACHE_DOWNLOADING_EVENT);
2251     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);
2252     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);
2253     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);  // final
2254     frontend2->AddExpectedEvent(ids2, APPCACHE_CACHED_EVENT);
2255
2256     WaitForUpdateToFinish();
2257   }
2258
2259   void UpgradeMasterEntrySomeFailTest() {
2260     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
2261
2262     MakeService();
2263     group_ = new AppCacheGroup(
2264         service_->storage(),
2265         MockHttpServer::GetMockUrl("files/manifest1"),
2266         111);
2267     AppCacheUpdateJob* update =
2268         new AppCacheUpdateJob(service_.get(), group_.get());
2269     group_->update_job_ = update;
2270
2271     AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 42);
2272     MockFrontend* frontend1 = MakeMockFrontend();
2273     AppCacheHost* host1 = MakeHost(1, frontend1);
2274     host1->AssociateCompleteCache(cache);
2275
2276     MockFrontend* frontend2 = MakeMockFrontend();
2277     frontend2->SetIgnoreProgressEvents(true);
2278     AppCacheHost* host2 = MakeHost(2, frontend2);
2279     host2->new_master_entry_url_ =
2280         MockHttpServer::GetMockUrl("files/nosuchfile");
2281     update->StartUpdate(host2, host2->new_master_entry_url_);
2282
2283     MockFrontend* frontend3 = MakeMockFrontend();
2284     AppCacheHost* host3 = MakeHost(3, frontend3);
2285     host3->new_master_entry_url_ =
2286         MockHttpServer::GetMockUrl("files/explicit2");
2287     update->StartUpdate(host3, host3->new_master_entry_url_);
2288
2289     // Set up checks for when update job finishes.
2290     do_checks_after_update_finished_ = true;
2291     expect_group_obsolete_ = false;
2292     expect_group_has_cache_ = true;
2293     expect_old_cache_ = cache;
2294     tested_manifest_ = MANIFEST1;
2295     expect_extra_entries_.insert(AppCache::EntryMap::value_type(
2296         MockHttpServer::GetMockUrl("files/explicit2"),
2297         AppCacheEntry(AppCacheEntry::MASTER)));
2298     MockFrontend::HostIds ids1(1, host1->host_id());
2299     frontend1->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
2300     frontend1->AddExpectedEvent(ids1, APPCACHE_DOWNLOADING_EVENT);
2301     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);
2302     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);
2303     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // final
2304     frontend1->AddExpectedEvent(ids1, APPCACHE_UPDATE_READY_EVENT);
2305     MockFrontend::HostIds ids2(1, host2->host_id());
2306     frontend2->AddExpectedEvent(ids2, APPCACHE_DOWNLOADING_EVENT);
2307     frontend2->AddExpectedEvent(ids2, APPCACHE_ERROR_EVENT);
2308     MockFrontend::HostIds ids3(1, host3->host_id());
2309     frontend3->AddExpectedEvent(ids3, APPCACHE_CHECKING_EVENT);
2310     frontend3->AddExpectedEvent(ids3, APPCACHE_DOWNLOADING_EVENT);
2311     frontend3->AddExpectedEvent(ids3, APPCACHE_PROGRESS_EVENT);
2312     frontend3->AddExpectedEvent(ids3, APPCACHE_PROGRESS_EVENT);
2313     frontend3->AddExpectedEvent(ids3, APPCACHE_PROGRESS_EVENT);  // final
2314     frontend3->AddExpectedEvent(ids3, APPCACHE_UPDATE_READY_EVENT);
2315
2316     WaitForUpdateToFinish();
2317   }
2318
2319   void MasterEntryNoUpdateTest() {
2320     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
2321
2322     MakeService();
2323     group_ = new AppCacheGroup(service_->storage(),
2324         MockHttpServer::GetMockUrl("files/notmodified"), 111);
2325     AppCacheUpdateJob* update =
2326         new AppCacheUpdateJob(service_.get(), group_.get());
2327     group_->update_job_ = update;
2328
2329     AppCache* cache = MakeCacheForGroup(1, 111);
2330     MockFrontend* frontend1 = MakeMockFrontend();
2331     AppCacheHost* host1 = MakeHost(1, frontend1);
2332     host1->AssociateCompleteCache(cache);
2333
2334     // Give cache an existing entry that can also be fetched.
2335     cache->AddEntry(MockHttpServer::GetMockUrl("files/explicit2"),
2336                     AppCacheEntry(AppCacheEntry::EXPLICIT, 222));
2337
2338     // Reset the update time to null so we can verify it gets
2339     // modified in this test case by the UpdateJob.
2340     cache->set_update_time(base::Time());
2341
2342     MockFrontend* frontend2 = MakeMockFrontend();
2343     AppCacheHost* host2 = MakeHost(2, frontend2);
2344     host2->new_master_entry_url_ =
2345         MockHttpServer::GetMockUrl("files/explicit1");
2346     update->StartUpdate(host2, host2->new_master_entry_url_);
2347
2348     AppCacheHost* host3 = MakeHost(3, frontend2);  // same frontend as host2
2349     host3->new_master_entry_url_ =
2350         MockHttpServer::GetMockUrl("files/explicit2");
2351     update->StartUpdate(host3, host3->new_master_entry_url_);
2352
2353     // Set up checks for when update job finishes.
2354     do_checks_after_update_finished_ = true;
2355     expect_group_obsolete_ = false;
2356     expect_group_has_cache_ = true;
2357     expect_newest_cache_ = cache;  // newest cache still the same cache
2358     expect_non_null_update_time_ = true;
2359     tested_manifest_ = PENDING_MASTER_NO_UPDATE;
2360     MockFrontend::HostIds ids1(1, host1->host_id());
2361     frontend1->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
2362     frontend1->AddExpectedEvent(ids1, APPCACHE_NO_UPDATE_EVENT);
2363     MockFrontend::HostIds ids3(1, host3->host_id());
2364     frontend2->AddExpectedEvent(ids3, APPCACHE_CHECKING_EVENT);
2365     MockFrontend::HostIds ids2and3;
2366     ids2and3.push_back(host2->host_id());
2367     ids2and3.push_back(host3->host_id());
2368     frontend2->AddExpectedEvent(ids2and3, APPCACHE_NO_UPDATE_EVENT);
2369
2370     WaitForUpdateToFinish();
2371   }
2372
2373   void StartUpdateMidCacheAttemptTest() {
2374     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
2375
2376     MakeService();
2377     group_ = new AppCacheGroup(
2378         service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"),
2379         service_->storage()->NewGroupId());
2380     AppCacheUpdateJob* update =
2381         new AppCacheUpdateJob(service_.get(), group_.get());
2382     group_->update_job_ = update;
2383
2384     MockFrontend* frontend1 = MakeMockFrontend();
2385     AppCacheHost* host1 = MakeHost(1, frontend1);
2386     host1->new_master_entry_url_ =
2387         MockHttpServer::GetMockUrl("files/explicit2");
2388     update->StartUpdate(host1, host1->new_master_entry_url_);
2389     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
2390
2391     // Set up additional updates to be started while update is in progress.
2392     MockFrontend* frontend2 = MakeMockFrontend();
2393     frontend2->SetIgnoreProgressEvents(true);
2394     AppCacheHost* host2 = MakeHost(2, frontend2);
2395     host2->new_master_entry_url_ =
2396         MockHttpServer::GetMockUrl("files/nosuchfile");
2397
2398     MockFrontend* frontend3 = MakeMockFrontend();
2399     AppCacheHost* host3 = MakeHost(3, frontend3);
2400     host3->new_master_entry_url_ =
2401         MockHttpServer::GetMockUrl("files/explicit1");
2402
2403     MockFrontend* frontend4 = MakeMockFrontend();
2404     AppCacheHost* host4 = MakeHost(4, frontend4);
2405     host4->new_master_entry_url_ =
2406         MockHttpServer::GetMockUrl("files/explicit2");
2407
2408     MockFrontend* frontend5 = MakeMockFrontend();
2409     AppCacheHost* host5 = MakeHost(5, frontend5);  // no master entry url
2410
2411     frontend1->TriggerAdditionalUpdates(APPCACHE_DOWNLOADING_EVENT, update);
2412     frontend1->AdditionalUpdateHost(host2);  // fetch will fail
2413     frontend1->AdditionalUpdateHost(host3);  // same as an explicit entry
2414     frontend1->AdditionalUpdateHost(host4);  // same as another master entry
2415     frontend1->AdditionalUpdateHost(NULL);   // no host
2416     frontend1->AdditionalUpdateHost(host5);  // no master entry url
2417
2418     // Set up checks for when update job finishes.
2419     do_checks_after_update_finished_ = true;
2420     expect_group_obsolete_ = false;
2421     expect_group_has_cache_ = true;
2422     tested_manifest_ = MANIFEST1;
2423     expect_extra_entries_.insert(AppCache::EntryMap::value_type(
2424         MockHttpServer::GetMockUrl("files/explicit2"),
2425         AppCacheEntry(AppCacheEntry::MASTER)));
2426     MockFrontend::HostIds ids1(1, host1->host_id());
2427     frontend1->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
2428     frontend1->AddExpectedEvent(ids1, APPCACHE_DOWNLOADING_EVENT);
2429     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);
2430     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);
2431     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // final
2432     frontend1->AddExpectedEvent(ids1, APPCACHE_CACHED_EVENT);
2433     MockFrontend::HostIds ids2(1, host2->host_id());
2434     frontend2->AddExpectedEvent(ids2, APPCACHE_CHECKING_EVENT);
2435     frontend2->AddExpectedEvent(ids2, APPCACHE_DOWNLOADING_EVENT);
2436     frontend2->AddExpectedEvent(ids2, APPCACHE_ERROR_EVENT);
2437     MockFrontend::HostIds ids3(1, host3->host_id());
2438     frontend3->AddExpectedEvent(ids3, APPCACHE_CHECKING_EVENT);
2439     frontend3->AddExpectedEvent(ids3, APPCACHE_DOWNLOADING_EVENT);
2440     frontend3->AddExpectedEvent(ids3, APPCACHE_PROGRESS_EVENT);
2441     frontend3->AddExpectedEvent(ids3, APPCACHE_PROGRESS_EVENT);
2442     frontend3->AddExpectedEvent(ids3, APPCACHE_PROGRESS_EVENT);  // final
2443     frontend3->AddExpectedEvent(ids3, APPCACHE_CACHED_EVENT);
2444     MockFrontend::HostIds ids4(1, host4->host_id());
2445     frontend4->AddExpectedEvent(ids4, APPCACHE_CHECKING_EVENT);
2446     frontend4->AddExpectedEvent(ids4, APPCACHE_DOWNLOADING_EVENT);
2447     frontend4->AddExpectedEvent(ids4, APPCACHE_PROGRESS_EVENT);
2448     frontend4->AddExpectedEvent(ids4, APPCACHE_PROGRESS_EVENT);
2449     frontend4->AddExpectedEvent(ids4, APPCACHE_PROGRESS_EVENT);  // final
2450     frontend4->AddExpectedEvent(ids4, APPCACHE_CACHED_EVENT);
2451
2452     // Host 5 is not associated with cache so no progress/cached events.
2453     MockFrontend::HostIds ids5(1, host5->host_id());
2454     frontend5->AddExpectedEvent(ids5, APPCACHE_CHECKING_EVENT);
2455     frontend5->AddExpectedEvent(ids5, APPCACHE_DOWNLOADING_EVENT);
2456
2457     WaitForUpdateToFinish();
2458   }
2459
2460   void StartUpdateMidNoUpdateTest() {
2461     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
2462
2463     MakeService();
2464     group_ = new AppCacheGroup(
2465         service_->storage(), MockHttpServer::GetMockUrl("files/notmodified"),
2466         service_->storage()->NewGroupId());
2467     AppCacheUpdateJob* update =
2468         new AppCacheUpdateJob(service_.get(), group_.get());
2469     group_->update_job_ = update;
2470
2471     AppCache* cache = MakeCacheForGroup(1, 111);
2472     MockFrontend* frontend1 = MakeMockFrontend();
2473     AppCacheHost* host1 = MakeHost(1, frontend1);
2474     host1->AssociateCompleteCache(cache);
2475
2476     // Give cache an existing entry.
2477     cache->AddEntry(MockHttpServer::GetMockUrl("files/explicit2"),
2478                     AppCacheEntry(AppCacheEntry::EXPLICIT, 222));
2479
2480     // Start update with a pending master entry that will fail to give us an
2481     // event to trigger other updates.
2482     MockFrontend* frontend2 = MakeMockFrontend();
2483     AppCacheHost* host2 = MakeHost(2, frontend2);
2484     host2->new_master_entry_url_ =
2485         MockHttpServer::GetMockUrl("files/nosuchfile");
2486     update->StartUpdate(host2, host2->new_master_entry_url_);
2487     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
2488
2489     // Set up additional updates to be started while update is in progress.
2490     MockFrontend* frontend3 = MakeMockFrontend();
2491     AppCacheHost* host3 = MakeHost(3, frontend3);
2492     host3->new_master_entry_url_ =
2493         MockHttpServer::GetMockUrl("files/explicit1");
2494
2495     MockFrontend* frontend4 = MakeMockFrontend();
2496     AppCacheHost* host4 = MakeHost(4, frontend4);  // no master entry url
2497
2498     MockFrontend* frontend5 = MakeMockFrontend();
2499     AppCacheHost* host5 = MakeHost(5, frontend5);
2500     host5->new_master_entry_url_ =
2501         MockHttpServer::GetMockUrl("files/explicit2");  // existing entry
2502
2503     MockFrontend* frontend6 = MakeMockFrontend();
2504     AppCacheHost* host6 = MakeHost(6, frontend6);
2505     host6->new_master_entry_url_ =
2506         MockHttpServer::GetMockUrl("files/explicit1");
2507
2508     frontend2->TriggerAdditionalUpdates(APPCACHE_ERROR_EVENT, update);
2509     frontend2->AdditionalUpdateHost(host3);
2510     frontend2->AdditionalUpdateHost(NULL);   // no host
2511     frontend2->AdditionalUpdateHost(host4);  // no master entry url
2512     frontend2->AdditionalUpdateHost(host5);  // same as existing cache entry
2513     frontend2->AdditionalUpdateHost(host6);  // same as another master entry
2514
2515     // Set up checks for when update job finishes.
2516     do_checks_after_update_finished_ = true;
2517     expect_group_obsolete_ = false;
2518     expect_group_has_cache_ = true;
2519     expect_newest_cache_ = cache;  // newest cache unaffected by update
2520     tested_manifest_ = PENDING_MASTER_NO_UPDATE;
2521     MockFrontend::HostIds ids1(1, host1->host_id());  // prior associated host
2522     frontend1->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
2523     frontend1->AddExpectedEvent(ids1, APPCACHE_NO_UPDATE_EVENT);
2524     MockFrontend::HostIds ids2(1, host2->host_id());
2525     frontend2->AddExpectedEvent(ids2, APPCACHE_ERROR_EVENT);
2526     MockFrontend::HostIds ids3(1, host3->host_id());
2527     frontend3->AddExpectedEvent(ids3, APPCACHE_CHECKING_EVENT);
2528     frontend3->AddExpectedEvent(ids3, APPCACHE_NO_UPDATE_EVENT);
2529     MockFrontend::HostIds ids4(1, host4->host_id());  // unassociated w/cache
2530     frontend4->AddExpectedEvent(ids4, APPCACHE_CHECKING_EVENT);
2531     MockFrontend::HostIds ids5(1, host5->host_id());
2532     frontend5->AddExpectedEvent(ids5, APPCACHE_CHECKING_EVENT);
2533     frontend5->AddExpectedEvent(ids5, APPCACHE_NO_UPDATE_EVENT);
2534     MockFrontend::HostIds ids6(1, host6->host_id());
2535     frontend6->AddExpectedEvent(ids6, APPCACHE_CHECKING_EVENT);
2536     frontend6->AddExpectedEvent(ids6, APPCACHE_NO_UPDATE_EVENT);
2537
2538     WaitForUpdateToFinish();
2539   }
2540
2541   void StartUpdateMidDownloadTest() {
2542     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
2543
2544     MakeService();
2545     group_ = new AppCacheGroup(
2546         service_->storage(),
2547         MockHttpServer::GetMockUrl("files/manifest1"),
2548         111);
2549     AppCacheUpdateJob* update =
2550         new AppCacheUpdateJob(service_.get(), group_.get());
2551     group_->update_job_ = update;
2552
2553     AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 42);
2554     MockFrontend* frontend1 = MakeMockFrontend();
2555     AppCacheHost* host1 = MakeHost(1, frontend1);
2556     host1->AssociateCompleteCache(cache);
2557
2558     update->StartUpdate(NULL, GURL());
2559
2560     // Set up additional updates to be started while update is in progress.
2561     MockFrontend* frontend2 = MakeMockFrontend();
2562     AppCacheHost* host2 = MakeHost(2, frontend2);
2563     host2->new_master_entry_url_ =
2564         MockHttpServer::GetMockUrl("files/explicit1");
2565
2566     MockFrontend* frontend3 = MakeMockFrontend();
2567     AppCacheHost* host3 = MakeHost(3, frontend3);
2568     host3->new_master_entry_url_ =
2569         MockHttpServer::GetMockUrl("files/explicit2");
2570
2571     MockFrontend* frontend4 = MakeMockFrontend();
2572     AppCacheHost* host4 = MakeHost(4, frontend4);  // no master entry url
2573
2574     MockFrontend* frontend5 = MakeMockFrontend();
2575     AppCacheHost* host5 = MakeHost(5, frontend5);
2576     host5->new_master_entry_url_ =
2577         MockHttpServer::GetMockUrl("files/explicit2");
2578
2579     frontend1->TriggerAdditionalUpdates(APPCACHE_PROGRESS_EVENT, update);
2580     frontend1->AdditionalUpdateHost(host2);  // same as entry in manifest
2581     frontend1->AdditionalUpdateHost(NULL);   // no host
2582     frontend1->AdditionalUpdateHost(host3);  // new master entry
2583     frontend1->AdditionalUpdateHost(host4);  // no master entry url
2584     frontend1->AdditionalUpdateHost(host5);  // same as another master entry
2585
2586     // Set up checks for when update job finishes.
2587     do_checks_after_update_finished_ = true;
2588     expect_group_obsolete_ = false;
2589     expect_group_has_cache_ = true;
2590     tested_manifest_ = MANIFEST1;
2591     expect_extra_entries_.insert(AppCache::EntryMap::value_type(
2592         MockHttpServer::GetMockUrl("files/explicit2"),
2593         AppCacheEntry(AppCacheEntry::MASTER)));
2594     MockFrontend::HostIds ids1(1, host1->host_id());  // prior associated host
2595     frontend1->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
2596     frontend1->AddExpectedEvent(ids1, APPCACHE_DOWNLOADING_EVENT);
2597     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);
2598     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);
2599     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // final
2600     frontend1->AddExpectedEvent(ids1, APPCACHE_UPDATE_READY_EVENT);
2601     MockFrontend::HostIds ids2(1, host2->host_id());
2602     frontend2->AddExpectedEvent(ids2, APPCACHE_CHECKING_EVENT);
2603     frontend2->AddExpectedEvent(ids2, APPCACHE_DOWNLOADING_EVENT);
2604     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);
2605     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);  // final
2606     frontend2->AddExpectedEvent(ids2, APPCACHE_UPDATE_READY_EVENT);
2607     MockFrontend::HostIds ids3(1, host3->host_id());
2608     frontend3->AddExpectedEvent(ids3, APPCACHE_CHECKING_EVENT);
2609     frontend3->AddExpectedEvent(ids3, APPCACHE_DOWNLOADING_EVENT);
2610     frontend3->AddExpectedEvent(ids3, APPCACHE_PROGRESS_EVENT);
2611     frontend3->AddExpectedEvent(ids3, APPCACHE_PROGRESS_EVENT);  // final
2612     frontend3->AddExpectedEvent(ids3, APPCACHE_UPDATE_READY_EVENT);
2613     MockFrontend::HostIds ids4(1, host4->host_id());  // unassociated w/cache
2614     frontend4->AddExpectedEvent(ids4, APPCACHE_CHECKING_EVENT);
2615     frontend4->AddExpectedEvent(ids4, APPCACHE_DOWNLOADING_EVENT);
2616     MockFrontend::HostIds ids5(1, host5->host_id());
2617     frontend5->AddExpectedEvent(ids5, APPCACHE_CHECKING_EVENT);
2618     frontend5->AddExpectedEvent(ids5, APPCACHE_DOWNLOADING_EVENT);
2619     frontend5->AddExpectedEvent(ids5, APPCACHE_PROGRESS_EVENT);
2620     frontend5->AddExpectedEvent(ids5, APPCACHE_PROGRESS_EVENT);  // final
2621     frontend5->AddExpectedEvent(ids5, APPCACHE_UPDATE_READY_EVENT);
2622
2623     WaitForUpdateToFinish();
2624   }
2625
2626   void QueueMasterEntryTest() {
2627     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
2628
2629     MakeService();
2630     group_ = new AppCacheGroup(
2631         service_->storage(),
2632         MockHttpServer::GetMockUrl("files/manifest1"),
2633         111);
2634     AppCacheUpdateJob* update =
2635         new AppCacheUpdateJob(service_.get(), group_.get());
2636     group_->update_job_ = update;
2637
2638     // Pretend update job has been running and is about to terminate.
2639     group_->update_status_ = AppCacheGroup::DOWNLOADING;
2640     update->internal_state_ = AppCacheUpdateJob::REFETCH_MANIFEST;
2641     EXPECT_TRUE(update->IsTerminating());
2642
2643     // Start an update. Should be queued.
2644     MockFrontend* frontend = MakeMockFrontend();
2645     AppCacheHost* host = MakeHost(1, frontend);
2646     host->new_master_entry_url_ =
2647         MockHttpServer::GetMockUrl("files/explicit2");
2648     update->StartUpdate(host, host->new_master_entry_url_);
2649     EXPECT_TRUE(update->pending_master_entries_.empty());
2650     EXPECT_FALSE(group_->queued_updates_.empty());
2651
2652     // Delete update, causing it to finish, which should trigger a new update
2653     // for the queued host and master entry after a delay.
2654     delete update;
2655     EXPECT_FALSE(group_->restart_update_task_.IsCancelled());
2656
2657     // Set up checks for when queued update job finishes.
2658     do_checks_after_update_finished_ = true;
2659     expect_group_obsolete_ = false;
2660     expect_group_has_cache_ = true;
2661     tested_manifest_ = MANIFEST1;
2662     expect_extra_entries_.insert(AppCache::EntryMap::value_type(
2663         host->new_master_entry_url_, AppCacheEntry(AppCacheEntry::MASTER)));
2664     MockFrontend::HostIds ids1(1, host->host_id());
2665     frontend->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
2666     frontend->AddExpectedEvent(ids1, APPCACHE_DOWNLOADING_EVENT);
2667     frontend->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);
2668     frontend->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);
2669     frontend->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // final
2670     frontend->AddExpectedEvent(ids1, APPCACHE_CACHED_EVENT);
2671
2672     // Group status will be APPCACHE_STATUS_IDLE so cannot call
2673     // WaitForUpdateToFinish.
2674     group_->AddUpdateObserver(this);
2675   }
2676
2677   void IfModifiedSinceTest() {
2678     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
2679
2680     net::URLRequestJobFactoryImpl* new_factory(
2681         new net::URLRequestJobFactoryImpl);
2682     new_factory->SetProtocolHandler("http", new IfModifiedSinceJobFactory);
2683     io_thread_->SetNewJobFactory(new_factory);
2684
2685     MakeService();
2686     group_ = new AppCacheGroup(
2687         service_->storage(), GURL("http://headertest"), 111);
2688     AppCacheUpdateJob* update =
2689         new AppCacheUpdateJob(service_.get(), group_.get());
2690     group_->update_job_ = update;
2691
2692     // First test against a cache attempt. Will start manifest fetch
2693     // synchronously.
2694     HttpHeadersRequestTestJob::Initialize(std::string(), std::string());
2695     MockFrontend mock_frontend;
2696     AppCacheHost host(1, &mock_frontend, service_.get());
2697     update->StartUpdate(&host, GURL());
2698     HttpHeadersRequestTestJob::Verify();
2699     delete update;
2700
2701     // Now simulate a refetch manifest request. Will start fetch request
2702     // synchronously.
2703     const char data[] =
2704         "HTTP/1.1 200 OK\0"
2705         "\0";
2706     net::HttpResponseHeaders* headers =
2707         new net::HttpResponseHeaders(std::string(data, arraysize(data)));
2708     net::HttpResponseInfo* response_info = new net::HttpResponseInfo();
2709     response_info->headers = headers;  // adds ref to headers
2710
2711     HttpHeadersRequestTestJob::Initialize(std::string(), std::string());
2712     update = new AppCacheUpdateJob(service_.get(), group_.get());
2713     group_->update_job_ = update;
2714     group_->update_status_ = AppCacheGroup::DOWNLOADING;
2715     update->manifest_response_info_.reset(response_info);
2716     update->internal_state_ = AppCacheUpdateJob::REFETCH_MANIFEST;
2717     update->FetchManifest(false);  // not first request
2718     HttpHeadersRequestTestJob::Verify();
2719     delete update;
2720
2721     // Change the headers to include a Last-Modified header. Manifest refetch
2722     // should include If-Modified-Since header.
2723     const char data2[] =
2724         "HTTP/1.1 200 OK\0"
2725         "Last-Modified: Sat, 29 Oct 1994 19:43:31 GMT\0"
2726         "\0";
2727     net::HttpResponseHeaders* headers2 =
2728         new net::HttpResponseHeaders(std::string(data2, arraysize(data2)));
2729     response_info = new net::HttpResponseInfo();
2730     response_info->headers = headers2;
2731
2732     HttpHeadersRequestTestJob::Initialize("Sat, 29 Oct 1994 19:43:31 GMT",
2733                                           std::string());
2734     update = new AppCacheUpdateJob(service_.get(), group_.get());
2735     group_->update_job_ = update;
2736     group_->update_status_ = AppCacheGroup::DOWNLOADING;
2737     update->manifest_response_info_.reset(response_info);
2738     update->internal_state_ = AppCacheUpdateJob::REFETCH_MANIFEST;
2739     update->FetchManifest(false);  // not first request
2740     HttpHeadersRequestTestJob::Verify();
2741     delete update;
2742
2743     UpdateFinished();
2744   }
2745
2746   void IfModifiedSinceUpgradeTest() {
2747     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
2748
2749     HttpHeadersRequestTestJob::Initialize("Sat, 29 Oct 1994 19:43:31 GMT",
2750                                           std::string());
2751     net::URLRequestJobFactoryImpl* new_factory(
2752         new net::URLRequestJobFactoryImpl);
2753     new_factory->SetProtocolHandler("http", new IfModifiedSinceJobFactory);
2754     io_thread_->SetNewJobFactory(new_factory);
2755
2756     MakeService();
2757     group_ =new AppCacheGroup(
2758         service_->storage(),
2759         MockHttpServer::GetMockUrl("files/manifest1"),
2760         111);
2761     AppCacheUpdateJob* update =
2762         new AppCacheUpdateJob(service_.get(), group_.get());
2763     group_->update_job_ = update;
2764
2765     // Give the newest cache a manifest enry that is in storage.
2766     response_writer_.reset(
2767         service_->storage()->CreateResponseWriter(group_->manifest_url(),
2768                                                   group_->group_id()));
2769
2770     AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(),
2771                                         response_writer_->response_id());
2772     MockFrontend* frontend = MakeMockFrontend();
2773     AppCacheHost* host = MakeHost(1, frontend);
2774     host->AssociateCompleteCache(cache);
2775
2776     // Set up checks for when update job finishes.
2777     do_checks_after_update_finished_ = true;
2778     expect_group_obsolete_ = false;
2779     expect_group_has_cache_ = true;
2780     expect_old_cache_ = cache;
2781     tested_manifest_ = MANIFEST1;
2782     MockFrontend::HostIds ids1(1, host->host_id());
2783     frontend->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
2784     frontend->AddExpectedEvent(ids1, APPCACHE_DOWNLOADING_EVENT);
2785     frontend->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);
2786     frontend->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);
2787     frontend->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // final
2788     frontend->AddExpectedEvent(ids1, APPCACHE_UPDATE_READY_EVENT);
2789
2790     // Seed storage with expected manifest response info that will cause
2791     // an If-Modified-Since header to be put in the manifest fetch request.
2792     const char data[] =
2793         "HTTP/1.1 200 OK\0"
2794         "Last-Modified: Sat, 29 Oct 1994 19:43:31 GMT\0"
2795         "\0";
2796     net::HttpResponseHeaders* headers =
2797         new net::HttpResponseHeaders(std::string(data, arraysize(data)));
2798     net::HttpResponseInfo* response_info = new net::HttpResponseInfo();
2799     response_info->headers = headers;  // adds ref to headers
2800     scoped_refptr<HttpResponseInfoIOBuffer> io_buffer(
2801         new HttpResponseInfoIOBuffer(response_info));  // adds ref to info
2802     response_writer_->WriteInfo(
2803         io_buffer.get(),
2804         base::Bind(&AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData,
2805                    base::Unretained(this)));
2806
2807     // Start update after data write completes asynchronously.
2808   }
2809
2810   void IfNoneMatchUpgradeTest() {
2811     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
2812
2813     HttpHeadersRequestTestJob::Initialize(std::string(), "\"LadeDade\"");
2814     net::URLRequestJobFactoryImpl* new_factory(
2815         new net::URLRequestJobFactoryImpl);
2816     new_factory->SetProtocolHandler("http", new IfModifiedSinceJobFactory);
2817     io_thread_->SetNewJobFactory(new_factory);
2818
2819     MakeService();
2820     group_ = new AppCacheGroup(
2821         service_->storage(),
2822         MockHttpServer::GetMockUrl("files/manifest1"),
2823         111);
2824     AppCacheUpdateJob* update =
2825         new AppCacheUpdateJob(service_.get(), group_.get());
2826     group_->update_job_ = update;
2827
2828     // Give the newest cache a manifest enry that is in storage.
2829     response_writer_.reset(
2830         service_->storage()->CreateResponseWriter(group_->manifest_url(),
2831                                                   group_->group_id()));
2832
2833     AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(),
2834                                         response_writer_->response_id());
2835     MockFrontend* frontend = MakeMockFrontend();
2836     AppCacheHost* host = MakeHost(1, frontend);
2837     host->AssociateCompleteCache(cache);
2838
2839     // Set up checks for when update job finishes.
2840     do_checks_after_update_finished_ = true;
2841     expect_group_obsolete_ = false;
2842     expect_group_has_cache_ = true;
2843     expect_old_cache_ = cache;
2844     tested_manifest_ = MANIFEST1;
2845     MockFrontend::HostIds ids1(1, host->host_id());
2846     frontend->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
2847     frontend->AddExpectedEvent(ids1, APPCACHE_DOWNLOADING_EVENT);
2848     frontend->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);
2849     frontend->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);
2850     frontend->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // final
2851     frontend->AddExpectedEvent(ids1, APPCACHE_UPDATE_READY_EVENT);
2852
2853     // Seed storage with expected manifest response info that will cause
2854     // an If-None-Match header to be put in the manifest fetch request.
2855     const char data[] =
2856         "HTTP/1.1 200 OK\0"
2857         "ETag: \"LadeDade\"\0"
2858         "\0";
2859     net::HttpResponseHeaders* headers =
2860         new net::HttpResponseHeaders(std::string(data, arraysize(data)));
2861     net::HttpResponseInfo* response_info = new net::HttpResponseInfo();
2862     response_info->headers = headers;  // adds ref to headers
2863     scoped_refptr<HttpResponseInfoIOBuffer> io_buffer(
2864         new HttpResponseInfoIOBuffer(response_info));  // adds ref to info
2865     response_writer_->WriteInfo(
2866         io_buffer.get(),
2867         base::Bind(&AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData,
2868                    base::Unretained(this)));
2869
2870     // Start update after data write completes asynchronously.
2871   }
2872
2873   void IfNoneMatchRefetchTest() {
2874     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
2875
2876     HttpHeadersRequestTestJob::Initialize(std::string(), "\"LadeDade\"");
2877     net::URLRequestJobFactoryImpl* new_factory(
2878         new net::URLRequestJobFactoryImpl);
2879     new_factory->SetProtocolHandler("http", new IfModifiedSinceJobFactory);
2880     io_thread_->SetNewJobFactory(new_factory);
2881
2882     MakeService();
2883     group_ = new AppCacheGroup(
2884         service_->storage(), GURL("http://headertest"), 111);
2885     AppCacheUpdateJob* update =
2886         new AppCacheUpdateJob(service_.get(), group_.get());
2887     group_->update_job_ = update;
2888
2889     // Simulate a refetch manifest request that uses an ETag header.
2890     const char data[] =
2891         "HTTP/1.1 200 OK\0"
2892         "ETag: \"LadeDade\"\0"
2893         "\0";
2894     net::HttpResponseHeaders* headers =
2895         new net::HttpResponseHeaders(std::string(data, arraysize(data)));
2896     net::HttpResponseInfo* response_info = new net::HttpResponseInfo();
2897     response_info->headers = headers;  // adds ref to headers
2898
2899     group_->update_status_ = AppCacheGroup::DOWNLOADING;
2900     update->manifest_response_info_.reset(response_info);
2901     update->internal_state_ = AppCacheUpdateJob::REFETCH_MANIFEST;
2902     update->FetchManifest(false);  // not first request
2903     HttpHeadersRequestTestJob::Verify();
2904     delete update;
2905
2906     UpdateFinished();
2907   }
2908
2909   void MultipleHeadersRefetchTest() {
2910     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
2911
2912     // Verify that code is correct when building multiple extra headers.
2913     HttpHeadersRequestTestJob::Initialize(
2914         "Sat, 29 Oct 1994 19:43:31 GMT", "\"LadeDade\"");
2915     net::URLRequestJobFactoryImpl* new_factory(
2916         new net::URLRequestJobFactoryImpl);
2917     new_factory->SetProtocolHandler("http", new IfModifiedSinceJobFactory);
2918     io_thread_->SetNewJobFactory(new_factory);
2919
2920     MakeService();
2921     group_ = new AppCacheGroup(
2922         service_->storage(), GURL("http://headertest"), 111);
2923     AppCacheUpdateJob* update =
2924         new AppCacheUpdateJob(service_.get(), group_.get());
2925     group_->update_job_ = update;
2926
2927     // Simulate a refetch manifest request that uses an ETag header.
2928     const char data[] =
2929         "HTTP/1.1 200 OK\0"
2930         "Last-Modified: Sat, 29 Oct 1994 19:43:31 GMT\0"
2931         "ETag: \"LadeDade\"\0"
2932         "\0";
2933     net::HttpResponseHeaders* headers =
2934         new net::HttpResponseHeaders(std::string(data, arraysize(data)));
2935     net::HttpResponseInfo* response_info = new net::HttpResponseInfo();
2936     response_info->headers = headers;  // adds ref to headers
2937
2938     group_->update_status_ = AppCacheGroup::DOWNLOADING;
2939     update->manifest_response_info_.reset(response_info);
2940     update->internal_state_ = AppCacheUpdateJob::REFETCH_MANIFEST;
2941     update->FetchManifest(false);  // not first request
2942     HttpHeadersRequestTestJob::Verify();
2943     delete update;
2944
2945     UpdateFinished();
2946   }
2947
2948   void CrossOriginHttpsSuccessTest() {
2949     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
2950
2951     GURL manifest_url = MockHttpServer::GetMockHttpsUrl(
2952         "files/valid_cross_origin_https_manifest");
2953
2954     MakeService();
2955     group_ = new AppCacheGroup(
2956         service_->storage(), manifest_url, service_->storage()->NewGroupId());
2957     AppCacheUpdateJob* update =
2958         new AppCacheUpdateJob(service_.get(), group_.get());
2959     group_->update_job_ = update;
2960
2961     MockFrontend* frontend = MakeMockFrontend();
2962     AppCacheHost* host = MakeHost(1, frontend);
2963     update->StartUpdate(host, GURL());
2964
2965     // Set up checks for when update job finishes.
2966     do_checks_after_update_finished_ = true;
2967     expect_group_obsolete_ = false;
2968     expect_group_has_cache_ = true;
2969     tested_manifest_ = NONE;
2970     MockFrontend::HostIds host_ids(1, host->host_id());
2971     frontend->AddExpectedEvent(host_ids, APPCACHE_CHECKING_EVENT);
2972
2973     WaitForUpdateToFinish();
2974   }
2975
2976   void CrossOriginHttpsDeniedTest() {
2977     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
2978
2979     GURL manifest_url = MockHttpServer::GetMockHttpsUrl(
2980         "files/invalid_cross_origin_https_manifest");
2981
2982     MakeService();
2983     group_ = new AppCacheGroup(
2984         service_->storage(), manifest_url, service_->storage()->NewGroupId());
2985     AppCacheUpdateJob* update =
2986         new AppCacheUpdateJob(service_.get(), group_.get());
2987     group_->update_job_ = update;
2988
2989     MockFrontend* frontend = MakeMockFrontend();
2990     AppCacheHost* host = MakeHost(1, frontend);
2991     update->StartUpdate(host, GURL());
2992
2993     // Set up checks for when update job finishes.
2994     do_checks_after_update_finished_ = true;
2995     expect_group_obsolete_ = false;
2996     expect_group_has_cache_ = false;
2997     tested_manifest_ = NONE;
2998     MockFrontend::HostIds host_ids(1, host->host_id());
2999     frontend->AddExpectedEvent(host_ids, APPCACHE_CHECKING_EVENT);
3000
3001     WaitForUpdateToFinish();
3002   }
3003
3004   void WaitForUpdateToFinish() {
3005     if (group_->update_status() == AppCacheGroup::IDLE)
3006       UpdateFinished();
3007     else
3008       group_->AddUpdateObserver(this);
3009   }
3010
3011   void OnUpdateComplete(AppCacheGroup* group) override {
3012     ASSERT_EQ(group_.get(), group);
3013     protect_newest_cache_ = group->newest_complete_cache();
3014     UpdateFinished();
3015   }
3016
3017   void UpdateFinished() {
3018     // We unwind the stack prior to finishing up to let stack-based objects
3019     // get deleted.
3020     base::MessageLoop::current()->PostTask(
3021         FROM_HERE,
3022         base::Bind(&AppCacheUpdateJobTest::UpdateFinishedUnwound,
3023                    base::Unretained(this)));
3024   }
3025
3026   void UpdateFinishedUnwound() {
3027     EXPECT_EQ(AppCacheGroup::IDLE, group_->update_status());
3028     EXPECT_TRUE(group_->update_job() == NULL);
3029     if (do_checks_after_update_finished_)
3030       VerifyExpectations();
3031
3032     // Clean up everything that was created on the IO thread.
3033     protect_newest_cache_ = NULL;
3034     group_ = NULL;
3035     STLDeleteContainerPointers(hosts_.begin(), hosts_.end());
3036     STLDeleteContainerPointers(frontends_.begin(), frontends_.end());
3037     response_infos_.clear();
3038     service_.reset(NULL);
3039
3040     event_->Signal();
3041   }
3042
3043   void MakeService() {
3044     service_.reset(new MockAppCacheService());
3045     service_->set_request_context(io_thread_->request_context());
3046   }
3047
3048   AppCache* MakeCacheForGroup(int64 cache_id, int64 manifest_response_id) {
3049     return MakeCacheForGroup(cache_id, group_->manifest_url(),
3050                              manifest_response_id);
3051   }
3052
3053   AppCache* MakeCacheForGroup(int64 cache_id, const GURL& manifest_entry_url,
3054                               int64 manifest_response_id) {
3055     AppCache* cache = new AppCache(service_->storage(), cache_id);
3056     cache->set_complete(true);
3057     cache->set_update_time(base::Time::Now());
3058     group_->AddCache(cache);
3059
3060     // Add manifest entry to cache.
3061     cache->AddEntry(manifest_entry_url,
3062         AppCacheEntry(AppCacheEntry::MANIFEST, manifest_response_id));
3063
3064     return cache;
3065   }
3066
3067   AppCacheHost* MakeHost(int host_id, AppCacheFrontend* frontend) {
3068     AppCacheHost* host = new AppCacheHost(host_id, frontend, service_.get());
3069     hosts_.push_back(host);
3070     return host;
3071   }
3072
3073   AppCacheResponseInfo* MakeAppCacheResponseInfo(
3074       const GURL& manifest_url, int64 response_id,
3075       const std::string& raw_headers) {
3076     net::HttpResponseInfo* http_info = new net::HttpResponseInfo();
3077     http_info->headers = new net::HttpResponseHeaders(raw_headers);
3078     scoped_refptr<AppCacheResponseInfo> info(
3079         new AppCacheResponseInfo(service_->storage(), manifest_url,
3080                                  response_id, http_info, 0));
3081     response_infos_.push_back(info);
3082     return info.get();
3083   }
3084
3085   MockFrontend* MakeMockFrontend() {
3086     MockFrontend* frontend = new MockFrontend();
3087     frontends_.push_back(frontend);
3088     return frontend;
3089   }
3090
3091   // Verifies conditions about the group and notifications after an update
3092   // has finished. Cannot verify update job internals as update is deleted.
3093   void VerifyExpectations() {
3094     RetryRequestTestJob::Verify();
3095     HttpHeadersRequestTestJob::Verify();
3096
3097     EXPECT_EQ(expect_group_obsolete_, group_->is_obsolete());
3098     EXPECT_EQ(expect_group_is_being_deleted_, group_->is_being_deleted());
3099
3100     if (expect_group_has_cache_) {
3101       EXPECT_TRUE(group_->newest_complete_cache() != NULL);
3102
3103       if (expect_non_null_update_time_)
3104         EXPECT_TRUE(!group_->newest_complete_cache()->update_time().is_null());
3105
3106       if (expect_old_cache_) {
3107         EXPECT_NE(expect_old_cache_, group_->newest_complete_cache());
3108         EXPECT_TRUE(group_->old_caches().end() !=
3109             std::find(group_->old_caches().begin(),
3110                       group_->old_caches().end(), expect_old_cache_));
3111       }
3112       if (expect_newest_cache_) {
3113         EXPECT_EQ(expect_newest_cache_, group_->newest_complete_cache());
3114         EXPECT_TRUE(group_->old_caches().end() ==
3115             std::find(group_->old_caches().begin(),
3116                       group_->old_caches().end(), expect_newest_cache_));
3117       } else {
3118         // Tests that don't know which newest cache to expect contain updates
3119         // that succeed (because the update creates a new cache whose pointer
3120         // is unknown to the test). Check group and newest cache were stored
3121         // when update succeeds.
3122         MockAppCacheStorage* storage =
3123             reinterpret_cast<MockAppCacheStorage*>(service_->storage());
3124         EXPECT_TRUE(storage->IsGroupStored(group_.get()));
3125         EXPECT_TRUE(storage->IsCacheStored(group_->newest_complete_cache()));
3126
3127         // Check that all entries in the newest cache were stored.
3128         const AppCache::EntryMap& entries =
3129             group_->newest_complete_cache()->entries();
3130         for (AppCache::EntryMap::const_iterator it = entries.begin();
3131              it != entries.end(); ++it) {
3132           EXPECT_NE(kAppCacheNoResponseId, it->second.response_id());
3133
3134           // Check that any copied entries have the expected response id
3135           // and that entries that are not copied have a different response id.
3136           std::map<GURL, int64>::iterator found =
3137               expect_response_ids_.find(it->first);
3138           if (found != expect_response_ids_.end()) {
3139             EXPECT_EQ(found->second, it->second.response_id());
3140           } else if (expect_old_cache_) {
3141             AppCacheEntry* old_entry = expect_old_cache_->GetEntry(it->first);
3142             if (old_entry)
3143               EXPECT_NE(old_entry->response_id(), it->second.response_id());
3144           }
3145         }
3146       }
3147     } else {
3148       EXPECT_TRUE(group_->newest_complete_cache() == NULL);
3149     }
3150
3151     // Check expected events.
3152     for (size_t i = 0; i < frontends_.size(); ++i) {
3153       MockFrontend* frontend = frontends_[i];
3154
3155       MockFrontend::RaisedEvents& expected_events = frontend->expected_events_;
3156       MockFrontend::RaisedEvents& actual_events = frontend->raised_events_;
3157       EXPECT_EQ(expected_events.size(), actual_events.size());
3158
3159       // Check each expected event.
3160       for (size_t j = 0;
3161            j < expected_events.size() && j < actual_events.size(); ++j) {
3162         EXPECT_EQ(expected_events[j].second, actual_events[j].second);
3163
3164         MockFrontend::HostIds& expected_ids = expected_events[j].first;
3165         MockFrontend::HostIds& actual_ids = actual_events[j].first;
3166         EXPECT_EQ(expected_ids.size(), actual_ids.size());
3167
3168         for (size_t k = 0; k < expected_ids.size(); ++k) {
3169           int id = expected_ids[k];
3170           EXPECT_TRUE(std::find(actual_ids.begin(), actual_ids.end(), id) !=
3171               actual_ids.end());
3172         }
3173       }
3174
3175       if (!frontend->expected_error_message_.empty()) {
3176         EXPECT_EQ(frontend->expected_error_message_,
3177                   frontend->error_message_);
3178       }
3179     }
3180
3181     // Verify expected cache contents last as some checks are asserts
3182     // and will abort the test if they fail.
3183     if (tested_manifest_) {
3184       AppCache* cache = group_->newest_complete_cache();
3185       ASSERT_TRUE(cache != NULL);
3186       EXPECT_EQ(group_.get(), cache->owning_group());
3187       EXPECT_TRUE(cache->is_complete());
3188
3189       switch (tested_manifest_) {
3190         case MANIFEST1:
3191           VerifyManifest1(cache);
3192           break;
3193         case MANIFEST_MERGED_TYPES:
3194           VerifyManifestMergedTypes(cache);
3195           break;
3196         case EMPTY_MANIFEST:
3197           VerifyEmptyManifest(cache);
3198           break;
3199         case EMPTY_FILE_MANIFEST:
3200           VerifyEmptyFileManifest(cache);
3201           break;
3202         case PENDING_MASTER_NO_UPDATE:
3203           VerifyMasterEntryNoUpdate(cache);
3204           break;
3205         case MANIFEST_WITH_INTERCEPT:
3206           VerifyManifestWithIntercept(cache);
3207           break;
3208         case NONE:
3209         default:
3210           break;
3211       }
3212     }
3213   }
3214
3215   void VerifyManifest1(AppCache* cache) {
3216     size_t expected = 3 + expect_extra_entries_.size();
3217     EXPECT_EQ(expected, cache->entries().size());
3218     const char* kManifestPath = tested_manifest_path_override_ ?
3219         tested_manifest_path_override_ :
3220         "files/manifest1";
3221     AppCacheEntry* entry =
3222         cache->GetEntry(MockHttpServer::GetMockUrl(kManifestPath));
3223     ASSERT_TRUE(entry);
3224     EXPECT_EQ(AppCacheEntry::MANIFEST, entry->types());
3225     entry = cache->GetEntry(MockHttpServer::GetMockUrl("files/explicit1"));
3226     ASSERT_TRUE(entry);
3227     EXPECT_TRUE(entry->IsExplicit());
3228     entry = cache->GetEntry(
3229         MockHttpServer::GetMockUrl("files/fallback1a"));
3230     ASSERT_TRUE(entry);
3231     EXPECT_EQ(AppCacheEntry::FALLBACK, entry->types());
3232
3233     for (AppCache::EntryMap::iterator i = expect_extra_entries_.begin();
3234          i != expect_extra_entries_.end(); ++i) {
3235       entry = cache->GetEntry(i->first);
3236       ASSERT_TRUE(entry);
3237       EXPECT_EQ(i->second.types(), entry->types());
3238     }
3239
3240     expected = 1;
3241     ASSERT_EQ(expected, cache->fallback_namespaces_.size());
3242     EXPECT_TRUE(cache->fallback_namespaces_[0] ==
3243                     AppCacheNamespace(
3244                         APPCACHE_FALLBACK_NAMESPACE,
3245                         MockHttpServer::GetMockUrl("files/fallback1"),
3246                         MockHttpServer::GetMockUrl("files/fallback1a"),
3247                         false));
3248
3249     EXPECT_TRUE(cache->online_whitelist_namespaces_.empty());
3250     EXPECT_TRUE(cache->online_whitelist_all_);
3251
3252     EXPECT_TRUE(cache->update_time_ > base::Time());
3253   }
3254
3255   void VerifyManifestMergedTypes(AppCache* cache) {
3256     size_t expected = 2;
3257     EXPECT_EQ(expected, cache->entries().size());
3258     AppCacheEntry* entry = cache->GetEntry(
3259         MockHttpServer::GetMockUrl("files/manifest-merged-types"));
3260     ASSERT_TRUE(entry);
3261     EXPECT_EQ(AppCacheEntry::EXPLICIT | AppCacheEntry::MANIFEST,
3262               entry->types());
3263     entry = cache->GetEntry(MockHttpServer::GetMockUrl("files/explicit1"));
3264     ASSERT_TRUE(entry);
3265     EXPECT_EQ(AppCacheEntry::EXPLICIT | AppCacheEntry::FALLBACK |
3266         AppCacheEntry::MASTER, entry->types());
3267
3268     expected = 1;
3269     ASSERT_EQ(expected, cache->fallback_namespaces_.size());
3270     EXPECT_TRUE(cache->fallback_namespaces_[0] ==
3271                     AppCacheNamespace(
3272                         APPCACHE_FALLBACK_NAMESPACE,
3273                         MockHttpServer::GetMockUrl("files/fallback1"),
3274                         MockHttpServer::GetMockUrl("files/explicit1"),
3275                         false));
3276
3277     EXPECT_EQ(expected, cache->online_whitelist_namespaces_.size());
3278     EXPECT_TRUE(cache->online_whitelist_namespaces_[0] ==
3279                     AppCacheNamespace(
3280                         APPCACHE_NETWORK_NAMESPACE,
3281                         MockHttpServer::GetMockUrl("files/online1"),
3282                         GURL(), false));
3283     EXPECT_FALSE(cache->online_whitelist_all_);
3284
3285     EXPECT_TRUE(cache->update_time_ > base::Time());
3286   }
3287
3288   void VerifyEmptyManifest(AppCache* cache) {
3289     const char* kManifestPath = tested_manifest_path_override_ ?
3290         tested_manifest_path_override_ :
3291         "files/empty-manifest";
3292     size_t expected = 1;
3293     EXPECT_EQ(expected, cache->entries().size());
3294     AppCacheEntry* entry = cache->GetEntry(
3295         MockHttpServer::GetMockUrl(kManifestPath));
3296     ASSERT_TRUE(entry);
3297     EXPECT_EQ(AppCacheEntry::MANIFEST, entry->types());
3298
3299     EXPECT_TRUE(cache->fallback_namespaces_.empty());
3300     EXPECT_TRUE(cache->online_whitelist_namespaces_.empty());
3301     EXPECT_FALSE(cache->online_whitelist_all_);
3302
3303     EXPECT_TRUE(cache->update_time_ > base::Time());
3304   }
3305
3306   void VerifyEmptyFileManifest(AppCache* cache) {
3307     EXPECT_EQ(size_t(2), cache->entries().size());
3308     AppCacheEntry* entry = cache->GetEntry(
3309         MockHttpServer::GetMockUrl("files/empty-file-manifest"));
3310     ASSERT_TRUE(entry);
3311     EXPECT_EQ(AppCacheEntry::MANIFEST, entry->types());
3312
3313     entry = cache->GetEntry(
3314         MockHttpServer::GetMockUrl("files/empty1"));
3315     ASSERT_TRUE(entry);
3316     EXPECT_EQ(AppCacheEntry::EXPLICIT, entry->types());
3317     EXPECT_TRUE(entry->has_response_id());
3318
3319     EXPECT_TRUE(cache->fallback_namespaces_.empty());
3320     EXPECT_TRUE(cache->online_whitelist_namespaces_.empty());
3321     EXPECT_FALSE(cache->online_whitelist_all_);
3322
3323     EXPECT_TRUE(cache->update_time_ > base::Time());
3324   }
3325
3326   void VerifyMasterEntryNoUpdate(AppCache* cache) {
3327     EXPECT_EQ(size_t(3), cache->entries().size());
3328     AppCacheEntry* entry = cache->GetEntry(
3329         MockHttpServer::GetMockUrl("files/notmodified"));
3330     ASSERT_TRUE(entry);
3331     EXPECT_EQ(AppCacheEntry::MANIFEST, entry->types());
3332
3333     entry = cache->GetEntry(
3334         MockHttpServer::GetMockUrl("files/explicit1"));
3335     ASSERT_TRUE(entry);
3336     EXPECT_EQ(AppCacheEntry::MASTER, entry->types());
3337     EXPECT_TRUE(entry->has_response_id());
3338
3339     entry = cache->GetEntry(
3340         MockHttpServer::GetMockUrl("files/explicit2"));
3341     ASSERT_TRUE(entry);
3342     EXPECT_EQ(AppCacheEntry::EXPLICIT | AppCacheEntry::MASTER, entry->types());
3343     EXPECT_TRUE(entry->has_response_id());
3344
3345     EXPECT_TRUE(cache->fallback_namespaces_.empty());
3346     EXPECT_TRUE(cache->online_whitelist_namespaces_.empty());
3347     EXPECT_FALSE(cache->online_whitelist_all_);
3348
3349     EXPECT_TRUE(cache->update_time_ > base::Time());
3350   }
3351
3352   void VerifyManifestWithIntercept(AppCache* cache) {
3353     EXPECT_EQ(2u, cache->entries().size());
3354     const char* kManifestPath = "files/manifest-with-intercept";
3355     AppCacheEntry* entry =
3356         cache->GetEntry(MockHttpServer::GetMockUrl(kManifestPath));
3357     ASSERT_TRUE(entry);
3358     EXPECT_EQ(AppCacheEntry::MANIFEST, entry->types());
3359     entry = cache->GetEntry(MockHttpServer::GetMockUrl("files/intercept1a"));
3360     ASSERT_TRUE(entry);
3361     EXPECT_TRUE(entry->IsIntercept());
3362     EXPECT_TRUE(cache->online_whitelist_namespaces_.empty());
3363     EXPECT_FALSE(cache->online_whitelist_all_);
3364     EXPECT_TRUE(cache->update_time_ > base::Time());
3365   }
3366
3367  private:
3368   // Various manifest files used in this test.
3369   enum TestedManifest {
3370     NONE,
3371     MANIFEST1,
3372     MANIFEST_MERGED_TYPES,
3373     EMPTY_MANIFEST,
3374     EMPTY_FILE_MANIFEST,
3375     PENDING_MASTER_NO_UPDATE,
3376     MANIFEST_WITH_INTERCEPT
3377   };
3378
3379   scoped_ptr<IOThread> io_thread_;
3380
3381   scoped_ptr<MockAppCacheService> service_;
3382   scoped_refptr<AppCacheGroup> group_;
3383   scoped_refptr<AppCache> protect_newest_cache_;
3384   scoped_ptr<base::WaitableEvent> event_;
3385
3386   scoped_ptr<AppCacheResponseWriter> response_writer_;
3387
3388   // Hosts used by an async test that need to live until update job finishes.
3389   // Otherwise, test can put host on the stack instead of here.
3390   std::vector<AppCacheHost*> hosts_;
3391
3392   // Response infos used by an async test that need to live until update job
3393   // finishes.
3394   std::vector<scoped_refptr<AppCacheResponseInfo> > response_infos_;
3395
3396   // Flag indicating if test cares to verify the update after update finishes.
3397   bool do_checks_after_update_finished_;
3398   bool expect_group_obsolete_;
3399   bool expect_group_has_cache_;
3400   bool expect_group_is_being_deleted_;
3401   AppCache* expect_old_cache_;
3402   AppCache* expect_newest_cache_;
3403   bool expect_non_null_update_time_;
3404   std::vector<MockFrontend*> frontends_;  // to check expected events
3405   TestedManifest tested_manifest_;
3406   const char* tested_manifest_path_override_;
3407   AppCache::EntryMap expect_extra_entries_;
3408   std::map<GURL, int64> expect_response_ids_;
3409 };
3410
3411 TEST_F(AppCacheUpdateJobTest, AlreadyChecking) {
3412   MockAppCacheService service;
3413   scoped_refptr<AppCacheGroup> group(
3414       new AppCacheGroup(service.storage(), GURL("http://manifesturl.com"),
3415                         service.storage()->NewGroupId()));
3416
3417   AppCacheUpdateJob update(&service, group.get());
3418
3419   // Pretend group is in checking state.
3420   group->update_job_ = &update;
3421   group->update_status_ = AppCacheGroup::CHECKING;
3422
3423   update.StartUpdate(NULL, GURL());
3424   EXPECT_EQ(AppCacheGroup::CHECKING, group->update_status());
3425
3426   MockFrontend mock_frontend;
3427   AppCacheHost host(1, &mock_frontend, &service);
3428   update.StartUpdate(&host, GURL());
3429
3430   MockFrontend::RaisedEvents events = mock_frontend.raised_events_;
3431   size_t expected = 1;
3432   EXPECT_EQ(expected, events.size());
3433   EXPECT_EQ(expected, events[0].first.size());
3434   EXPECT_EQ(host.host_id(), events[0].first[0]);
3435   EXPECT_EQ(APPCACHE_CHECKING_EVENT, events[0].second);
3436   EXPECT_EQ(AppCacheGroup::CHECKING, group->update_status());
3437 }
3438
3439 TEST_F(AppCacheUpdateJobTest, AlreadyDownloading) {
3440   MockAppCacheService service;
3441   scoped_refptr<AppCacheGroup> group(
3442       new AppCacheGroup(service.storage(), GURL("http://manifesturl.com"),
3443                         service.storage()->NewGroupId()));
3444
3445   AppCacheUpdateJob update(&service, group.get());
3446
3447   // Pretend group is in downloading state.
3448   group->update_job_ = &update;
3449   group->update_status_ = AppCacheGroup::DOWNLOADING;
3450
3451   update.StartUpdate(NULL, GURL());
3452   EXPECT_EQ(AppCacheGroup::DOWNLOADING, group->update_status());
3453
3454   MockFrontend mock_frontend;
3455   AppCacheHost host(1, &mock_frontend, &service);
3456   update.StartUpdate(&host, GURL());
3457
3458   MockFrontend::RaisedEvents events = mock_frontend.raised_events_;
3459   size_t expected = 2;
3460   EXPECT_EQ(expected, events.size());
3461   expected = 1;
3462   EXPECT_EQ(expected, events[0].first.size());
3463   EXPECT_EQ(host.host_id(), events[0].first[0]);
3464   EXPECT_EQ(APPCACHE_CHECKING_EVENT, events[0].second);
3465
3466   EXPECT_EQ(expected, events[1].first.size());
3467   EXPECT_EQ(host.host_id(), events[1].first[0]);
3468   EXPECT_EQ(APPCACHE_DOWNLOADING_EVENT, events[1].second);
3469
3470   EXPECT_EQ(AppCacheGroup::DOWNLOADING, group->update_status());
3471 }
3472
3473 TEST_F(AppCacheUpdateJobTest, StartCacheAttempt) {
3474   RunTestOnIOThread(&AppCacheUpdateJobTest::StartCacheAttemptTest);
3475 }
3476
3477 TEST_F(AppCacheUpdateJobTest, StartUpgradeAttempt) {
3478   RunTestOnIOThread(&AppCacheUpdateJobTest::StartUpgradeAttemptTest);
3479 }
3480
3481 TEST_F(AppCacheUpdateJobTest, CacheAttemptFetchManifestFail) {
3482   RunTestOnIOThread(&AppCacheUpdateJobTest::CacheAttemptFetchManifestFailTest);
3483 }
3484
3485 TEST_F(AppCacheUpdateJobTest, UpgradeFetchManifestFail) {
3486   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeFetchManifestFailTest);
3487 }
3488
3489 TEST_F(AppCacheUpdateJobTest, ManifestRedirect) {
3490   RunTestOnIOThread(&AppCacheUpdateJobTest::ManifestRedirectTest);
3491 }
3492
3493 TEST_F(AppCacheUpdateJobTest, ManifestMissingMimeTypeTest) {
3494   RunTestOnIOThread(&AppCacheUpdateJobTest::ManifestMissingMimeTypeTest);
3495 }
3496
3497 TEST_F(AppCacheUpdateJobTest, ManifestNotFound) {
3498   RunTestOnIOThread(&AppCacheUpdateJobTest::ManifestNotFoundTest);
3499 }
3500
3501 TEST_F(AppCacheUpdateJobTest, ManifestGone) {
3502   RunTestOnIOThread(&AppCacheUpdateJobTest::ManifestGoneTest);
3503 }
3504
3505 TEST_F(AppCacheUpdateJobTest, CacheAttemptNotModified) {
3506   RunTestOnIOThread(&AppCacheUpdateJobTest::CacheAttemptNotModifiedTest);
3507 }
3508
3509 TEST_F(AppCacheUpdateJobTest, UpgradeNotModified) {
3510   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeNotModifiedTest);
3511 }
3512
3513 TEST_F(AppCacheUpdateJobTest, UpgradeManifestDataUnchanged) {
3514   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeManifestDataUnchangedTest);
3515 }
3516
3517 TEST_F(AppCacheUpdateJobTest, Bug95101Test) {
3518   RunTestOnIOThread(&AppCacheUpdateJobTest::Bug95101Test);
3519 }
3520
3521 TEST_F(AppCacheUpdateJobTest, BasicCacheAttemptSuccess) {
3522   RunTestOnIOThread(&AppCacheUpdateJobTest::BasicCacheAttemptSuccessTest);
3523 }
3524
3525 TEST_F(AppCacheUpdateJobTest, DownloadInterceptEntriesTest) {
3526   RunTestOnIOThread(&AppCacheUpdateJobTest::DownloadInterceptEntriesTest);
3527 }
3528
3529 TEST_F(AppCacheUpdateJobTest, BasicUpgradeSuccess) {
3530   RunTestOnIOThread(&AppCacheUpdateJobTest::BasicUpgradeSuccessTest);
3531 }
3532
3533 TEST_F(AppCacheUpdateJobTest, UpgradeLoadFromNewestCache) {
3534   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeLoadFromNewestCacheTest);
3535 }
3536
3537 TEST_F(AppCacheUpdateJobTest, UpgradeNoLoadFromNewestCache) {
3538   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeNoLoadFromNewestCacheTest);
3539 }
3540
3541 TEST_F(AppCacheUpdateJobTest, UpgradeLoadFromNewestCacheVaryHeader) {
3542   RunTestOnIOThread(
3543       &AppCacheUpdateJobTest::UpgradeLoadFromNewestCacheVaryHeaderTest);
3544 }
3545
3546 TEST_F(AppCacheUpdateJobTest, UpgradeSuccessMergedTypes) {
3547   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeSuccessMergedTypesTest);
3548 }
3549
3550 TEST_F(AppCacheUpdateJobTest, CacheAttemptFailUrlFetch) {
3551   RunTestOnIOThread(&AppCacheUpdateJobTest::CacheAttemptFailUrlFetchTest);
3552 }
3553
3554 TEST_F(AppCacheUpdateJobTest, UpgradeFailUrlFetch) {
3555   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeFailUrlFetchTest);
3556 }
3557
3558 TEST_F(AppCacheUpdateJobTest, UpgradeFailMasterUrlFetch) {
3559   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeFailMasterUrlFetchTest);
3560 }
3561
3562 TEST_F(AppCacheUpdateJobTest, EmptyManifest) {
3563   RunTestOnIOThread(&AppCacheUpdateJobTest::EmptyManifestTest);
3564 }
3565
3566 TEST_F(AppCacheUpdateJobTest, EmptyFile) {
3567   RunTestOnIOThread(&AppCacheUpdateJobTest::EmptyFileTest);
3568 }
3569
3570 TEST_F(AppCacheUpdateJobTest, RetryRequest) {
3571   RunTestOnIOThread(&AppCacheUpdateJobTest::RetryRequestTest);
3572 }
3573
3574 TEST_F(AppCacheUpdateJobTest, RetryNoRetryAfter) {
3575   RunTestOnIOThread(&AppCacheUpdateJobTest::RetryNoRetryAfterTest);
3576 }
3577
3578 TEST_F(AppCacheUpdateJobTest, RetryNonzeroRetryAfter) {
3579   RunTestOnIOThread(&AppCacheUpdateJobTest::RetryNonzeroRetryAfterTest);
3580 }
3581
3582 TEST_F(AppCacheUpdateJobTest, RetrySuccess) {
3583   RunTestOnIOThread(&AppCacheUpdateJobTest::RetrySuccessTest);
3584 }
3585
3586 TEST_F(AppCacheUpdateJobTest, RetryUrl) {
3587   RunTestOnIOThread(&AppCacheUpdateJobTest::RetryUrlTest);
3588 }
3589
3590 TEST_F(AppCacheUpdateJobTest, FailStoreNewestCache) {
3591   RunTestOnIOThread(&AppCacheUpdateJobTest::FailStoreNewestCacheTest);
3592 }
3593
3594 TEST_F(AppCacheUpdateJobTest, MasterEntryFailStoreNewestCacheTest) {
3595   RunTestOnIOThread(
3596       &AppCacheUpdateJobTest::MasterEntryFailStoreNewestCacheTest);
3597 }
3598
3599 TEST_F(AppCacheUpdateJobTest, UpgradeFailStoreNewestCache) {
3600   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeFailStoreNewestCacheTest);
3601 }
3602
3603 TEST_F(AppCacheUpdateJobTest, UpgradeFailMakeGroupObsolete) {
3604   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeFailMakeGroupObsoleteTest);
3605 }
3606
3607 TEST_F(AppCacheUpdateJobTest, MasterEntryFetchManifestFail) {
3608   RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntryFetchManifestFailTest);
3609 }
3610
3611 TEST_F(AppCacheUpdateJobTest, MasterEntryBadManifest) {
3612   RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntryBadManifestTest);
3613 }
3614
3615 TEST_F(AppCacheUpdateJobTest, MasterEntryManifestNotFound) {
3616   RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntryManifestNotFoundTest);
3617 }
3618
3619 TEST_F(AppCacheUpdateJobTest, MasterEntryFailUrlFetch) {
3620   RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntryFailUrlFetchTest);
3621 }
3622
3623 TEST_F(AppCacheUpdateJobTest, MasterEntryAllFail) {
3624   RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntryAllFailTest);
3625 }
3626
3627 TEST_F(AppCacheUpdateJobTest, UpgradeMasterEntryAllFail) {
3628   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeMasterEntryAllFailTest);
3629 }
3630
3631 TEST_F(AppCacheUpdateJobTest, MasterEntrySomeFail) {
3632   RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntrySomeFailTest);
3633 }
3634
3635 TEST_F(AppCacheUpdateJobTest, UpgradeMasterEntrySomeFail) {
3636   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeMasterEntrySomeFailTest);
3637 }
3638
3639 TEST_F(AppCacheUpdateJobTest, MasterEntryNoUpdate) {
3640   RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntryNoUpdateTest);
3641 }
3642
3643 TEST_F(AppCacheUpdateJobTest, StartUpdateMidCacheAttempt) {
3644   RunTestOnIOThread(&AppCacheUpdateJobTest::StartUpdateMidCacheAttemptTest);
3645 }
3646
3647 TEST_F(AppCacheUpdateJobTest, StartUpdateMidNoUpdate) {
3648   RunTestOnIOThread(&AppCacheUpdateJobTest::StartUpdateMidNoUpdateTest);
3649 }
3650
3651 TEST_F(AppCacheUpdateJobTest, StartUpdateMidDownload) {
3652   RunTestOnIOThread(&AppCacheUpdateJobTest::StartUpdateMidDownloadTest);
3653 }
3654
3655 TEST_F(AppCacheUpdateJobTest, QueueMasterEntry) {
3656   RunTestOnIOThread(&AppCacheUpdateJobTest::QueueMasterEntryTest);
3657 }
3658
3659 TEST_F(AppCacheUpdateJobTest, IfModifiedSince) {
3660   RunTestOnIOThread(&AppCacheUpdateJobTest::IfModifiedSinceTest);
3661 }
3662
3663 TEST_F(AppCacheUpdateJobTest, IfModifiedSinceUpgrade) {
3664   RunTestOnIOThread(&AppCacheUpdateJobTest::IfModifiedSinceUpgradeTest);
3665 }
3666
3667 TEST_F(AppCacheUpdateJobTest, IfNoneMatchUpgrade) {
3668   RunTestOnIOThread(&AppCacheUpdateJobTest::IfNoneMatchUpgradeTest);
3669 }
3670
3671 TEST_F(AppCacheUpdateJobTest, IfNoneMatchRefetch) {
3672   RunTestOnIOThread(&AppCacheUpdateJobTest::IfNoneMatchRefetchTest);
3673 }
3674
3675 TEST_F(AppCacheUpdateJobTest, MultipleHeadersRefetch) {
3676   RunTestOnIOThread(&AppCacheUpdateJobTest::MultipleHeadersRefetchTest);
3677 }
3678
3679 TEST_F(AppCacheUpdateJobTest, CrossOriginHttpsSuccess) {
3680   RunTestOnIOThread(&AppCacheUpdateJobTest::CrossOriginHttpsSuccessTest);
3681 }
3682
3683 TEST_F(AppCacheUpdateJobTest, CrossOriginHttpsDenied) {
3684   RunTestOnIOThread(&AppCacheUpdateJobTest::CrossOriginHttpsDeniedTest);
3685 }
3686
3687 }  // namespace content