summaryrefslogtreecommitdiffstats
path: root/webkit/appcache/appcache_update_job_unittest.cc
diff options
context:
space:
mode:
authorjennb@chromium.org <jennb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-22 18:22:23 +0000
committerjennb@chromium.org <jennb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-22 18:22:23 +0000
commitbdd42287e26666cb9230de0102045ccaa1e29207 (patch)
treefa5b66de3a049c67045e3cb5014b9d4d172efe17 /webkit/appcache/appcache_update_job_unittest.cc
parent1c5491c13d721e264432fe75e4030017b1ee10e8 (diff)
downloadchromium_src-bdd42287e26666cb9230de0102045ccaa1e29207.zip
chromium_src-bdd42287e26666cb9230de0102045ccaa1e29207.tar.gz
chromium_src-bdd42287e26666cb9230de0102045ccaa1e29207.tar.bz2
Make appcache update conditionally include If-Modified-Since and If-None-Match headers when fetching a manifest.
TEST=new tests added BUG=none Review URL: http://codereview.chromium.org/500152 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@35153 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/appcache/appcache_update_job_unittest.cc')
-rw-r--r--webkit/appcache/appcache_update_job_unittest.cc341
1 files changed, 340 insertions, 1 deletions
diff --git a/webkit/appcache/appcache_update_job_unittest.cc b/webkit/appcache/appcache_update_job_unittest.cc
index 72698e2..45898e8 100644
--- a/webkit/appcache/appcache_update_job_unittest.cc
+++ b/webkit/appcache/appcache_update_job_unittest.cc
@@ -131,7 +131,7 @@ class RetryRequestTestJob : public URLRequestTestJob {
}
static URLRequestJob* RetryFactory(URLRequest* request,
- const std::string& scheme) {
+ const std::string& scheme) {
++num_requests_;
if (num_retries_ > 0 && request->original_url() == kRetryUrl) {
--num_retries_;
@@ -206,6 +206,72 @@ int RetryRequestTestJob::num_retries_;
RetryRequestTestJob::RetryHeader RetryRequestTestJob::retry_after_;
int RetryRequestTestJob::expected_requests_ = 0;
+// Helper class to check for certain HTTP headers.
+class HttpHeadersRequestTestJob : public URLRequestTestJob {
+ public:
+ // Call this at the start of each HTTP header-related test.
+ static void Initialize(const std::string& expect_if_modified_since,
+ const std::string& expect_if_none_match) {
+ expect_if_modified_since_ = expect_if_modified_since;
+ expect_if_none_match_ = expect_if_none_match;
+ }
+
+ // Verifies results at end of test and resets class.
+ static void Verify() {
+ if (!expect_if_modified_since_.empty())
+ EXPECT_TRUE(saw_if_modified_since_);
+ if (!expect_if_none_match_.empty())
+ EXPECT_TRUE(saw_if_none_match_);
+
+ // Reset.
+ expect_if_modified_since_.clear();
+ saw_if_modified_since_ = false;
+ expect_if_none_match_.clear();
+ saw_if_none_match_ = false;
+ already_checked_ = false;
+ }
+
+ static URLRequestJob* IfModifiedSinceFactory(URLRequest* request,
+ const std::string& scheme) {
+ if (!already_checked_) {
+ already_checked_ = true; // only check once for a test
+ const std::string& extra_headers = request->extra_request_headers();
+ const std::string if_modified_since = "If-Modified-Since: ";
+ size_t pos = extra_headers.find(if_modified_since);
+ if (pos != std::string::npos) {
+ saw_if_modified_since_ = (0 == extra_headers.compare(
+ pos + if_modified_since.length(),
+ expect_if_modified_since_.length(),
+ expect_if_modified_since_));
+ }
+
+ const std::string if_none_match = "If-None-Match: ";
+ pos = extra_headers.find(if_none_match);
+ if (pos != std::string::npos) {
+ saw_if_none_match_ = (0 == extra_headers.compare(
+ pos + if_none_match.length(),
+ expect_if_none_match_.length(),
+ expect_if_none_match_));
+ }
+ }
+ return NULL;
+ }
+
+ private:
+ static std::string expect_if_modified_since_;
+ static bool saw_if_modified_since_;
+ static std::string expect_if_none_match_;
+ static bool saw_if_none_match_;
+ static bool already_checked_;
+};
+
+// static
+std::string HttpHeadersRequestTestJob::expect_if_modified_since_;
+bool HttpHeadersRequestTestJob::saw_if_modified_since_ = false;
+std::string HttpHeadersRequestTestJob::expect_if_none_match_;
+bool HttpHeadersRequestTestJob::saw_if_none_match_ = false;
+bool HttpHeadersRequestTestJob::already_checked_ = false;
+
class AppCacheUpdateJobTest : public testing::Test,
public AppCacheGroup::UpdateObserver {
public:
@@ -2116,6 +2182,258 @@ class AppCacheUpdateJobTest : public testing::Test,
group_->AddUpdateObserver(this);
}
+ void IfModifiedSinceTest() {
+ ASSERT_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type());
+
+ old_factory_ = URLRequest::RegisterProtocolFactory(
+ "http", HttpHeadersRequestTestJob::IfModifiedSinceFactory);
+ registered_factory_ = true;
+
+ MakeService();
+ group_ = new AppCacheGroup(service_.get(), GURL("http://headertest"), 111);
+ AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_);
+ group_->update_job_ = update;
+
+ // First test against a cache attempt. Will start manifest fetch
+ // synchronously.
+ HttpHeadersRequestTestJob::Initialize("", "");
+ MockFrontend mock_frontend;
+ AppCacheHost host(1, &mock_frontend, service_.get());
+ update->StartUpdate(&host, GURL::EmptyGURL());
+ HttpHeadersRequestTestJob::Verify();
+ delete update;
+
+ // Now simulate a refetch manifest request. Will start fetch request
+ // synchronously.
+ const char data[] =
+ "HTTP/1.1 200 OK\0"
+ "\0";
+ net::HttpResponseHeaders* headers =
+ new net::HttpResponseHeaders(std::string(data, arraysize(data)));
+ net::HttpResponseInfo* response_info = new net::HttpResponseInfo();
+ response_info->headers = headers; // adds ref to headers
+
+ HttpHeadersRequestTestJob::Initialize("", "");
+ update = new AppCacheUpdateJob(service_.get(), group_);
+ group_->update_job_ = update;
+ group_->update_status_ = AppCacheGroup::DOWNLOADING;
+ update->manifest_response_info_.reset(response_info);
+ update->internal_state_ = AppCacheUpdateJob::REFETCH_MANIFEST;
+ update->FetchManifest(false); // not first request
+ HttpHeadersRequestTestJob::Verify();
+ delete update;
+
+ // Change the headers to include a Last-Modified header. Manifest refetch
+ // should include If-Modified-Since header.
+ const char data2[] =
+ "HTTP/1.1 200 OK\0"
+ "Last-Modified: Sat, 29 Oct 1994 19:43:31 GMT\0"
+ "\0";
+ net::HttpResponseHeaders* headers2 =
+ new net::HttpResponseHeaders(std::string(data2, arraysize(data2)));
+ response_info = new net::HttpResponseInfo();
+ response_info->headers = headers2;
+
+ HttpHeadersRequestTestJob::Initialize("Sat, 29 Oct 1994 19:43:31 GMT", "");
+ update = new AppCacheUpdateJob(service_.get(), group_);
+ group_->update_job_ = update;
+ group_->update_status_ = AppCacheGroup::DOWNLOADING;
+ update->manifest_response_info_.reset(response_info);
+ update->internal_state_ = AppCacheUpdateJob::REFETCH_MANIFEST;
+ update->FetchManifest(false); // not first request
+ HttpHeadersRequestTestJob::Verify();
+ delete update;
+
+ UpdateFinished();
+ }
+
+ void IfModifiedSinceUpgradeTest() {
+ ASSERT_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type());
+
+ HttpHeadersRequestTestJob::Initialize("Sat, 29 Oct 1994 19:43:31 GMT", "");
+ old_factory_ = URLRequest::RegisterProtocolFactory(
+ "http", HttpHeadersRequestTestJob::IfModifiedSinceFactory);
+ registered_factory_ = true;
+
+ MakeService();
+ group_ = new AppCacheGroup(
+ service_.get(), http_server_->TestServerPage("files/manifest1"), 111);
+ AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_);
+ group_->update_job_ = update;
+
+ // Give the newest cache a manifest enry that is in storage.
+ response_writer_.reset(
+ service_->storage()->CreateResponseWriter(group_->manifest_url()));
+
+ AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(),
+ response_writer_->response_id());
+ MockFrontend* frontend = MakeMockFrontend();
+ AppCacheHost* host = MakeHost(1, frontend);
+ host->AssociateCache(cache);
+
+ // Set up checks for when update job finishes.
+ do_checks_after_update_finished_ = true;
+ expect_group_obsolete_ = false;
+ expect_group_has_cache_ = true;
+ expect_old_cache_ = cache;
+ tested_manifest_ = MANIFEST1;
+ MockFrontend::HostIds ids1(1, host->host_id());
+ frontend->AddExpectedEvent(ids1, CHECKING_EVENT);
+ frontend->AddExpectedEvent(ids1, DOWNLOADING_EVENT);
+ frontend->AddExpectedEvent(ids1, PROGRESS_EVENT);
+ frontend->AddExpectedEvent(ids1, PROGRESS_EVENT);
+ frontend->AddExpectedEvent(ids1, UPDATE_READY_EVENT);
+
+ // Seed storage with expected manifest response info that will cause
+ // an If-Modified-Since header to be put in the manifest fetch request.
+ const char data[] =
+ "HTTP/1.1 200 OK\0"
+ "Last-Modified: Sat, 29 Oct 1994 19:43:31 GMT\0"
+ "\0";
+ net::HttpResponseHeaders* headers =
+ new net::HttpResponseHeaders(std::string(data, arraysize(data)));
+ net::HttpResponseInfo* response_info = new net::HttpResponseInfo();
+ response_info->headers = headers; // adds ref to headers
+ scoped_refptr<HttpResponseInfoIOBuffer> io_buffer =
+ new HttpResponseInfoIOBuffer(response_info); // adds ref to info
+ write_callback_.reset(
+ new net::CompletionCallbackImpl<AppCacheUpdateJobTest>(this,
+ &AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData));
+ response_writer_->WriteInfo(io_buffer, write_callback_.get());
+
+ // Start update after data write completes asynchronously.
+ }
+
+ void IfNoneMatchUpgradeTest() {
+ ASSERT_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type());
+
+ HttpHeadersRequestTestJob::Initialize("", "\"LadeDade\"");
+ old_factory_ = URLRequest::RegisterProtocolFactory(
+ "http", HttpHeadersRequestTestJob::IfModifiedSinceFactory);
+ registered_factory_ = true;
+
+ MakeService();
+ group_ = new AppCacheGroup(
+ service_.get(), http_server_->TestServerPage("files/manifest1"), 111);
+ AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_);
+ group_->update_job_ = update;
+
+ // Give the newest cache a manifest enry that is in storage.
+ response_writer_.reset(
+ service_->storage()->CreateResponseWriter(group_->manifest_url()));
+
+ AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(),
+ response_writer_->response_id());
+ MockFrontend* frontend = MakeMockFrontend();
+ AppCacheHost* host = MakeHost(1, frontend);
+ host->AssociateCache(cache);
+
+ // Set up checks for when update job finishes.
+ do_checks_after_update_finished_ = true;
+ expect_group_obsolete_ = false;
+ expect_group_has_cache_ = true;
+ expect_old_cache_ = cache;
+ tested_manifest_ = MANIFEST1;
+ MockFrontend::HostIds ids1(1, host->host_id());
+ frontend->AddExpectedEvent(ids1, CHECKING_EVENT);
+ frontend->AddExpectedEvent(ids1, DOWNLOADING_EVENT);
+ frontend->AddExpectedEvent(ids1, PROGRESS_EVENT);
+ frontend->AddExpectedEvent(ids1, PROGRESS_EVENT);
+ frontend->AddExpectedEvent(ids1, UPDATE_READY_EVENT);
+
+ // Seed storage with expected manifest response info that will cause
+ // an If-None-Match header to be put in the manifest fetch request.
+ const char data[] =
+ "HTTP/1.1 200 OK\0"
+ "ETag: \"LadeDade\"\0"
+ "\0";
+ net::HttpResponseHeaders* headers =
+ new net::HttpResponseHeaders(std::string(data, arraysize(data)));
+ net::HttpResponseInfo* response_info = new net::HttpResponseInfo();
+ response_info->headers = headers; // adds ref to headers
+ scoped_refptr<HttpResponseInfoIOBuffer> io_buffer =
+ new HttpResponseInfoIOBuffer(response_info); // adds ref to info
+ write_callback_.reset(
+ new net::CompletionCallbackImpl<AppCacheUpdateJobTest>(this,
+ &AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData));
+ response_writer_->WriteInfo(io_buffer, write_callback_.get());
+
+ // Start update after data write completes asynchronously.
+ }
+
+ void IfNoneMatchRefetchTest() {
+ ASSERT_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type());
+
+ HttpHeadersRequestTestJob::Initialize("", "\"LadeDade\"");
+ old_factory_ = URLRequest::RegisterProtocolFactory(
+ "http", HttpHeadersRequestTestJob::IfModifiedSinceFactory);
+ registered_factory_ = true;
+
+ MakeService();
+ group_ = new AppCacheGroup(service_.get(), GURL("http://headertest"), 111);
+ AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_);
+ group_->update_job_ = update;
+
+ // Simulate a refetch manifest request that uses an ETag header.
+ const char data[] =
+ "HTTP/1.1 200 OK\0"
+ "ETag: \"LadeDade\"\0"
+ "\0";
+ net::HttpResponseHeaders* headers =
+ new net::HttpResponseHeaders(std::string(data, arraysize(data)));
+ net::HttpResponseInfo* response_info = new net::HttpResponseInfo();
+ response_info->headers = headers; // adds ref to headers
+
+ update = new AppCacheUpdateJob(service_.get(), group_);
+ group_->update_job_ = update;
+ group_->update_status_ = AppCacheGroup::DOWNLOADING;
+ update->manifest_response_info_.reset(response_info);
+ update->internal_state_ = AppCacheUpdateJob::REFETCH_MANIFEST;
+ update->FetchManifest(false); // not first request
+ HttpHeadersRequestTestJob::Verify();
+ delete update;
+
+ UpdateFinished();
+ }
+
+ void MultipleHeadersRefetchTest() {
+ ASSERT_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type());
+
+ // Verify that code is correct when building multiple extra headers.
+ HttpHeadersRequestTestJob::Initialize(
+ "Sat, 29 Oct 1994 19:43:31 GMT", "\"LadeDade\"");
+ old_factory_ = URLRequest::RegisterProtocolFactory(
+ "http", HttpHeadersRequestTestJob::IfModifiedSinceFactory);
+ registered_factory_ = true;
+
+ MakeService();
+ group_ = new AppCacheGroup(service_.get(), GURL("http://headertest"), 111);
+ AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_);
+ group_->update_job_ = update;
+
+ // Simulate a refetch manifest request that uses an ETag header.
+ const char data[] =
+ "HTTP/1.1 200 OK\0"
+ "Last-Modified: Sat, 29 Oct 1994 19:43:31 GMT\0"
+ "ETag: \"LadeDade\"\0"
+ "\0";
+ net::HttpResponseHeaders* headers =
+ new net::HttpResponseHeaders(std::string(data, arraysize(data)));
+ net::HttpResponseInfo* response_info = new net::HttpResponseInfo();
+ response_info->headers = headers; // adds ref to headers
+
+ update = new AppCacheUpdateJob(service_.get(), group_);
+ group_->update_job_ = update;
+ group_->update_status_ = AppCacheGroup::DOWNLOADING;
+ update->manifest_response_info_.reset(response_info);
+ update->internal_state_ = AppCacheUpdateJob::REFETCH_MANIFEST;
+ update->FetchManifest(false); // not first request
+ HttpHeadersRequestTestJob::Verify();
+ delete update;
+
+ UpdateFinished();
+ }
+
void WaitForUpdateToFinish() {
if (group_->update_status() == AppCacheGroup::IDLE)
UpdateFinished();
@@ -2190,6 +2508,7 @@ class AppCacheUpdateJobTest : public testing::Test,
// has finished. Cannot verify update job internals as update is deleted.
void VerifyExpectations() {
RetryRequestTestJob::Verify();
+ HttpHeadersRequestTestJob::Verify();
EXPECT_EQ(expect_group_obsolete_, group_->is_obsolete());
@@ -2713,4 +3032,24 @@ TEST_F(AppCacheUpdateJobTest, QueueMasterEntry) {
RunTestOnIOThread(&AppCacheUpdateJobTest::QueueMasterEntryTest);
}
+TEST_F(AppCacheUpdateJobTest, IfModifiedSince) {
+ RunTestOnIOThread(&AppCacheUpdateJobTest::IfModifiedSinceTest);
+}
+
+TEST_F(AppCacheUpdateJobTest, IfModifiedSinceUpgrade) {
+ RunTestOnIOThread(&AppCacheUpdateJobTest::IfModifiedSinceUpgradeTest);
+}
+
+TEST_F(AppCacheUpdateJobTest, IfNoneMatchUpgrade) {
+ RunTestOnIOThread(&AppCacheUpdateJobTest::IfNoneMatchUpgradeTest);
+}
+
+TEST_F(AppCacheUpdateJobTest, IfNoneMatchRefetch) {
+ RunTestOnIOThread(&AppCacheUpdateJobTest::IfNoneMatchRefetchTest);
+}
+
+TEST_F(AppCacheUpdateJobTest, MultipleHeadersRefetch) {
+ RunTestOnIOThread(&AppCacheUpdateJobTest::MultipleHeadersRefetchTest);
+}
+
} // namespace appcache