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