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