Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(242)

Unified Diff: content/browser/loader/resource_dispatcher_host_unittest.cc

Issue 1041993004: content::ResourceDispatcherHostImpl changes for stale-while-revalidate (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@s-w-r-yhirano-patch
Patch Set: Workaround iwyu bug in prerender_resource Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/loader/resource_dispatcher_host_unittest.cc
diff --git a/content/browser/loader/resource_dispatcher_host_unittest.cc b/content/browser/loader/resource_dispatcher_host_unittest.cc
index 126fbad1e2936ad7797250eeecff561ac341f249..025c888848af48305ecacb909c0d5b8c8e1ab049 100644
--- a/content/browser/loader/resource_dispatcher_host_unittest.cc
+++ b/content/browser/loader/resource_dispatcher_host_unittest.cc
@@ -2,14 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <queue>
+#include <string>
#include <vector>
#include "base/basictypes.h"
#include "base/bind.h"
+#include "base/callback.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/location.h"
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "base/memory/shared_memory.h"
#include "base/pickle.h"
@@ -47,9 +52,12 @@
#include "content/public/test/test_renderer_host.h"
#include "content/test/test_content_browser_client.h"
#include "net/base/elements_upload_data_stream.h"
+#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/base/request_priority.h"
#include "net/base/upload_bytes_element_reader.h"
+#include "net/http/http_response_headers.h"
+#include "net/http/http_response_info.h"
#include "net/http/http_util.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
@@ -830,8 +838,10 @@ class ResourceDispatcherHostTest : public testing::Test,
typedef ResourceDispatcherHostImpl::LoadInfo LoadInfo;
typedef ResourceDispatcherHostImpl::LoadInfoMap LoadInfoMap;
- ResourceDispatcherHostTest()
+ ResourceDispatcherHostTest(
+ scoped_ptr<net::TestNetworkDelegate> network_delegate)
: thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
+ network_delegate_(network_delegate.Pass()),
old_factory_(NULL),
send_data_received_acks_(false) {
browser_context_.reset(new TestBrowserContext());
@@ -843,9 +853,15 @@ class ResourceDispatcherHostTest : public testing::Test,
browser_context_->GetResourceContext()->GetRequestContext();
job_factory_.reset(new TestURLRequestJobFactory(this));
request_context->set_job_factory(job_factory_.get());
- request_context->set_network_delegate(&network_delegate_);
+ request_context->set_network_delegate(network_delegate_.get());
+ // TODO(ricea): Remove this when it becomes the default.
+ host_.async_revalidation_enabled_ = true;
}
+ ResourceDispatcherHostTest()
+ : ResourceDispatcherHostTest(
+ make_scoped_ptr(new net::TestNetworkDelegate)) {}
+
// IPC::Sender implementation
bool Send(IPC::Message* msg) override {
accum_.AddMessage(*msg);
@@ -961,7 +977,9 @@ class ResourceDispatcherHostTest : public testing::Test,
void CompleteStartRequest(int request_id);
void CompleteStartRequest(ResourceMessageFilter* filter, int request_id);
- net::TestNetworkDelegate* network_delegate() { return &network_delegate_; }
+ net::TestNetworkDelegate* network_delegate() {
+ return network_delegate_.get();
+ }
void EnsureSchemeIsAllowed(const std::string& scheme) {
ChildProcessSecurityPolicyImpl* policy =
@@ -1021,9 +1039,22 @@ class ResourceDispatcherHostTest : public testing::Test,
wait_for_request_complete_loop_.reset();
}
+ typedef base::Callback<net::URLRequestJob*(net::URLRequest*,
+ net::NetworkDelegate*)>
+ URLRequestJobCreateCallback;
+
+ void SetCustomURLRequestJobCreateCallback(
+ const URLRequestJobCreateCallback& callback) {
+ custom_url_request_job_create_callback_.reset(
+ new URLRequestJobCreateCallback(callback));
+ }
+
scoped_ptr<LoadInfoTestRequestInfo> loader_test_request_info_;
scoped_ptr<base::RunLoop> wait_for_request_create_loop_;
+ scoped_ptr<URLRequestJobCreateCallback>
+ custom_url_request_job_create_callback_;
+
content::TestBrowserThreadBundle thread_bundle_;
scoped_ptr<TestBrowserContext> browser_context_;
scoped_ptr<TestURLRequestJobFactory> job_factory_;
@@ -1031,7 +1062,7 @@ class ResourceDispatcherHostTest : public testing::Test,
scoped_ptr<TestWebContentsObserver> web_contents_observer_;
scoped_refptr<ForwardingFilter> filter_;
scoped_refptr<TestFilterSpecifyingChild> web_contents_filter_;
- net::TestNetworkDelegate network_delegate_;
+ scoped_ptr<net::TestNetworkDelegate> network_delegate_;
ResourceDispatcherHostImpl host_;
ResourceIPCAccumulator accum_;
std::string response_headers_;
@@ -3397,6 +3428,10 @@ net::URLRequestJob* TestURLRequestJobFactory::MaybeCreateJobWithProtocolHandler(
return new URLRequestLoadInfoJob(request, network_delegate,
info->load_state, info->upload_progress);
}
+ if (test_fixture_->custom_url_request_job_create_callback_) {
+ return test_fixture_->custom_url_request_job_create_callback_->Run(
+ request, network_delegate);
+ }
if (test_fixture_->response_headers_.empty()) {
if (delay_start_) {
return new URLRequestTestDelayedStartJob(request, network_delegate);
@@ -3443,4 +3478,294 @@ net::URLRequestJob* TestURLRequestJobFactory::MaybeInterceptResponse(
return nullptr;
}
+TEST_F(ResourceDispatcherHostTest, SupportsAsyncRevalidation) {
+ // Scheme has to be HTTP or HTTPS to support async revalidation.
+ HandleScheme("http");
+ // Prevent the job from completing synchronously.
+ job_factory_->SetDelayedCompleteJobGeneration(true);
+ SetResponse(net::URLRequestTestJob::test_headers(), "delay complete");
+ MakeTestRequest(0, 1, GURL("http://example.com/baz"));
+
+ net::URLRequest* url_request(
+ host_.GetURLRequest(GlobalRequestID(filter_->child_id(), 1)));
+ ASSERT_TRUE(url_request);
+
+ EXPECT_TRUE(url_request->load_flags() & net::LOAD_SUPPORT_ASYNC_REVALIDATION);
+}
+
+TEST_F(ResourceDispatcherHostTest, AsyncRevalidationNotSupportedForPOST) {
+ // Scheme has to be HTTP or HTTPS to support async revalidation.
+ HandleScheme("http");
+ // Prevent the job from completing synchronously.
+ job_factory_->SetDelayedCompleteJobGeneration(true);
+ SetResponse(net::URLRequestTestJob::test_headers(), "delay complete");
+ // Create POST request.
+ ResourceHostMsg_Request request = CreateResourceRequest(
+ "POST", RESOURCE_TYPE_SUB_RESOURCE, GURL("http://example.com/baz.php"));
+ ResourceHostMsg_RequestResource msg(0, 1, request);
+ host_.OnMessageReceived(msg, filter_.get());
+ KickOffRequest();
+
+ net::URLRequest* url_request(
+ host_.GetURLRequest(GlobalRequestID(filter_->child_id(), 1)));
+ ASSERT_TRUE(url_request);
+
+ EXPECT_FALSE(url_request->load_flags() &
+ net::LOAD_SUPPORT_ASYNC_REVALIDATION);
+}
+
+TEST_F(ResourceDispatcherHostTest, AsyncRevalidationNotSupportedForRedirect) {
+ static const char kRedirectHeaders[] =
+ "HTTP/1.1 302 MOVED\n"
+ "Location: http://example.com/var\n"
+ "\n";
+ // Scheme has to be HTTP or HTTPS to support async revalidation.
+ HandleScheme("http");
+ // Prevent the job from completing synchronously.
+ job_factory_->SetDelayedCompleteJobGeneration(true);
+ SetResponse(kRedirectHeaders, "");
+
+ MakeTestRequest(0, 1, GURL("http://example.com/baz"));
+
+ net::URLRequest* url_request(
+ host_.GetURLRequest(GlobalRequestID(filter_->child_id(), 1)));
+ ASSERT_TRUE(url_request);
+
+ EXPECT_FALSE(url_request->load_flags() &
+ net::LOAD_SUPPORT_ASYNC_REVALIDATION);
+}
+
+// A URLRequestJob implementation which sets the |async_revalidation_required|
+// flag on the HttpResponseInfo object to true if the request has the
+// LOAD_SUPPORT_ASYNC_REVALIDATION flag.
+class AsyncRevalidationRequiredURLRequestTestJob
+ : public net::URLRequestTestJob {
+ public:
+ // The Create() method is useful for wrapping the construction of the object
+ // in a Callback.
+ static net::URLRequestJob* Create(net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) {
+ return new AsyncRevalidationRequiredURLRequestTestJob(request,
+ network_delegate);
+ }
+
+ void GetResponseInfo(net::HttpResponseInfo* info) override {
+ if (request()->load_flags() & net::LOAD_SUPPORT_ASYNC_REVALIDATION)
+ info->async_revalidation_required = true;
+ }
+
+ private:
+ AsyncRevalidationRequiredURLRequestTestJob(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate)
+ : URLRequestTestJob(request,
+ network_delegate,
+ net::URLRequestTestJob::test_headers(),
+ std::string(),
+ false) {}
+
+ ~AsyncRevalidationRequiredURLRequestTestJob() override {}
+
+ DISALLOW_COPY_AND_ASSIGN(AsyncRevalidationRequiredURLRequestTestJob);
+};
+
+// A URLRequestJob implementation which serves a redirect and sets the
+// |async_revalidation_required| flag on the HttpResponseInfo object to true if
+// the request has the LOAD_SUPPORT_ASYNC_REVALIDATION flag.
+class RedirectAndRevalidateURLRequestTestJob : public net::URLRequestTestJob {
+ public:
+ // The Create() method is useful for wrapping the construction of the object
+ // in a Callback.
+ static net::URLRequestJob* Create(net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) {
+ return new RedirectAndRevalidateURLRequestTestJob(request,
+ network_delegate);
+ }
+
+ void GetResponseInfo(net::HttpResponseInfo* info) override {
+ URLRequestTestJob::GetResponseInfo(info);
+ if (request()->load_flags() & net::LOAD_SUPPORT_ASYNC_REVALIDATION)
+ info->async_revalidation_required = true;
+ }
+
+ private:
+ RedirectAndRevalidateURLRequestTestJob(net::URLRequest* request,
+ net::NetworkDelegate* network_delegate)
+ : URLRequestTestJob(
+ request,
+ network_delegate,
+ std::string(CreateRedirectHeaders()),
+ std::string(),
+ false) {}
+
+ ~RedirectAndRevalidateURLRequestTestJob() override {}
+
+ static std::string CreateRedirectHeaders() {
+ static const char kRedirectHeaders[] =
+ "HTTP/1.1 302 MOVED\0"
+ "Location: http://example.com/var\0"
+ "\0";
+ return std::string(kRedirectHeaders, arraysize(kRedirectHeaders));
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(RedirectAndRevalidateURLRequestTestJob);
+};
+
+// A NetworkDelegate that records the URLRequests as they are created.
+class URLRequestRecordingNetworkDelegate : public net::TestNetworkDelegate {
+ public:
+ URLRequestRecordingNetworkDelegate() : requests_() {}
+
+ net::URLRequest* NextRequest() {
+ if (requests_.empty())
+ return nullptr;
+ net::URLRequest* request = requests_.front();
+ requests_.pop();
+ return request;
+ }
+
+ bool IsEmpty() {
+ return requests_.empty();
+ }
+
+ int OnBeforeURLRequest(net::URLRequest* request,
+ const net::CompletionCallback& callback,
+ GURL* new_url) override {
+ requests_.push(request);
+ return TestNetworkDelegate::OnBeforeURLRequest(request, callback, new_url);
+ }
+
+ private:
+ std::queue<net::URLRequest*> requests_;
+
+ DISALLOW_COPY_AND_ASSIGN(URLRequestRecordingNetworkDelegate);
+};
+
+class ResourceDispatcherHostAsyncRevalidationTest
+ : public ResourceDispatcherHostTest {
+ public:
+ ResourceDispatcherHostAsyncRevalidationTest()
+ : ResourceDispatcherHostTest(
+ make_scoped_ptr(new URLRequestRecordingNetworkDelegate)) {
+ // Scheme has to be HTTP or HTTPS to support async revalidation.
+ HandleScheme("http");
+ // Use the AsyncRevalidationRequiredURLRequestTestJob.
+ SetCustomURLRequestJobCreateCallback(
+ base::Bind(&AsyncRevalidationRequiredURLRequestTestJob::Create));
+ }
+
+ URLRequestRecordingNetworkDelegate* recording_network_delegate() {
+ return static_cast<URLRequestRecordingNetworkDelegate*>(network_delegate());
+ }
+
+ net::URLRequest* NextRequest() {
+ return recording_network_delegate()->NextRequest();
+ }
+
+ bool IsEmpty() {
+ return recording_network_delegate()->IsEmpty();
+ }
+};
+
+// Verify that an async revalidation is actually created when needed.
+TEST_F(ResourceDispatcherHostAsyncRevalidationTest, Issued) {
+ // Create the original request.
+ MakeTestRequest(0, 1, GURL("http://example.com/baz"));
+
+ net::URLRequest* initial_request = NextRequest();
+ ASSERT_TRUE(initial_request);
+ EXPECT_TRUE(initial_request->load_flags() &
+ net::LOAD_SUPPORT_ASYNC_REVALIDATION);
+
+ net::URLRequest* async_request = NextRequest();
+ ASSERT_TRUE(async_request);
+}
+
+// Verify the the URL of the async revalidation matches the original request.
+TEST_F(ResourceDispatcherHostAsyncRevalidationTest, URLMatches) {
+ // Create the original request.
+ MakeTestRequest(0, 1, GURL("http://example.com/special-baz"));
+
+ // Discard the original request.
+ NextRequest();
+
+ net::URLRequest* async_request = NextRequest();
+ ASSERT_TRUE(async_request);
+ EXPECT_EQ(GURL("http://example.com/special-baz"), async_request->url());
+}
+
+TEST_F(ResourceDispatcherHostAsyncRevalidationTest,
+ AsyncRevalidationsDoNotSupportAsyncRevalidation) {
+ // Create the original request.
+ MakeTestRequest(0, 1, GURL("http://example.com/baz"));
+
+ // Discard the original request.
+ NextRequest();
+
+ // Get the async revalidation request.
+ net::URLRequest* async_request = NextRequest();
+ ASSERT_TRUE(async_request);
+ EXPECT_FALSE(async_request->load_flags() &
+ net::LOAD_SUPPORT_ASYNC_REVALIDATION);
+}
+
+TEST_F(ResourceDispatcherHostAsyncRevalidationTest,
+ AsyncRevalidationsNotDuplicated) {
+ // Create the original request.
+ MakeTestRequest(0, 1, GURL("http://example.com/baz"));
+
+ // Discard the original request.
+ NextRequest();
+
+ // Get the async revalidation request.
+ net::URLRequest* async_request = NextRequest();
+ EXPECT_TRUE(async_request);
+
+ // Start a second request to the same URL.
+ MakeTestRequest(0, 2, GURL("http://example.com/baz"));
+
+ // Discard the second request.
+ NextRequest();
+
+ // There should not be another async revalidation request.
+ EXPECT_TRUE(IsEmpty());
+}
+
+// Async revalidation to different URLs should not be treated as duplicates.
+TEST_F(ResourceDispatcherHostAsyncRevalidationTest,
+ AsyncRevalidationsToSeparateURLsAreSeparate) {
+ // Create two requests to two URLs.
+ MakeTestRequest(0, 1, GURL("http://example.com/baz"));
+ MakeTestRequest(0, 2, GURL("http://example.com/far"));
+
+ net::URLRequest* initial_request = NextRequest();
+ ASSERT_TRUE(initial_request);
+ net::URLRequest* initial_async_revalidation = NextRequest();
+ ASSERT_TRUE(initial_async_revalidation);
+ net::URLRequest* second_request = NextRequest();
+ ASSERT_TRUE(second_request);
+ net::URLRequest* second_async_revalidation = NextRequest();
+ ASSERT_TRUE(second_async_revalidation);
+
+ EXPECT_EQ("http://example.com/baz", initial_request->url().spec());
+ EXPECT_EQ("http://example.com/baz", initial_async_revalidation->url().spec());
+ EXPECT_EQ("http://example.com/far", second_request->url().spec());
+ EXPECT_EQ("http://example.com/far", second_async_revalidation->url().spec());
+}
+
+// A stale-while-revalidate applicable redirect response should not result in an
+// async revalidation.
+TEST_F(ResourceDispatcherHostAsyncRevalidationTest, RedirectNotApplicable) {
+ // Use the appropriate URLRequestJob for the test.
+ SetCustomURLRequestJobCreateCallback(
+ base::Bind(&RedirectAndRevalidateURLRequestTestJob::Create));
+ MakeTestRequest(0, 1, GURL("http://example.com/redirect"));
+
+ net::URLRequest* initial_request = NextRequest();
+ EXPECT_TRUE(initial_request);
+
+ // There should not be an async revalidation request.
+ EXPECT_TRUE(IsEmpty());
+}
+
} // namespace content

Powered by Google App Engine
This is Rietveld 408576698