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