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