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

Unified Diff: content/browser/loader/async_revalidation_driver_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: Use histograms instead of user actions. Created 5 years 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/async_revalidation_driver_unittest.cc
diff --git a/content/browser/loader/async_revalidation_driver_unittest.cc b/content/browser/loader/async_revalidation_driver_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..1f5a7e4b1f0d3bc488b1c31d4b226c6c6a554328
--- /dev/null
+++ b/content/browser/loader/async_revalidation_driver_unittest.cc
@@ -0,0 +1,397 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/loader/async_revalidation_driver.h"
+
+#include <string>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/location.h"
+#include "base/macros.h"
+#include "base/run_loop.h"
+#include "content/public/browser/client_certificate_delegate.h"
+#include "content/public/common/content_client.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/test/test_content_browser_client.h"
+#include "ipc/ipc_message.h"
+#include "net/base/net_errors.h"
+#include "net/base/network_delegate_impl.h"
+#include "net/base/request_priority.h"
+#include "net/ssl/ssl_cert_request_info.h"
+#include "net/url_request/url_request_job_factory.h"
+#include "net/url_request/url_request_job_factory_impl.h"
+#include "net/url_request/url_request_status.h"
+#include "net/url_request/url_request_test_job.h"
+#include "net/url_request/url_request_test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+namespace {
+
+// Dummy implementation of ResourceThrottle, an instance of which is needed to
+// initialize AsyncRevalidationDriver.
+class ResourceThrottleStub : public ResourceThrottle {
+ public:
+ ResourceThrottleStub() {}
+
+ // If true, defers the request in WillStartRequest.
+ void set_defer_request_on_will_start_request(
+ bool defer_request_on_will_start_request) {
+ defer_request_on_will_start_request_ = defer_request_on_will_start_request;
+ }
+
+ // ResourceThrottler implementation:
+ void WillStartRequest(bool* defer) override {
+ *defer = defer_request_on_will_start_request_;
+ }
+
+ const char* GetNameForLogging() const override {
+ return "ResourceThrottleStub";
+ }
+
+ private:
+ bool defer_request_on_will_start_request_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(ResourceThrottleStub);
+};
+
+// There are multiple layers of boilerplate needed to use a URLRequestTestJob
+// subclass. Subclasses of AsyncRevalidationDriverTest can use
+// BindCreateProtocolHandlerCallback() to bypass most of that boilerplate.
+using CreateProtocolHandlerCallback =
+ base::Callback<scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>()>;
+
+template <typename T>
+CreateProtocolHandlerCallback BindCreateProtocolHandlerCallback() {
+ static_assert(std::is_base_of<net::URLRequestJob, T>::value,
+ "Template argument to BindCreateProtocolHandlerCallback() must "
+ "be a subclass of URLRequestJob.");
+
+ class TemplatedProtocolHandler
+ : public net::URLRequestJobFactory::ProtocolHandler {
+ public:
+ static scoped_ptr<net::URLRequestJobFactory::ProtocolHandler> Create() {
+ return make_scoped_ptr(new TemplatedProtocolHandler());
+ }
+
+ // URLRequestJobFactory::ProtocolHandler implementation:
+ net::URLRequestJob* MaybeCreateJob(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) const override {
+ return new T(request, network_delegate);
+ }
+ };
+
+ return base::Bind(&TemplatedProtocolHandler::Create);
+}
+
+// An implementation of NetworkDelegate that captures the status of the last
+// URLRequest to be destroyed.
+class StatusCapturingNetworkDelegate : public net::NetworkDelegateImpl {
+ public:
+ const net::URLRequestStatus& last_status() { return last_status_; }
+
+ private:
+ // net::NetworkDelegate implementation.
+ void OnURLRequestDestroyed(net::URLRequest* request) override {
+ last_status_ = request->status();
+ }
+
+ net::URLRequestStatus last_status_;
+};
+
+class AsyncRevalidationDriverTest : public testing::Test {
+ protected:
+ // Constructor for test fixtures that subclass this one.
+ AsyncRevalidationDriverTest(
+ const CreateProtocolHandlerCallback& create_protocol_handler_callback)
+ : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
+ create_protocol_handler_callback_(create_protocol_handler_callback),
+ raw_ptr_resource_throttle_(nullptr),
+ raw_ptr_request_(nullptr) {
+ test_url_request_context_.set_job_factory(&job_factory_);
+ test_url_request_context_.set_network_delegate(&network_delegate_);
+ }
+
+ // Constructor for tests that use this fixture directly.
+ AsyncRevalidationDriverTest()
+ : AsyncRevalidationDriverTest(
+ base::Bind(net::URLRequestTestJob::CreateProtocolHandler)) {}
+
+ bool async_revalidation_complete_called() const {
+ return async_revalidation_complete_called_;
+ }
+
+ const net::URLRequestStatus& last_status() {
+ return network_delegate_.last_status();
+ }
+
+ void SetUpAsyncRevalidationDriverWithRequestToUrl(const GURL& url) {
+ scoped_ptr<net::URLRequest> request(test_url_request_context_.CreateRequest(
+ url, net::DEFAULT_PRIORITY, nullptr /* delegate */));
+ raw_ptr_request_ = request.get();
+ raw_ptr_resource_throttle_ = new ResourceThrottleStub();
+ // This use of base::Unretained() is safe because |driver_|, and the closure
+ // passed to it, will be destroyed before this object is.
+ driver_.reset(new AsyncRevalidationDriver(
+ std::move(request), make_scoped_ptr(raw_ptr_resource_throttle_),
+ base::Bind(&AsyncRevalidationDriverTest::OnAsyncRevalidationComplete,
+ base::Unretained(this))));
+ }
+
+ void SetUpAsyncRevalidationDriverWithDefaultRequest() {
+ SetUpAsyncRevalidationDriverWithRequestToUrl(
+ net::URLRequestTestJob::test_url_1());
+ }
+
+ void SetUp() override {
+ job_factory_.SetProtocolHandler("test",
+ create_protocol_handler_callback_.Run());
+ SetUpAsyncRevalidationDriverWithDefaultRequest();
+ }
+
+ void OnAsyncRevalidationComplete() {
+ EXPECT_FALSE(async_revalidation_complete_called_);
+ async_revalidation_complete_called_ = true;
+ driver_.reset();
+ }
+
+ TestBrowserThreadBundle thread_bundle_;
+ net::URLRequestJobFactoryImpl job_factory_;
+ net::TestURLRequestContext test_url_request_context_;
+ StatusCapturingNetworkDelegate network_delegate_;
+ CreateProtocolHandlerCallback create_protocol_handler_callback_;
+
+ // The AsyncRevalidationDriver owns the URLRequest and the ResourceThrottle.
+ ResourceThrottleStub* raw_ptr_resource_throttle_;
+ net::URLRequest* raw_ptr_request_;
+ scoped_ptr<AsyncRevalidationDriver> driver_;
+ bool async_revalidation_complete_called_ = false;
+};
+
+TEST_F(AsyncRevalidationDriverTest, NormalRequestCompletes) {
+ driver_->StartRequest();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(async_revalidation_complete_called());
+}
+
+// Verifies that request that should be deferred at start is deferred.
+TEST_F(AsyncRevalidationDriverTest, DeferOnStart) {
+ raw_ptr_resource_throttle_->set_defer_request_on_will_start_request(true);
+
+ driver_->StartRequest();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(raw_ptr_request_->is_pending());
+ EXPECT_FALSE(async_revalidation_complete_called());
+}
+
+// Verifies that resuming a deferred request works. Assumes that DeferOnStart
+// passes.
+TEST_F(AsyncRevalidationDriverTest, ResumeDeferredRequestWorks) {
+ raw_ptr_resource_throttle_->set_defer_request_on_will_start_request(true);
+
+ driver_->StartRequest();
+ base::RunLoop().RunUntilIdle();
+
+ ResourceController* driver_as_resource_controller = driver_.get();
+ driver_as_resource_controller->Resume();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(async_revalidation_complete_called());
+}
+
+// Verifies that redirects are not followed.
+TEST_F(AsyncRevalidationDriverTest, RedirectsAreNotFollowed) {
+ SetUpAsyncRevalidationDriverWithRequestToUrl(
+ net::URLRequestTestJob::test_url_redirect_to_url_2());
+
+ driver_->StartRequest();
+ while (net::URLRequestTestJob::ProcessOnePendingMessage())
+ base::RunLoop().RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(last_status().is_success());
+ EXPECT_EQ(net::ERR_ABORTED, last_status().error());
+ EXPECT_TRUE(async_revalidation_complete_called());
+}
+
+// A mock URLRequestJob which simulates an SSL client auth request.
+class MockClientCertURLRequestJob : public net::URLRequestTestJob {
+ public:
+ MockClientCertURLRequestJob(net::URLRequest* request,
+ net::NetworkDelegate* network_delegate)
+ : net::URLRequestTestJob(request, network_delegate, true),
+ weak_factory_(this) {}
+
+ // net::URLRequestTestJob implementation:
+ void Start() override {
+ scoped_refptr<net::SSLCertRequestInfo> cert_request_info(
+ new net::SSLCertRequestInfo);
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::Bind(&MockClientCertURLRequestJob::NotifyCertificateRequested,
+ weak_factory_.GetWeakPtr(), cert_request_info));
+ }
+
+ void ContinueWithCertificate(
+ net::X509Certificate* cert,
+ net::SSLPrivateKey* client_private_key) override {
+ ADD_FAILURE() << "Certificate supplied.";
+ }
+
+ void Kill() override {
+ weak_factory_.InvalidateWeakPtrs();
+ URLRequestJob::Kill();
+ }
+
+ private:
+ base::WeakPtrFactory<MockClientCertURLRequestJob> weak_factory_;
+};
+
+class AsyncRevalidationDriverClientCertTest
+ : public AsyncRevalidationDriverTest {
+ protected:
+ AsyncRevalidationDriverClientCertTest()
+ : AsyncRevalidationDriverTest(
+ BindCreateProtocolHandlerCallback<MockClientCertURLRequestJob>()) {}
+};
+
+// Test browser client that causes the test to fail if SelectClientCertificate()
+// is called. Automatically sets itself as the browser client when constructed
+// and restores the old browser client in the destructor.
+class ScopedDontSelectCertificateBrowserClient
+ : public TestContentBrowserClient {
+ public:
+ ScopedDontSelectCertificateBrowserClient() {
+ old_client_ = SetBrowserClientForTesting(this);
+ }
+
+ ~ScopedDontSelectCertificateBrowserClient() override {
+ SetBrowserClientForTesting(old_client_);
+ }
+
+ void SelectClientCertificate(
+ WebContents* web_contents,
+ net::SSLCertRequestInfo* cert_request_info,
+ scoped_ptr<ClientCertificateDelegate> delegate) override {
+ ADD_FAILURE() << "SelectClientCertificate was called.";
+ }
+
+ private:
+ ContentBrowserClient* old_client_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedDontSelectCertificateBrowserClient);
+};
+
+// Verifies that async revalidation requests do not attempt to provide client
+// certificates.
+TEST_F(AsyncRevalidationDriverClientCertTest, RequestRejected) {
+ // Ensure that SelectClientCertificate is not called during this test.
+ ScopedDontSelectCertificateBrowserClient test_client;
+
+ // Start the request and wait for it to pause.
+ driver_->StartRequest();
+
+ // Because TestBrowserThreadBundle only uses one real thread, this is
+ // sufficient to ensure that tasks posted to the "UI thread" have run.
+ base::RunLoop().RunUntilIdle();
+
+ // Check that the request aborted.
+ EXPECT_FALSE(last_status().is_success());
+ EXPECT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, last_status().error());
+ EXPECT_TRUE(async_revalidation_complete_called());
+}
+
+// A mock URLRequestJob which simulates an SSL certificate error.
+class MockSSLErrorURLRequestJob : public net::URLRequestTestJob {
+ public:
+ MockSSLErrorURLRequestJob(net::URLRequest* request,
+ net::NetworkDelegate* network_delegate)
+ : net::URLRequestTestJob(request, network_delegate, true),
+ weak_factory_(this) {}
+
+ // net::URLRequestTestJob implementation:
+ void Start() override {
+ // This SSLInfo isn't really valid, but it is good enough for testing.
+ net::SSLInfo ssl_info;
+ ssl_info.SetCertError(net::ERR_CERT_DATE_INVALID);
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::Bind(&MockSSLErrorURLRequestJob::NotifySSLCertificateError,
+ weak_factory_.GetWeakPtr(), ssl_info, false));
+ }
+
+ void ContinueDespiteLastError() override {
+ ADD_FAILURE() << "ContinueDespiteLastError called.";
+ }
+
+ private:
+ base::WeakPtrFactory<MockSSLErrorURLRequestJob> weak_factory_;
+};
+
+class AsyncRevalidationDriverSSLErrorTest : public AsyncRevalidationDriverTest {
+ protected:
+ AsyncRevalidationDriverSSLErrorTest()
+ : AsyncRevalidationDriverTest(
+ BindCreateProtocolHandlerCallback<MockSSLErrorURLRequestJob>()) {}
+};
+
+// Verifies that async revalidation requests do not attempt to recover from SSL
+// certificate errors.
+TEST_F(AsyncRevalidationDriverSSLErrorTest, RequestWithSSLErrorRejected) {
+ // Start the request and wait for it to pause.
+ driver_->StartRequest();
+ base::RunLoop().RunUntilIdle();
+
+ // Check that the request has been aborted.
+ EXPECT_FALSE(last_status().is_success());
+ EXPECT_EQ(net::ERR_ABORTED, last_status().error());
+ EXPECT_TRUE(async_revalidation_complete_called());
+}
+
+// A URLRequestTestJob that sets |request_time| and |was_cached| on their
+// response_info, and causes the test to fail if Read() is called.
+class FromCacheURLRequestJob : public net::URLRequestTestJob {
+ public:
+ FromCacheURLRequestJob(net::URLRequest* request,
+ net::NetworkDelegate* network_delegate)
+ : net::URLRequestTestJob(request, network_delegate, true) {}
+
+ void GetResponseInfo(net::HttpResponseInfo* info) override {
+ URLRequestTestJob::GetResponseInfo(info);
+ info->request_time = base::Time::Now();
+ info->was_cached = true;
+ }
+
+ int ReadRawData(net::IOBuffer* buf, int buf_size) override {
+ ADD_FAILURE() << "ReadRawData() was called.";
+ return URLRequestTestJob::ReadRawData(buf, buf_size);
+ }
+
+ private:
+ ~FromCacheURLRequestJob() override {}
+
+ DISALLOW_COPY_AND_ASSIGN(FromCacheURLRequestJob);
+};
+
+class AsyncRevalidationDriverFromCacheTest
+ : public AsyncRevalidationDriverTest {
+ protected:
+ AsyncRevalidationDriverFromCacheTest()
+ : AsyncRevalidationDriverTest(
+ BindCreateProtocolHandlerCallback<FromCacheURLRequestJob>()) {}
+};
+
+TEST_F(AsyncRevalidationDriverFromCacheTest,
+ CacheNotReadOnSuccessfulRevalidation) {
+ driver_->StartRequest();
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(async_revalidation_complete_called());
+}
+
+} // namespace
+} // namespace content
« no previous file with comments | « content/browser/loader/async_revalidation_driver.cc ('k') | content/browser/loader/async_revalidation_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698