summaryrefslogtreecommitdiffstats
path: root/webkit/appcache
diff options
context:
space:
mode:
authorjennb@chromium.org <jennb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-08 17:46:21 +0000
committerjennb@chromium.org <jennb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-08 17:46:21 +0000
commitb75a52794712b69a59960901f4761aef748e38bf (patch)
tree3dd9dad03dba7b0dc8e60cdfd309dcd8f0d009d8 /webkit/appcache
parentd0767cb54b2b5ee4d9cf00b3ee0fa585826b4036 (diff)
downloadchromium_src-b75a52794712b69a59960901f4761aef748e38bf.zip
chromium_src-b75a52794712b69a59960901f4761aef748e38bf.tar.gz
chromium_src-b75a52794712b69a59960901f4761aef748e38bf.tar.bz2
Make appcache update job retry 503 requests with retry-after of 0.
TEST=test retry logic BUG=none Review URL: http://codereview.chromium.org/264002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@28406 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/appcache')
-rw-r--r--webkit/appcache/appcache_update_job.cc67
-rw-r--r--webkit/appcache/appcache_update_job.h4
-rw-r--r--webkit/appcache/appcache_update_job_unittest.cc302
3 files changed, 353 insertions, 20 deletions
diff --git a/webkit/appcache/appcache_update_job.cc b/webkit/appcache/appcache_update_job.cc
index 146c8f2..0834039 100644
--- a/webkit/appcache/appcache_update_job.cc
+++ b/webkit/appcache/appcache_update_job.cc
@@ -6,6 +6,7 @@
#include "base/compiler_specific.h"
#include "base/message_loop.h"
+#include "base/string_util.h"
#include "net/base/io_buffer.h"
#include "net/base/load_flags.h"
#include "webkit/appcache/appcache_group.h"
@@ -15,6 +16,7 @@ namespace appcache {
static const int kBufferSize = 4096;
static const size_t kMaxConcurrentUrlFetches = 2;
+static const int kMax503Retries = 3;
// Extra info associated with requests for use during response processing.
// This info is deleted when the URLRequest is deleted.
@@ -27,12 +29,15 @@ struct UpdateJobInfo : public URLRequest::UserData {
explicit UpdateJobInfo(RequestType request_type)
: type(request_type),
- buffer(new net::IOBuffer(kBufferSize)) {
+ buffer(new net::IOBuffer(kBufferSize)),
+ retry_503_attempts(0) {
}
RequestType type;
scoped_refptr<net::IOBuffer> buffer;
// TODO(jennb): need storage info to stream response data to storage
+
+ int retry_503_attempts;
};
// Helper class for collecting hosts per frontend when sending notifications
@@ -219,7 +224,13 @@ void AppCacheUpdateJob::OnReceivedRedirect(URLRequest* request,
}
void AppCacheUpdateJob::OnResponseCompleted(URLRequest* request) {
- // TODO(jennb): think about retrying for 503s where retry-after is 0
+ // Retry for 503s where retry-after is 0.
+ if (request->status().is_success() &&
+ request->GetResponseCode() == 503 &&
+ RetryRequest(request)) {
+ return;
+ }
+
UpdateJobInfo* info =
static_cast<UpdateJobInfo*>(request->GetUserData(this));
switch (info->type) {
@@ -239,12 +250,50 @@ void AppCacheUpdateJob::OnResponseCompleted(URLRequest* request) {
delete request;
}
+bool AppCacheUpdateJob::RetryRequest(URLRequest* request) {
+ UpdateJobInfo* info =
+ static_cast<UpdateJobInfo*>(request->GetUserData(this));
+ if (info->retry_503_attempts >= kMax503Retries) {
+ return false;
+ }
+
+ if (!request->response_headers()->HasHeaderValue("retry-after", "0"))
+ return false;
+
+ const GURL& url = request->original_url();
+ URLRequest* retry = new URLRequest(url, this);
+ UpdateJobInfo* retry_info = new UpdateJobInfo(info->type);
+ retry_info->retry_503_attempts = info->retry_503_attempts + 1;
+ retry->SetUserData(this, retry_info);
+ retry->set_context(request->context());
+ retry->set_load_flags(request->load_flags());
+
+ switch (info->type) {
+ case UpdateJobInfo::MANIFEST_FETCH:
+ case UpdateJobInfo::MANIFEST_REFETCH:
+ manifest_url_request_ = retry;
+ manifest_data_.clear();
+ break;
+ case UpdateJobInfo::URL_FETCH:
+ pending_url_fetches_.erase(url);
+ pending_url_fetches_.insert(PendingUrlFetches::value_type(url, retry));
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ retry->Start();
+
+ delete request;
+ return true;
+}
+
void AppCacheUpdateJob::HandleManifestFetchCompleted(URLRequest* request) {
DCHECK(internal_state_ == FETCH_MANIFEST);
manifest_url_request_ = NULL;
if (!request->status().is_success()) {
- LOG(ERROR) << "Request non-success, status: " << request->status().status()
+ LOG(INFO) << "Request non-success, status: " << request->status().status()
<< " os_error: " << request->status().os_error();
internal_state_ = CACHE_FAILURE;
MaybeCompleteUpdate(); // if not done, run async cache failure steps
@@ -255,7 +304,7 @@ void AppCacheUpdateJob::HandleManifestFetchCompleted(URLRequest* request) {
std::string mime_type;
request->GetMimeType(&mime_type);
- if (response_code == 200 && mime_type == kManifestMimeType) {
+ if ((response_code / 100 == 2) && mime_type == kManifestMimeType) {
if (update_type_ == UPGRADE_ATTEMPT)
CheckIfManifestChanged(); // continues asynchronously
else
@@ -268,7 +317,7 @@ void AppCacheUpdateJob::HandleManifestFetchCompleted(URLRequest* request) {
NotifyAllPendingMasterHosts(ERROR_EVENT);
DeleteSoon();
} else {
- LOG(ERROR) << "Cache failure, response code: " << response_code;
+ LOG(INFO) << "Cache failure, response code: " << response_code;
internal_state_ = CACHE_FAILURE;
MaybeCompleteUpdate(); // if not done, run async cache failure steps
}
@@ -287,7 +336,7 @@ void AppCacheUpdateJob::ContinueHandleManifestFetchCompleted(bool changed) {
Manifest manifest;
if (!ParseManifest(manifest_url_, manifest_data_.data(),
manifest_data_.length(), manifest)) {
- LOG(ERROR) << "Failed to parse manifest: " << manifest_url_;
+ LOG(INFO) << "Failed to parse manifest: " << manifest_url_;
internal_state_ = CACHE_FAILURE;
MaybeCompleteUpdate(); // if not done, run async cache failure steps
return;
@@ -327,7 +376,7 @@ void AppCacheUpdateJob::HandleUrlFetchCompleted(URLRequest* request) {
int response_code = request->GetResponseCode();
AppCacheEntry& entry = url_file_list_.find(url)->second;
- if (request->status().is_success() && response_code == 200) {
+ if (request->status().is_success() && (response_code / 100 == 2)) {
// TODO(jennb): associate storage with the new entry
inprogress_cache_->AddEntry(url, entry);
@@ -337,7 +386,7 @@ void AppCacheUpdateJob::HandleUrlFetchCompleted(URLRequest* request) {
// whose value doesn't match the manifest url of the application cache
// being processed, mark the entry as being foreign.
} else {
- LOG(ERROR) << "Request status: " << request->status().status()
+ LOG(INFO) << "Request status: " << request->status().status()
<< " os_error: " << request->status().os_error()
<< " response code: " << response_code;
@@ -403,7 +452,7 @@ void AppCacheUpdateJob::HandleManifestRefetchCompleted(URLRequest* request) {
DeleteSoon();
// TODO(jennb): end of part that needs to be made async.
} else {
- LOG(ERROR) << "Request status: " << request->status().status()
+ LOG(INFO) << "Request status: " << request->status().status()
<< " os_error: " << request->status().os_error()
<< " response code: " << response_code;
ScheduleUpdateRetry(kRerunDelayMs);
diff --git a/webkit/appcache/appcache_update_job.h b/webkit/appcache/appcache_update_job.h
index 160e27e..0c19196 100644
--- a/webkit/appcache/appcache_update_job.h
+++ b/webkit/appcache/appcache_update_job.h
@@ -74,6 +74,10 @@ class AppCacheUpdateJob : public URLRequest::Delegate {
void OnResponseCompleted(URLRequest* request);
+ // Retries a 503 request with retry-after header of 0.
+ // Returns true if request should be retried and deletes original request.
+ bool RetryRequest(URLRequest* request);
+
void ReadResponseData(URLRequest* request);
// Returns false if response data is processed asynchronously, in which
diff --git a/webkit/appcache/appcache_update_job_unittest.cc b/webkit/appcache/appcache_update_job_unittest.cc
index f08625d..00fc819 100644
--- a/webkit/appcache/appcache_update_job_unittest.cc
+++ b/webkit/appcache/appcache_update_job_unittest.cc
@@ -75,6 +75,107 @@ static URLRequestJob* RedirectFactory(URLRequest* request,
true);
}
+// Helper class to simulate a URL that returns retry or success.
+class RetryRequestTestJob : public URLRequestTestJob {
+ public:
+ enum RetryHeader {
+ NO_RETRY_AFTER,
+ NONZERO_RETRY_AFTER,
+ RETRY_AFTER_0,
+ };
+
+ static const GURL kRetryUrl;
+
+ // Call this at the start of each retry test.
+ static void Initialize(int num_retry_responses, RetryHeader header,
+ int expected_requests) {
+ num_requests_ = 0;
+ num_retries_ = num_retry_responses;
+ retry_after_ = header;
+ expected_requests_ = expected_requests;
+ }
+
+ // Verifies results at end of test and resets counters.
+ static void Verify() {
+ EXPECT_EQ(expected_requests_, num_requests_);
+ num_requests_ = 0;
+ expected_requests_ = 0;
+ }
+
+ static URLRequestJob* RetryFactory(URLRequest* request,
+ const std::string& scheme) {
+ ++num_requests_;
+ if (num_retries_ > 0 && request->original_url() == kRetryUrl) {
+ --num_retries_;
+ return new RetryRequestTestJob(
+ request, RetryRequestTestJob::retry_headers(), 503);
+ } else {
+ return new RetryRequestTestJob(
+ request, RetryRequestTestJob::manifest_headers(), 200);
+ }
+ }
+
+ virtual int GetResponseCode() const { return response_code_; }
+
+ private:
+ static std::string retry_headers() {
+ const char no_retry_after[] =
+ "HTTP/1.1 503 BOO HOO\0"
+ "\0";
+ const char nonzero[] =
+ "HTTP/1.1 503 BOO HOO\0"
+ "Retry-After: 60\0"
+ "\0";
+ const char retry_after_0[] =
+ "HTTP/1.1 503 BOO HOO\0"
+ "Retry-After: 0\0"
+ "\0";
+
+ switch (retry_after_) {
+ case NO_RETRY_AFTER:
+ return std::string(no_retry_after, arraysize(no_retry_after));
+ case NONZERO_RETRY_AFTER:
+ return std::string(nonzero, arraysize(nonzero));
+ case RETRY_AFTER_0:
+ default:
+ return std::string(retry_after_0, arraysize(retry_after_0));
+ }
+ }
+
+ static std::string manifest_headers() {
+ const char headers[] =
+ "HTTP/1.1 200 OK\0"
+ "Content-type: text/cache-manifest\0"
+ "\0";
+ return std::string(headers, arraysize(headers));
+ }
+
+ static std::string data() {
+ return std::string("CACHE MANIFEST\r"
+ "http://retry\r"); // must be same as kRetryUrl
+ }
+
+ explicit RetryRequestTestJob(URLRequest* request, const std::string& headers,
+ int response_code)
+ : URLRequestTestJob(request, headers, data(), true),
+ response_code_(response_code) {
+ }
+
+ int response_code_;
+
+ static int num_requests_;
+ static int num_retries_;
+ static RetryHeader retry_after_;
+ static int expected_requests_;
+};
+
+// static
+const GURL RetryRequestTestJob::kRetryUrl("http://retry");
+int RetryRequestTestJob::num_requests_ = 0;
+int RetryRequestTestJob::num_retries_;
+RetryRequestTestJob::RetryHeader RetryRequestTestJob::retry_after_;
+int RetryRequestTestJob::expected_requests_ = 0;
+
class AppCacheUpdateJobTest : public testing::Test,
public AppCacheGroup::Observer {
public:
@@ -85,11 +186,13 @@ class AppCacheUpdateJobTest : public testing::Test,
expect_group_has_cache_(false),
expect_old_cache_(NULL),
expect_newest_cache_(NULL),
- tested_manifest_(NONE) {
+ tested_manifest_(NONE),
+ registered_factory_(false),
+ old_factory_(NULL) {
}
static void SetUpTestCase() {
- io_thread_.reset(new base::Thread("AppCacheUpdateJob IO test thread"));
+ io_thread_.reset(new base::Thread("AppCacheUpdateJob IO test thread"));
base::Thread::Options options(MessageLoop::TYPE_IO, 0);
io_thread_->StartWithOptions(options);
@@ -276,7 +379,9 @@ class AppCacheUpdateJobTest : public testing::Test,
void ManifestRedirectTest() {
ASSERT_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type());
- URLRequest::RegisterProtocolFactory("http", RedirectFactory);
+ old_factory_ =
+ URLRequest::RegisterProtocolFactory("http", RedirectFactory);
+ registered_factory_ = true;
MakeService();
group_ = new AppCacheGroup(service_.get(), GURL("http://testme"));
@@ -362,7 +467,7 @@ class AppCacheUpdateJobTest : public testing::Test,
MakeService();
group_ = new AppCacheGroup(
- service_.get(), http_server_->TestServerPage("files/gone"));
+ service_.get(), http_server_->TestServerPage("files/gone"));
AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_);
group_->update_job_ = update;
@@ -386,7 +491,7 @@ class AppCacheUpdateJobTest : public testing::Test,
MakeService();
group_ = new AppCacheGroup(
- service_.get(), http_server_->TestServerPage("files/notmodified"));
+ service_.get(), http_server_->TestServerPage("files/notmodified"));
AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_);
group_->update_job_ = update;
@@ -483,7 +588,7 @@ class AppCacheUpdateJobTest : public testing::Test,
MakeService();
group_ = new AppCacheGroup(
- service_.get(), http_server_->TestServerPage("files/manifest1"));
+ service_.get(), http_server_->TestServerPage("files/manifest1"));
AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_);
group_->update_job_ = update;
@@ -604,8 +709,8 @@ class AppCacheUpdateJobTest : public testing::Test,
ASSERT_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type());
MakeService();
- group_ = new AppCacheGroup(
- service_.get(), http_server_->TestServerPage("files/manifest-with-404"));
+ group_ = new AppCacheGroup(service_.get(),
+ http_server_->TestServerPage("files/manifest-with-404"));
AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_);
group_->update_job_ = update;
@@ -628,8 +733,8 @@ class AppCacheUpdateJobTest : public testing::Test,
ASSERT_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type());
MakeService();
- group_ = new AppCacheGroup(
- service_.get(), http_server_->TestServerPage("files/manifest-fb-404"));
+ group_ = new AppCacheGroup(service_.get(),
+ http_server_->TestServerPage("files/manifest-fb-404"));
AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_);
group_->update_job_ = update;
@@ -785,6 +890,155 @@ class AppCacheUpdateJobTest : public testing::Test,
WaitForUpdateToFinish();
}
+ void RetryRequestTest() {
+ ASSERT_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type());
+
+ // Set some large number of times to return retry.
+ // Expect 1 manifest fetch and 3 retries.
+ RetryRequestTestJob::Initialize(5, RetryRequestTestJob::RETRY_AFTER_0, 4);
+ old_factory_ = URLRequest::RegisterProtocolFactory(
+ "http", RetryRequestTestJob::RetryFactory);
+ registered_factory_ = true;
+
+ MakeService();
+ group_ = new AppCacheGroup(service_.get(), RetryRequestTestJob::kRetryUrl);
+ AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_);
+ group_->update_job_ = update;
+
+ MockFrontend* frontend = MakeMockFrontend();
+ AppCacheHost* host = MakeHost(1, frontend);
+ update->StartUpdate(host, GURL::EmptyGURL());
+ EXPECT_TRUE(update->manifest_url_request_ != NULL);
+
+ // Set up checks for when update job finishes.
+ do_checks_after_update_finished_ = true;
+ expect_group_obsolete_ = false;
+ expect_group_has_cache_ = false;
+ frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()),
+ CHECKING_EVENT);
+
+ WaitForUpdateToFinish();
+ }
+
+ void RetryNoRetryAfterTest() {
+ ASSERT_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type());
+
+ // Set some large number of times to return retry.
+ // Expect 1 manifest fetch and 0 retries.
+ RetryRequestTestJob::Initialize(5, RetryRequestTestJob::NO_RETRY_AFTER, 1);
+ old_factory_ = URLRequest::RegisterProtocolFactory(
+ "http", RetryRequestTestJob::RetryFactory);
+ registered_factory_ = true;
+
+ MakeService();
+ group_ = new AppCacheGroup(service_.get(), RetryRequestTestJob::kRetryUrl);
+ AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_);
+ group_->update_job_ = update;
+
+ MockFrontend* frontend = MakeMockFrontend();
+ AppCacheHost* host = MakeHost(1, frontend);
+ update->StartUpdate(host, GURL::EmptyGURL());
+ EXPECT_TRUE(update->manifest_url_request_ != NULL);
+
+ // Set up checks for when update job finishes.
+ do_checks_after_update_finished_ = true;
+ expect_group_obsolete_ = false;
+ expect_group_has_cache_ = false;
+ frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()),
+ CHECKING_EVENT);
+
+ WaitForUpdateToFinish();
+ }
+
+ void RetryNonzeroRetryAfterTest() {
+ ASSERT_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type());
+
+ // Set some large number of times to return retry.
+ // Expect 1 request and 0 retry attempts.
+ RetryRequestTestJob::Initialize(
+ 5, RetryRequestTestJob::NONZERO_RETRY_AFTER, 1);
+ old_factory_ = URLRequest::RegisterProtocolFactory(
+ "http", RetryRequestTestJob::RetryFactory);
+ registered_factory_ = true;
+
+ MakeService();
+ group_ = new AppCacheGroup(service_.get(), RetryRequestTestJob::kRetryUrl);
+ AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_);
+ group_->update_job_ = update;
+
+ MockFrontend* frontend = MakeMockFrontend();
+ AppCacheHost* host = MakeHost(1, frontend);
+ update->StartUpdate(host, GURL::EmptyGURL());
+ EXPECT_TRUE(update->manifest_url_request_ != NULL);
+
+ // Set up checks for when update job finishes.
+ do_checks_after_update_finished_ = true;
+ expect_group_obsolete_ = false;
+ expect_group_has_cache_ = false;
+ frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()),
+ CHECKING_EVENT);
+
+ WaitForUpdateToFinish();
+ }
+
+ void RetrySuccessTest() {
+ ASSERT_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type());
+
+ // Set 2 as the retry limit (does not exceed the max).
+ // Expect 1 manifest fetch, 2 retries, 1 url fetch, 1 manifest refetch.
+ RetryRequestTestJob::Initialize(2, RetryRequestTestJob::RETRY_AFTER_0, 5);
+ old_factory_ = URLRequest::RegisterProtocolFactory(
+ "http", RetryRequestTestJob::RetryFactory);
+ registered_factory_ = true;
+
+ MakeService();
+ group_ = new AppCacheGroup(service_.get(), RetryRequestTestJob::kRetryUrl);
+ AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_);
+ group_->update_job_ = update;
+
+ MockFrontend* frontend = MakeMockFrontend();
+ AppCacheHost* host = MakeHost(1, frontend);
+ update->StartUpdate(host, GURL::EmptyGURL());
+ EXPECT_TRUE(update->manifest_url_request_ != NULL);
+
+ // Set up checks for when update job finishes.
+ do_checks_after_update_finished_ = true;
+ expect_group_obsolete_ = false;
+ expect_group_has_cache_ = true;
+ frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()),
+ CHECKING_EVENT);
+
+ WaitForUpdateToFinish();
+ }
+
+ void RetryUrlTest() {
+ // Set 1 as the retry limit (does not exceed the max).
+ // Expect 1 manifest fetch, 1 url fetch, 1 url retry, 1 manifest refetch.
+ RetryRequestTestJob::Initialize(1, RetryRequestTestJob::RETRY_AFTER_0, 4);
+ old_factory_ = URLRequest::RegisterProtocolFactory(
+ "http", RetryRequestTestJob::RetryFactory);
+ registered_factory_ = true;
+
+ MakeService();
+ group_ = new AppCacheGroup(service_.get(), GURL("http://retryurl"));
+ AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_);
+ group_->update_job_ = update;
+
+ MockFrontend* frontend = MakeMockFrontend();
+ AppCacheHost* host = MakeHost(1, frontend);
+ update->StartUpdate(host, GURL::EmptyGURL());
+ EXPECT_TRUE(update->manifest_url_request_ != NULL);
+
+ // Set up checks for when update job finishes.
+ do_checks_after_update_finished_ = true;
+ expect_group_obsolete_ = false;
+ expect_group_has_cache_ = true;
+ frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()),
+ CHECKING_EVENT);
+
+ WaitForUpdateToFinish();
+ }
+
void WaitForUpdateToFinish() {
if (group_->update_status() == AppCacheGroup::IDLE)
UpdateFinished();
@@ -812,7 +1066,8 @@ class AppCacheUpdateJobTest : public testing::Test,
STLDeleteContainerPointers(hosts_.begin(), hosts_.end());
STLDeleteContainerPointers(frontends_.begin(), frontends_.end());
service_.reset(NULL);
- URLRequest::RegisterProtocolFactory("http", NULL);
+ if (registered_factory_)
+ URLRequest::RegisterProtocolFactory("http", old_factory_);
event_->Signal();
}
@@ -847,6 +1102,8 @@ class AppCacheUpdateJobTest : public testing::Test,
// Verifies conditions about the group and notifications after an update
// has finished. Cannot verify update job internals as update is deleted.
void VerifyExpectations() {
+ RetryRequestTestJob::Verify();
+
EXPECT_EQ(expect_group_obsolete_, group_->is_obsolete());
if (expect_group_has_cache_) {
@@ -1034,6 +1291,9 @@ class AppCacheUpdateJobTest : public testing::Test,
std::vector<MockFrontend*> frontends_; // to check expected events
TestedManifest tested_manifest_;
AppCache::EntryMap expect_extra_entries_;
+
+ bool registered_factory_;
+ URLRequest::ProtocolFactory* old_factory_;
};
// static
@@ -1172,4 +1432,24 @@ TEST_F(AppCacheUpdateJobTest, EmptyManifest) {
RunTestOnIOThread(&AppCacheUpdateJobTest::EmptyManifestTest);
}
+TEST_F(AppCacheUpdateJobTest, RetryRequest) {
+ RunTestOnIOThread(&AppCacheUpdateJobTest::RetryRequestTest);
+}
+
+TEST_F(AppCacheUpdateJobTest, RetryNoRetryAfter) {
+ RunTestOnIOThread(&AppCacheUpdateJobTest::RetryNoRetryAfterTest);
+}
+
+TEST_F(AppCacheUpdateJobTest, RetryNonzeroRetryAfter) {
+ RunTestOnIOThread(&AppCacheUpdateJobTest::RetryNonzeroRetryAfterTest);
+}
+
+TEST_F(AppCacheUpdateJobTest, RetrySuccess) {
+ RunTestOnIOThread(&AppCacheUpdateJobTest::RetrySuccessTest);
+}
+
+TEST_F(AppCacheUpdateJobTest, RetryUrl) {
+ RunTestOnIOThread(&AppCacheUpdateJobTest::RetryUrlTest);
+}
+
} // namespace appcache