Chromium Code Reviews| Index: net/url_request/url_request_unittest.cc |
| diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc |
| index 139b6f3ee270e404ab14d9d93af038a02184c667..8b42c3785e676ee76f0e5ef390a9dc440ee9fc6b 100644 |
| --- a/net/url_request/url_request_unittest.cc |
| +++ b/net/url_request/url_request_unittest.cc |
| @@ -72,6 +72,8 @@ |
| #include "net/url_request/static_http_user_agent_settings.h" |
| #include "net/url_request/url_request.h" |
| #include "net/url_request/url_request_http_job.h" |
| +#include "net/url_request/url_request_intercepting_job_factory.h" |
| +#include "net/url_request/url_request_interceptor.h" |
| #include "net/url_request/url_request_job_factory_impl.h" |
| #include "net/url_request/url_request_redirect_job.h" |
| #include "net/url_request/url_request_test_job.h" |
| @@ -607,31 +609,52 @@ class URLRequestTest : public PlatformTest { |
| URLRequestTest() : default_context_(true) { |
| default_context_.set_network_delegate(&default_network_delegate_); |
| default_context_.set_net_log(&net_log_); |
| - job_factory_.SetProtocolHandler("data", new DataProtocolHandler); |
| -#if !defined(DISABLE_FILE_SUPPORT) |
| - job_factory_.SetProtocolHandler( |
| - "file", new FileProtocolHandler(base::MessageLoopProxy::current())); |
| -#endif |
| - default_context_.set_job_factory(&job_factory_); |
| - default_context_.Init(); |
| + job_factory_impl_ = new URLRequestJobFactoryImpl(); |
| + job_factory_.reset(job_factory_impl_); |
| } |
| + |
| ~URLRequestTest() override { |
| // URLRequestJobs may post clean-up tasks on destruction. |
| base::RunLoop().RunUntilIdle(); |
| } |
| + virtual void SetUp() { |
| + SetUpFactory(); |
| + default_context_.set_job_factory(job_factory_.get()); |
| + default_context_.Init(); |
| + PlatformTest::SetUp(); |
| + } |
| + |
| + virtual void SetUpFactory() { |
| + job_factory_impl_->SetProtocolHandler("data", new DataProtocolHandler); |
| +#if !defined(DISABLE_FILE_SUPPORT) |
| + job_factory_impl_->SetProtocolHandler( |
| + "file", new FileProtocolHandler(base::MessageLoopProxy::current())); |
| +#endif |
| + } |
| + |
| + TestNetworkDelegate* default_network_delegate() { |
| + return &default_network_delegate_; |
| + } |
| + |
| + const TestURLRequestContext& default_context() const { |
| + return default_context_; |
| + } |
| + |
| + |
| // Adds the TestJobInterceptor to the default context. |
| TestJobInterceptor* AddTestInterceptor() { |
| TestJobInterceptor* protocol_handler_ = new TestJobInterceptor(); |
| - job_factory_.SetProtocolHandler("http", NULL); |
| - job_factory_.SetProtocolHandler("http", protocol_handler_); |
| + job_factory_impl_->SetProtocolHandler("http", NULL); |
| + job_factory_impl_->SetProtocolHandler("http", protocol_handler_); |
| return protocol_handler_; |
| } |
| protected: |
| CapturingNetLog net_log_; |
| TestNetworkDelegate default_network_delegate_; // Must outlive URLRequest. |
| - URLRequestJobFactoryImpl job_factory_; |
| + URLRequestJobFactoryImpl* job_factory_impl_; |
| + scoped_ptr<URLRequestJobFactory> job_factory_; |
| TestURLRequestContext default_context_; |
| }; |
| @@ -1574,29 +1597,570 @@ TEST_F(URLRequestTest, InterceptRespectsCancelInRestart) { |
| EXPECT_EQ(URLRequestStatus::CANCELED, req->status().status()); |
| } |
| -LoadTimingInfo RunLoadTimingTest(const LoadTimingInfo& job_load_timing, |
| - URLRequestContext* context) { |
| - TestInterceptor interceptor; |
| - interceptor.intercept_main_request_ = true; |
| - interceptor.main_request_load_timing_info_ = job_load_timing; |
| +// An Interceptor for use with interceptor tests. |
| +class MockURLRequestInterceptor : public URLRequestInterceptor { |
| + public: |
| + // Static getters for canned response header and data strings. |
| + static std::string ok_data() { |
| + return URLRequestTestJob::test_data_1(); |
| + } |
| + |
| + static std::string ok_headers() { |
| + return URLRequestTestJob::test_headers(); |
| + } |
| + |
| + static std::string redirect_data() { |
| + return std::string(); |
| + } |
| + |
| + static std::string redirect_headers() { |
| + return URLRequestTestJob::test_redirect_headers(); |
| + } |
| + |
| + static std::string error_data() { |
| + return std::string("ohhh nooooo mr. bill!"); |
| + } |
| + |
| + static std::string error_headers() { |
| + return URLRequestTestJob::test_error_headers(); |
| + } |
| + |
| + MockURLRequestInterceptor() |
| + : intercept_main_request_(false), restart_main_request_(false), |
| + cancel_main_request_(false), cancel_then_restart_main_request_(false), |
| + simulate_main_network_error_(false), |
| + intercept_redirect_(false), cancel_redirect_request_(false), |
| + intercept_final_response_(false), cancel_final_request_(false), |
| + use_url_request_http_job_(false), |
| + did_intercept_main_(false), did_restart_main_(false), |
| + did_cancel_main_(false), did_cancel_then_restart_main_(false), |
| + did_simulate_error_main_(false), |
| + did_intercept_redirect_(false), did_cancel_redirect_(false), |
| + did_intercept_final_(false), did_cancel_final_(false) { |
| + } |
| + |
| + ~MockURLRequestInterceptor() override { |
| + } |
| + |
| + // URLRequestInterceptor implementation: |
| + URLRequestJob* MaybeInterceptRequest( |
| + URLRequest* request, |
| + NetworkDelegate* network_delegate) const override { |
| + if (restart_main_request_) { |
| + restart_main_request_ = false; |
| + did_restart_main_ = true; |
| + return new RestartTestJob(request, network_delegate); |
| + } |
| + if (cancel_main_request_) { |
| + cancel_main_request_ = false; |
| + did_cancel_main_ = true; |
| + return new CancelTestJob(request, network_delegate); |
| + } |
| + if (cancel_then_restart_main_request_) { |
| + cancel_then_restart_main_request_ = false; |
| + did_cancel_then_restart_main_ = true; |
| + return new CancelThenRestartTestJob(request, network_delegate); |
| + } |
| + if (simulate_main_network_error_) { |
| + simulate_main_network_error_ = false; |
| + did_simulate_error_main_ = true; |
| + if (use_url_request_http_job_) { |
| + return URLRequestHttpJob::Factory(request, network_delegate, "http"); |
| + } |
| + // This job will result in error since the requested URL is not one of the |
| + // URLs supported by these tests. |
| + return new URLRequestTestJob(request, network_delegate, true); |
| + } |
| + if (!intercept_main_request_) |
| + return nullptr; |
| + intercept_main_request_ = false; |
| + did_intercept_main_ = true; |
| + URLRequestTestJob* job = new URLRequestTestJob(request, |
| + network_delegate, |
| + main_headers_, |
| + main_data_, |
| + true); |
| + job->set_load_timing_info(main_request_load_timing_info_); |
| + return job; |
| + } |
| + |
| + URLRequestJob* MaybeInterceptRedirect(URLRequest* request, |
| + NetworkDelegate* network_delegate, |
| + const GURL& location) const override { |
| + if (cancel_redirect_request_) { |
| + cancel_redirect_request_ = false; |
| + did_cancel_redirect_ = true; |
| + return new CancelTestJob(request, network_delegate); |
| + } |
| + if (!intercept_redirect_) |
| + return nullptr; |
| + intercept_redirect_ = false; |
| + did_intercept_redirect_ = true; |
| + if (use_url_request_http_job_) { |
| + return URLRequestHttpJob::Factory(request, network_delegate, "http"); |
| + } |
| + return new URLRequestTestJob(request, |
| + network_delegate, |
| + redirect_headers_, |
| + redirect_data_, |
| + true); |
| + } |
| + |
| + URLRequestJob* MaybeInterceptResponse( |
| + URLRequest* request, |
| + NetworkDelegate* network_delegate) const override { |
| + if (cancel_final_request_) { |
| + cancel_final_request_ = false; |
| + did_cancel_final_ = true; |
| + return new CancelTestJob(request, network_delegate); |
| + } |
| + if (!intercept_final_response_) |
| + return nullptr; |
| + intercept_final_response_ = false; |
| + did_intercept_final_ = true; |
| + if (use_url_request_http_job_) { |
| + return URLRequestHttpJob::Factory(request, network_delegate, "http"); |
| + } |
| + return new URLRequestTestJob(request, |
| + network_delegate, |
| + final_headers_, |
| + final_data_, |
| + true); |
| + } |
| + |
| + void set_intercept_main_request(bool intercept_main_request) { |
| + intercept_main_request_ = intercept_main_request; |
| + } |
| + |
| + void set_main_headers(const std::string& main_headers) { |
| + main_headers_ = main_headers; |
| + } |
| + |
| + void set_main_data(const std::string& main_data) { |
| + main_data_ = main_data; |
| + } |
| + |
| + void set_main_request_load_timing_info( |
| + const LoadTimingInfo& main_request_load_timing_info) { |
| + main_request_load_timing_info_ = main_request_load_timing_info; |
| + } |
| + |
| + void set_restart_main_request(bool restart_main_request) { |
| + restart_main_request_ = restart_main_request; |
| + } |
| + |
| + void set_cancel_main_request(bool cancel_main_request) { |
| + cancel_main_request_ = cancel_main_request; |
| + } |
| + |
| + void set_cancel_then_restart_main_request( |
| + bool cancel_then_restart_main_request) { |
| + cancel_then_restart_main_request_ = cancel_then_restart_main_request; |
| + } |
| + |
| + void set_simulate_main_network_error(bool simulate_main_network_error) { |
| + simulate_main_network_error_ = simulate_main_network_error; |
| + } |
| + |
| + void set_intercept_redirect(bool intercept_redirect) { |
| + intercept_redirect_ = intercept_redirect; |
| + } |
| + |
| + void set_redirect_headers(const std::string& redirect_headers) { |
| + redirect_headers_ = redirect_headers; |
| + } |
| + |
| + void set_redirect_data(const std::string& redirect_data) { |
| + redirect_data_ = redirect_data; |
| + } |
| + |
| + void set_cancel_redirect_request(bool cancel_redirect_request) { |
| + cancel_redirect_request_ = cancel_redirect_request; |
| + } |
| + |
| + void set_intercept_final_response(bool intercept_final_response) { |
| + intercept_final_response_ = intercept_final_response; |
| + } |
| + |
| + void set_final_headers(const std::string& final_headers) { |
| + final_headers_ = final_headers; |
| + } |
| + |
| + void set_final_data(const std::string& final_data) { |
| + final_data_ = final_data; |
| + } |
| + |
| + void set_cancel_final_request(bool cancel_final_request) { |
| + cancel_final_request_ = cancel_final_request; |
| + } |
| + |
| + void set_use_url_request_http_job(bool use_url_request_http_job) { |
| + use_url_request_http_job_ = use_url_request_http_job; |
| + } |
| + |
| + bool did_intercept_main() const { |
| + return did_intercept_main_; |
| + } |
| + |
| + bool did_restart_main() const { |
| + return did_restart_main_; |
| + } |
| + |
| + bool did_cancel_main() const { |
| + return did_cancel_main_; |
| + } |
| + |
| + bool did_cancel_then_restart_main() const { |
| + return did_cancel_then_restart_main_; |
| + } |
| + |
| + bool did_simulate_error_main() const { |
| + return did_simulate_error_main_; |
| + } |
| + |
| + bool did_intercept_redirect() const { |
| + return did_intercept_redirect_; |
| + } |
| + |
| + bool did_cancel_redirect() const { |
| + return did_cancel_redirect_; |
| + } |
| + |
| + bool did_intercept_final() const { |
| + return did_intercept_final_; |
| + } |
| + |
| + bool did_cancel_final() const { |
| + return did_cancel_final_; |
| + } |
| + |
| + private: |
| + // Indicate whether to intercept the main request, and if so specify the |
| + // response to return and the LoadTimingInfo to use. |
| + mutable bool intercept_main_request_; |
| + mutable std::string main_headers_; |
| + mutable std::string main_data_; |
| + mutable LoadTimingInfo main_request_load_timing_info_; |
| + |
| + // These indicate actions that can be taken within MaybeInterceptRequest. |
| + mutable bool restart_main_request_; |
| + mutable bool cancel_main_request_; |
| + mutable bool cancel_then_restart_main_request_; |
| + mutable bool simulate_main_network_error_; |
| + |
| + // Indicate whether to intercept redirects, and if so specify the response to |
| + // return. |
| + mutable bool intercept_redirect_; |
| + mutable std::string redirect_headers_; |
| + mutable std::string redirect_data_; |
| + |
| + // Cancel the request within MaybeInterceptRedirect. |
| + mutable bool cancel_redirect_request_; |
| + |
| + // Indicate whether to intercept the final response, and if so specify the |
| + // response to return. |
| + mutable bool intercept_final_response_; |
| + mutable std::string final_headers_; |
| + mutable std::string final_data_; |
| + |
| + // Cancel the final request within MaybeInterceptResponse. |
| + mutable bool cancel_final_request_; |
| + |
| + // Instruct the interceptor to use a real URLRequestHTTPJob. |
| + mutable bool use_url_request_http_job_; |
| + |
| + // These indicate if the interceptor did something or not. |
| + mutable bool did_intercept_main_; |
| + mutable bool did_restart_main_; |
| + mutable bool did_cancel_main_; |
| + mutable bool did_cancel_then_restart_main_; |
| + mutable bool did_simulate_error_main_; |
| + mutable bool did_intercept_redirect_; |
| + mutable bool did_cancel_redirect_; |
| + mutable bool did_intercept_final_; |
| + mutable bool did_cancel_final_; |
| +}; |
| + |
| +// Inherit PlatformTest since we require the autorelease pool on Mac OS X. |
| +class URLRequestInterceptorTest : public URLRequestTest { |
| + public: |
| + URLRequestInterceptorTest() : URLRequestTest(), interceptor_(NULL) { |
| + } |
| + |
| + ~URLRequestInterceptorTest() override { |
| + // URLRequestJobs may post clean-up tasks on destruction. |
| + base::RunLoop().RunUntilIdle(); |
| + } |
| + |
| + void SetUpFactory() override { |
| + interceptor_ = new MockURLRequestInterceptor(); |
| + job_factory_.reset(new URLRequestInterceptingJobFactory( |
| + job_factory_.Pass(), make_scoped_ptr(interceptor_))); |
| + } |
| + |
| + MockURLRequestInterceptor* interceptor() const { |
| + return interceptor_; |
| + } |
| + |
| + private: |
| + MockURLRequestInterceptor* interceptor_; |
| +}; |
| + |
| +TEST_F(URLRequestInterceptorTest, Intercept) { |
| + // Intercept the main request and respond with a simple response. |
| + interceptor()->set_intercept_main_request(true); |
| + interceptor()->set_main_headers(MockURLRequestInterceptor::ok_headers()); |
| + interceptor()->set_main_data(MockURLRequestInterceptor::ok_data()); |
| TestDelegate d; |
| - scoped_ptr<URLRequest> req(context->CreateRequest( |
| - GURL("http://test_intercept/foo"), DEFAULT_PRIORITY, &d, NULL)); |
| + scoped_ptr<URLRequest> req(default_context().CreateRequest( |
| + GURL("http://test_intercept/foo"), DEFAULT_PRIORITY, &d, nullptr)); |
| + base::SupportsUserData::Data* user_data0 = new base::SupportsUserData::Data(); |
| + base::SupportsUserData::Data* user_data1 = new base::SupportsUserData::Data(); |
| + base::SupportsUserData::Data* user_data2 = new base::SupportsUserData::Data(); |
| + req->SetUserData(nullptr, user_data0); |
| + req->SetUserData(&user_data1, user_data1); |
| + req->SetUserData(&user_data2, user_data2); |
| + req->set_method("GET"); |
| req->Start(); |
| base::RunLoop().Run(); |
| - LoadTimingInfo resulting_load_timing; |
| - req->GetLoadTimingInfo(&resulting_load_timing); |
| + // Make sure we can retrieve our specific user data. |
| + EXPECT_EQ(user_data0, req->GetUserData(nullptr)); |
| + EXPECT_EQ(user_data1, req->GetUserData(&user_data1)); |
| + EXPECT_EQ(user_data2, req->GetUserData(&user_data2)); |
| - // None of these should be modified by the URLRequest. |
| - EXPECT_EQ(job_load_timing.socket_reused, resulting_load_timing.socket_reused); |
| - EXPECT_EQ(job_load_timing.socket_log_id, resulting_load_timing.socket_log_id); |
| - EXPECT_EQ(job_load_timing.send_start, resulting_load_timing.send_start); |
| - EXPECT_EQ(job_load_timing.send_end, resulting_load_timing.send_end); |
| - EXPECT_EQ(job_load_timing.receive_headers_end, |
| - resulting_load_timing.receive_headers_end); |
| + // Check that we got one good response. |
| + EXPECT_TRUE(req->status().is_success()); |
| + EXPECT_EQ(200, req->response_headers()->response_code()); |
| + EXPECT_EQ(MockURLRequestInterceptor::ok_data(), d.data_received()); |
| + EXPECT_EQ(1, d.response_started_count()); |
| + EXPECT_EQ(0, d.received_redirect_count()); |
| +} |
| - return resulting_load_timing; |
| +TEST_F(URLRequestInterceptorTest, InterceptRedirect) { |
| + // Intercept the main request and respond with a redirect. |
| + interceptor()->set_intercept_main_request(true); |
| + interceptor()->set_main_headers( |
| + MockURLRequestInterceptor::redirect_headers()); |
| + interceptor()->set_main_data(MockURLRequestInterceptor::redirect_data()); |
| + |
| + // Intercept that redirect and respond with a final OK response. |
| + interceptor()->set_intercept_redirect(true); |
| + interceptor()->set_redirect_headers(MockURLRequestInterceptor::ok_headers()); |
| + interceptor()->set_redirect_data(MockURLRequestInterceptor::ok_data()); |
| + |
| + TestDelegate d; |
| + scoped_ptr<URLRequest> req(default_context().CreateRequest( |
| + GURL("http://test_intercept/foo"), DEFAULT_PRIORITY, &d, nullptr)); |
| + req->set_method("GET"); |
| + req->Start(); |
| + base::RunLoop().Run(); |
| + |
| + // Check that the interceptor got called as expected. |
| + EXPECT_TRUE(interceptor()->did_intercept_main()); |
| + EXPECT_TRUE(interceptor()->did_intercept_redirect()); |
| + |
| + // Check that we got one good response. |
| + EXPECT_TRUE(req->status().is_success()); |
| + if (req->status().is_success()) |
| + EXPECT_EQ(200, req->response_headers()->response_code()); |
| + |
| + EXPECT_EQ(MockURLRequestInterceptor::ok_data(), d.data_received()); |
| + EXPECT_EQ(1, d.response_started_count()); |
| + EXPECT_EQ(0, d.received_redirect_count()); |
| +} |
| + |
| +TEST_F(URLRequestInterceptorTest, InterceptServerError) { |
| + // Intercept the main request to generate a server error response. |
| + interceptor()->set_intercept_main_request(true); |
| + interceptor()->set_main_headers(MockURLRequestInterceptor::error_headers()); |
| + interceptor()->set_main_data(MockURLRequestInterceptor::error_data()); |
| + |
| + // Intercept that error and respond with an OK response. |
| + interceptor()->set_intercept_final_response(true); |
| + interceptor()->set_final_headers(MockURLRequestInterceptor::ok_headers()); |
| + interceptor()->set_final_data(MockURLRequestInterceptor::ok_data()); |
| + |
| + TestDelegate d; |
| + scoped_ptr<URLRequest> req(default_context().CreateRequest( |
| + GURL("http://test_intercept/foo"), DEFAULT_PRIORITY, &d, nullptr)); |
| + req->set_method("GET"); |
| + req->Start(); |
| + base::RunLoop().Run(); |
| + |
| + // Check that the interceptor got called as expected. |
| + EXPECT_TRUE(interceptor()->did_intercept_main()); |
| + EXPECT_TRUE(interceptor()->did_intercept_final()); |
| + |
| + // Check that we got one good response. |
| + EXPECT_TRUE(req->status().is_success()); |
| + EXPECT_EQ(200, req->response_headers()->response_code()); |
| + EXPECT_EQ(MockURLRequestInterceptor::ok_data(), d.data_received()); |
| + EXPECT_EQ(1, d.response_started_count()); |
| + EXPECT_EQ(0, d.received_redirect_count()); |
| +} |
| + |
| +TEST_F(URLRequestInterceptorTest, InterceptNetworkError) { |
| + // Intercept the main request to simulate a network error. |
| + interceptor()->set_simulate_main_network_error(true); |
| + |
| + // Intercept that error and respond with an OK response. |
| + interceptor()->set_intercept_final_response(true); |
| + interceptor()->set_final_headers(MockURLRequestInterceptor::ok_headers()); |
| + interceptor()->set_final_data(MockURLRequestInterceptor::ok_data()); |
| + |
| + TestDelegate d; |
| + scoped_ptr<URLRequest> req(default_context().CreateRequest( |
| + GURL("http://test_intercept/foo"), DEFAULT_PRIORITY, &d, nullptr)); |
| + req->set_method("GET"); |
| + req->Start(); |
| + base::RunLoop().Run(); |
| + |
| + // Check that the interceptor got called as expected. |
| + EXPECT_TRUE(interceptor()->did_simulate_error_main()); |
| + EXPECT_TRUE(interceptor()->did_intercept_final()); |
| + |
| + // Check that we received one good response. |
| + EXPECT_TRUE(req->status().is_success()); |
| + EXPECT_EQ(200, req->response_headers()->response_code()); |
| + EXPECT_EQ(MockURLRequestInterceptor::ok_data(), d.data_received()); |
| + EXPECT_EQ(1, d.response_started_count()); |
| + EXPECT_EQ(0, d.received_redirect_count()); |
| +} |
| + |
| +TEST_F(URLRequestInterceptorTest, InterceptRestartRequired) { |
| + // Restart the main request. |
| + interceptor()->set_restart_main_request(true); |
| + |
| + // then intercept the new main request and respond with an OK response |
| + interceptor()->set_intercept_main_request(true); |
| + interceptor()->set_main_headers(MockURLRequestInterceptor::ok_headers()); |
| + interceptor()->set_main_data(MockURLRequestInterceptor::ok_data()); |
| + |
| + TestDelegate d; |
| + scoped_ptr<URLRequest> req(default_context().CreateRequest( |
| + GURL("http://test_intercept/foo"), DEFAULT_PRIORITY, &d, nullptr)); |
| + req->set_method("GET"); |
| + req->Start(); |
| + base::RunLoop().Run(); |
| + |
| + // Check that the interceptor got called as expected. |
| + EXPECT_TRUE(interceptor()->did_restart_main()); |
| + EXPECT_TRUE(interceptor()->did_intercept_main()); |
| + |
| + // Check that we received one good response. |
| + EXPECT_TRUE(req->status().is_success()); |
| + if (req->status().is_success()) |
| + EXPECT_EQ(200, req->response_headers()->response_code()); |
| + |
| + EXPECT_EQ(MockURLRequestInterceptor::ok_data(), d.data_received()); |
| + EXPECT_EQ(1, d.response_started_count()); |
| + EXPECT_EQ(0, d.received_redirect_count()); |
| +} |
| + |
| +TEST_F(URLRequestInterceptorTest, InterceptRespectsCancelMain) { |
| + // Intercept the main request and cancel from within the restarted job. |
| + interceptor()->set_cancel_main_request(true); |
| + |
| + // Set up to intercept the final response and override it with an OK response. |
| + interceptor()->set_intercept_final_response(true); |
| + interceptor()->set_final_headers(MockURLRequestInterceptor::ok_headers()); |
| + interceptor()->set_final_data(MockURLRequestInterceptor::ok_data()); |
| + |
| + TestDelegate d; |
| + scoped_ptr<URLRequest> req(default_context().CreateRequest( |
| + GURL("http://test_intercept/foo"), DEFAULT_PRIORITY, &d, nullptr)); |
| + req->set_method("GET"); |
| + req->Start(); |
| + base::RunLoop().Run(); |
| + |
| + // Check that the interceptor got called as expected. |
| + EXPECT_TRUE(interceptor()->did_cancel_main()); |
| + EXPECT_FALSE(interceptor()->did_intercept_final()); |
| + |
| + // Check that we see a canceled request. |
| + EXPECT_FALSE(req->status().is_success()); |
| + EXPECT_EQ(URLRequestStatus::CANCELED, req->status().status()); |
| +} |
| + |
| +TEST_F(URLRequestInterceptorTest, InterceptRespectsCancelRedirect) { |
| + // Intercept the main request and respond with a redirect. |
| + interceptor()->set_intercept_main_request(true); |
| + interceptor()->set_main_headers( |
| + MockURLRequestInterceptor::redirect_headers()); |
| + interceptor()->set_main_data(MockURLRequestInterceptor::redirect_data()); |
| + |
| + // Intercept the redirect and cancel from within that job. |
| + interceptor()->set_cancel_redirect_request(true); |
| + |
| + // Set up to intercept the final response and override it with an OK response. |
| + interceptor()->set_intercept_final_response(true); |
| + interceptor()->set_final_headers(MockURLRequestInterceptor::ok_headers()); |
| + interceptor()->set_final_data(MockURLRequestInterceptor::ok_data()); |
| + |
| + TestDelegate d; |
| + scoped_ptr<URLRequest> req(default_context().CreateRequest( |
| + GURL("http://test_intercept/foo"), DEFAULT_PRIORITY, &d, nullptr)); |
| + req->set_method("GET"); |
| + req->Start(); |
| + base::RunLoop().Run(); |
| + |
| + // Check that the interceptor got called as expected. |
| + EXPECT_TRUE(interceptor()->did_intercept_main()); |
| + EXPECT_TRUE(interceptor()->did_cancel_redirect()); |
| + EXPECT_FALSE(interceptor()->did_intercept_final()); |
| + |
| + // Check that we see a canceled request. |
| + EXPECT_FALSE(req->status().is_success()); |
| + EXPECT_EQ(URLRequestStatus::CANCELED, req->status().status()); |
| +} |
| + |
| +TEST_F(URLRequestInterceptorTest, InterceptRespectsCancelFinal) { |
| + // Intercept the main request to simulate a network error. |
| + interceptor()->set_simulate_main_network_error(true); |
| + |
| + // Set up to intercept final the response and cancel from within that job. |
| + interceptor()->set_cancel_final_request(true); |
| + |
| + TestDelegate d; |
| + scoped_ptr<URLRequest> req(default_context().CreateRequest( |
| + GURL("http://test_intercept/foo"), DEFAULT_PRIORITY, &d, nullptr)); |
| + req->set_method("GET"); |
| + req->Start(); |
| + base::RunLoop().Run(); |
| + |
| + // Check that the interceptor got called as expected. |
| + EXPECT_TRUE(interceptor()->did_simulate_error_main()); |
| + EXPECT_TRUE(interceptor()->did_cancel_final()); |
| + |
| + // Check that we see a canceled request. |
| + EXPECT_FALSE(req->status().is_success()); |
| + EXPECT_EQ(URLRequestStatus::CANCELED, req->status().status()); |
| +} |
| + |
| +TEST_F(URLRequestInterceptorTest, InterceptRespectsCancelInRestart) { |
| + // Intercept the main request and cancel then restart from within that job. |
| + interceptor()->set_cancel_then_restart_main_request(true); |
| + |
| + // Set up to intercept the final response and override it with an OK response. |
| + interceptor()->set_intercept_final_response(true); |
| + interceptor()->set_final_headers(TestInterceptor::ok_headers()); |
| + interceptor()->set_final_data(TestInterceptor::ok_data()); |
| + |
| + TestDelegate d; |
| + scoped_ptr<URLRequest> req(default_context().CreateRequest( |
| + GURL("http://test_intercept/foo"), DEFAULT_PRIORITY, &d, nullptr)); |
| + req->set_method("GET"); |
| + req->Start(); |
| + base::RunLoop().Run(); |
| + |
| + // Check that the interceptor got called as expected. |
| + EXPECT_TRUE(interceptor()->did_cancel_then_restart_main()); |
| + EXPECT_FALSE(interceptor()->did_intercept_final()); |
| + |
| + // Check that we see a canceled request. |
| + EXPECT_FALSE(req->status().is_success()); |
| + EXPECT_EQ(URLRequestStatus::CANCELED, req->status().status()); |
| } |
| // "Normal" LoadTimingInfo as returned by a job. Everything is in order, not |
| @@ -1649,14 +2213,41 @@ LoadTimingInfo NormalLoadTimingInfoReused(base::TimeTicks now, |
| return load_timing; |
| } |
| +LoadTimingInfo RunURLRequestInterceptorLoadTimingTest( |
| + const LoadTimingInfo& job_load_timing, |
| + const URLRequestContext& context, |
| + MockURLRequestInterceptor* interceptor) { |
| + interceptor->set_intercept_main_request(true); |
| + interceptor->set_main_request_load_timing_info(job_load_timing); |
| + TestDelegate d; |
| + scoped_ptr<URLRequest> req(context.CreateRequest( |
| + GURL("http://test_intercept/foo"), DEFAULT_PRIORITY, &d, nullptr)); |
| + req->Start(); |
| + base::RunLoop().Run(); |
| + |
| + LoadTimingInfo resulting_load_timing; |
| + req->GetLoadTimingInfo(&resulting_load_timing); |
| + |
| + // None of these should be modified by the URLRequest. |
| + EXPECT_EQ(job_load_timing.socket_reused, resulting_load_timing.socket_reused); |
| + EXPECT_EQ(job_load_timing.socket_log_id, resulting_load_timing.socket_log_id); |
| + EXPECT_EQ(job_load_timing.send_start, resulting_load_timing.send_start); |
| + EXPECT_EQ(job_load_timing.send_end, resulting_load_timing.send_end); |
| + EXPECT_EQ(job_load_timing.receive_headers_end, |
| + resulting_load_timing.receive_headers_end); |
| + |
| + return resulting_load_timing; |
| +} |
| + |
| // Basic test that the intercept + load timing tests work. |
| -TEST_F(URLRequestTest, InterceptLoadTiming) { |
| +TEST_F(URLRequestInterceptorTest, InterceptLoadTiming) { |
| base::TimeTicks now = base::TimeTicks::Now(); |
| LoadTimingInfo job_load_timing = |
| NormalLoadTimingInfo(now, CONNECT_TIMING_HAS_DNS_TIMES, false); |
| LoadTimingInfo load_timing_result = |
| - RunLoadTimingTest(job_load_timing, &default_context_); |
| + RunURLRequestInterceptorLoadTimingTest( |
| + job_load_timing, default_context(), interceptor()); |
| // Nothing should have been changed by the URLRequest. |
| EXPECT_EQ(job_load_timing.proxy_resolve_start, |
| @@ -1681,13 +2272,14 @@ TEST_F(URLRequestTest, InterceptLoadTiming) { |
| } |
| // Another basic test, with proxy and SSL times, but no DNS times. |
| -TEST_F(URLRequestTest, InterceptLoadTimingProxy) { |
| +TEST_F(URLRequestInterceptorTest, InterceptLoadTimingProxy) { |
| base::TimeTicks now = base::TimeTicks::Now(); |
| LoadTimingInfo job_load_timing = |
| NormalLoadTimingInfo(now, CONNECT_TIMING_HAS_SSL_TIMES, true); |
| LoadTimingInfo load_timing_result = |
| - RunLoadTimingTest(job_load_timing, &default_context_); |
| + RunURLRequestInterceptorLoadTimingTest( |
| + job_load_timing, default_context(), interceptor()); |
| // Nothing should have been changed by the URLRequest. |
| EXPECT_EQ(job_load_timing.proxy_resolve_start, |
| @@ -1718,7 +2310,7 @@ TEST_F(URLRequestTest, InterceptLoadTimingProxy) { |
| // reused in this test (May be a preconnect). |
| // |
| // To mix things up from the test above, assumes DNS times but no SSL times. |
| -TEST_F(URLRequestTest, InterceptLoadTimingEarlyProxyResolution) { |
| +TEST_F(URLRequestInterceptorTest, InterceptLoadTimingEarlyProxyResolution) { |
| base::TimeTicks now = base::TimeTicks::Now(); |
| LoadTimingInfo job_load_timing = |
| NormalLoadTimingInfo(now, CONNECT_TIMING_HAS_DNS_TIMES, true); |
| @@ -1732,7 +2324,8 @@ TEST_F(URLRequestTest, InterceptLoadTimingEarlyProxyResolution) { |
| now - base::TimeDelta::FromDays(1); |
| LoadTimingInfo load_timing_result = |
| - RunLoadTimingTest(job_load_timing, &default_context_); |
| + RunURLRequestInterceptorLoadTimingTest( |
| + job_load_timing, default_context(), interceptor()); |
| // Proxy times, connect times, and DNS times should all be replaced with |
| // request_start. |
| @@ -1755,14 +2348,16 @@ TEST_F(URLRequestTest, InterceptLoadTimingEarlyProxyResolution) { |
| } |
| // Same as above, but in the reused case. |
| -TEST_F(URLRequestTest, InterceptLoadTimingEarlyProxyResolutionReused) { |
| +TEST_F(URLRequestInterceptorTest, |
| + InterceptLoadTimingEarlyProxyResolutionReused) { |
| base::TimeTicks now = base::TimeTicks::Now(); |
| LoadTimingInfo job_load_timing = NormalLoadTimingInfoReused(now, true); |
| job_load_timing.proxy_resolve_start = now - base::TimeDelta::FromDays(4); |
| job_load_timing.proxy_resolve_end = now - base::TimeDelta::FromDays(3); |
| LoadTimingInfo load_timing_result = |
| - RunLoadTimingTest(job_load_timing, &default_context_); |
| + RunURLRequestInterceptorLoadTimingTest( |
| + job_load_timing, default_context(), interceptor()); |
| // Proxy times and connect times should all be replaced with request_start. |
| EXPECT_EQ(load_timing_result.request_start, |
| @@ -1779,7 +2374,7 @@ TEST_F(URLRequestTest, InterceptLoadTimingEarlyProxyResolutionReused) { |
| // not considered reused in this test (May be a preconnect). |
| // |
| // To mix things up, the request has SSL times, but no DNS times. |
| -TEST_F(URLRequestTest, InterceptLoadTimingEarlyConnect) { |
| +TEST_F(URLRequestInterceptorTest, InterceptLoadTimingEarlyConnect) { |
| base::TimeTicks now = base::TimeTicks::Now(); |
| LoadTimingInfo job_load_timing = |
| NormalLoadTimingInfo(now, CONNECT_TIMING_HAS_SSL_TIMES, false); |
| @@ -1791,7 +2386,8 @@ TEST_F(URLRequestTest, InterceptLoadTimingEarlyConnect) { |
| now - base::TimeDelta::FromDays(4); |
| LoadTimingInfo load_timing_result = |
| - RunLoadTimingTest(job_load_timing, &default_context_); |
| + RunURLRequestInterceptorLoadTimingTest( |
| + job_load_timing, default_context(), interceptor()); |
| // Connect times, and SSL times should be replaced with request_start. |
| EXPECT_EQ(load_timing_result.request_start, |
| @@ -1813,7 +2409,7 @@ TEST_F(URLRequestTest, InterceptLoadTimingEarlyConnect) { |
| // test (May be a preconnect). |
| // |
| // In this test, there are no SSL or DNS times. |
| -TEST_F(URLRequestTest, InterceptLoadTimingEarlyConnectWithProxy) { |
| +TEST_F(URLRequestInterceptorTest, InterceptLoadTimingEarlyConnectWithProxy) { |
| base::TimeTicks now = base::TimeTicks::Now(); |
| LoadTimingInfo job_load_timing = |
| NormalLoadTimingInfo(now, CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY, true); |
| @@ -1823,7 +2419,8 @@ TEST_F(URLRequestTest, InterceptLoadTimingEarlyConnectWithProxy) { |
| now - base::TimeDelta::FromDays(2); |
| LoadTimingInfo load_timing_result = |
| - RunLoadTimingTest(job_load_timing, &default_context_); |
| + RunURLRequestInterceptorLoadTimingTest( |
| + job_load_timing, default_context(), interceptor()); |
| // Connect times should be replaced with proxy_resolve_end. |
| EXPECT_EQ(load_timing_result.proxy_resolve_end, |
| @@ -2665,6 +3262,11 @@ class URLRequestTestHTTP : public URLRequestTest { |
| return is_success; |
| } |
| + LocalHttpTestServer* test_server() { |
| + return &test_server_; |
| + } |
| + |
| + protected: |
| LocalHttpTestServer test_server_; |
| }; |
| @@ -5166,7 +5768,7 @@ TEST_F(URLRequestTestHTTP, ProtocolHandlerAndFactoryRestrictDataRedirects) { |
| EXPECT_FALSE(data_protocol_handler.IsSafeRedirectTarget(data_url)); |
| // Test URLRequestJobFactoryImpl::IsSafeRedirectTarget(). |
| - EXPECT_FALSE(job_factory_.IsSafeRedirectTarget(data_url)); |
| + EXPECT_FALSE(job_factory_->IsSafeRedirectTarget(data_url)); |
| } |
| #if !defined(DISABLE_FILE_SUPPORT) |
| @@ -5177,7 +5779,7 @@ TEST_F(URLRequestTestHTTP, ProtocolHandlerAndFactoryRestrictFileRedirects) { |
| EXPECT_FALSE(file_protocol_handler.IsSafeRedirectTarget(file_url)); |
| // Test URLRequestJobFactoryImpl::IsSafeRedirectTarget(). |
| - EXPECT_FALSE(job_factory_.IsSafeRedirectTarget(file_url)); |
| + EXPECT_FALSE(job_factory_->IsSafeRedirectTarget(file_url)); |
| } |
| TEST_F(URLRequestTestHTTP, RestrictFileRedirects) { |
| @@ -6446,6 +7048,123 @@ TEST_F(URLRequestTestHTTP, NetworkSuspendTestNoCache) { |
| EXPECT_EQ(ERR_NETWORK_IO_SUSPENDED, req->status().error()); |
| } |
| +class URLRequestInterceptorTestHTTP : public URLRequestTestHTTP { |
| + public: |
| + // TODO(bengr): Merge this with the URLRequestInterceptorHTTPTest fixture, |
| + // ideally remove the dependency on URLRequestTestJob, and maybe move these |
| + // tests into the factory tests. |
| + URLRequestInterceptorTestHTTP() : URLRequestTestHTTP(), interceptor_(NULL) { |
| + } |
| + |
| + void SetUpFactory() override { |
| + interceptor_ = new MockURLRequestInterceptor(); |
| + job_factory_.reset(new URLRequestInterceptingJobFactory( |
| + job_factory_.Pass(), make_scoped_ptr(interceptor_))); |
| + } |
| + |
| + MockURLRequestInterceptor* interceptor() const { |
| + return interceptor_; |
| + } |
| + |
| + private: |
| + MockURLRequestInterceptor* interceptor_; |
| + |
|
mmenke
2014/11/06 18:49:37
nit: Remove blank line.
bengr
2014/11/06 23:58:01
Done.
|
| +}; |
| + |
| +TEST_F(URLRequestInterceptorTestHTTP, |
| + NetworkDelegateNotificationOnRedirectIntercept) { |
| + interceptor()->set_intercept_redirect(true); |
| + interceptor()->set_redirect_headers(MockURLRequestInterceptor::ok_headers()); |
| + interceptor()->set_redirect_data(MockURLRequestInterceptor::ok_data()); |
| + |
| + ASSERT_TRUE(test_server()->Start()); |
| + |
| + TestDelegate d; |
| + scoped_ptr<URLRequest> req(default_context().CreateRequest( |
| + test_server()->GetURL("files/redirect-test.html"), DEFAULT_PRIORITY, |
| + &d, nullptr)); |
| + req->Start(); |
| + base::RunLoop().Run(); |
| + |
| + EXPECT_TRUE(interceptor()->did_intercept_redirect()); |
| + // Check we got one good response |
| + EXPECT_TRUE(req->status().is_success()); |
| + if (req->status().is_success()) { |
| + EXPECT_EQ(200, req->response_headers()->response_code()); |
| + } |
|
mmenke
2014/11/06 18:49:37
nit: Don't use braces when both parts of an if ta
bengr
2014/11/06 23:58:01
Done.
|
| + EXPECT_EQ(MockURLRequestInterceptor::ok_data(), d.data_received()); |
| + EXPECT_EQ(1, d.response_started_count()); |
| + EXPECT_EQ(0, d.received_redirect_count()); |
| + |
| + EXPECT_EQ(1, default_network_delegate()->created_requests()); |
| + EXPECT_EQ(1, default_network_delegate()->before_send_headers_count()); |
| + EXPECT_EQ(1, default_network_delegate()->headers_received_count()); |
| +} |
| + |
| +TEST_F(URLRequestInterceptorTestHTTP, |
| + NetworkDelegateNotificationOnErrorIntercept) { |
| + // Intercept that error and respond with an OK response. |
| + interceptor()->set_intercept_final_response(true); |
| + interceptor()->set_final_headers(MockURLRequestInterceptor::ok_headers()); |
| + interceptor()->set_final_data(MockURLRequestInterceptor::ok_data()); |
| + default_network_delegate()->set_can_be_intercepted_on_error(true); |
| + |
| + ASSERT_TRUE(test_server()->Start()); |
| + |
| + TestDelegate d; |
| + scoped_ptr<URLRequest> req(default_context().CreateRequest( |
| + test_server()->GetURL("files/two-content-lengths.html"), DEFAULT_PRIORITY, |
| + &d, nullptr)); |
| + req->set_method("GET"); |
| + req->Start(); |
| + base::RunLoop().Run(); |
| + |
| + EXPECT_TRUE(interceptor()->did_intercept_final()); |
| + |
| + // Check we received one good response. |
| + EXPECT_TRUE(req->status().is_success()); |
| + EXPECT_EQ(200, req->response_headers()->response_code()); |
|
mmenke
2014/11/06 18:49:37
Should probably check if the response was a succes
bengr
2014/11/06 23:58:01
Done.
|
| + EXPECT_EQ(MockURLRequestInterceptor::ok_data(), d.data_received()); |
| + EXPECT_EQ(1, d.response_started_count()); |
| + EXPECT_EQ(0, d.received_redirect_count()); |
| + |
| + EXPECT_EQ(1, default_network_delegate()->created_requests()); |
| + EXPECT_EQ(1, default_network_delegate()->before_send_headers_count()); |
| + EXPECT_EQ(0, default_network_delegate()->headers_received_count()); |
| +} |
| + |
| +TEST_F(URLRequestInterceptorTestHTTP, |
| + NetworkDelegateNotificationOnResponseIntercept) { |
| + // Intercept that error and respond with an OK response. |
| + interceptor()->set_intercept_final_response(true); |
| + |
| + // Intercept with a real URLRequestHttpJob. |
| + interceptor()->set_use_url_request_http_job(true); |
| + |
| + ASSERT_TRUE(test_server()->Start()); |
| + |
| + TestDelegate d; |
| + scoped_ptr<URLRequest> req(default_context().CreateRequest( |
| + test_server()->GetURL("files/simple.html"), DEFAULT_PRIORITY, |
| + &d, nullptr)); |
| + req->set_method("GET"); |
| + req->Start(); |
| + base::RunLoop().Run(); |
| + |
| + EXPECT_TRUE(interceptor()->did_intercept_final()); |
| + |
| + // Check we received one good response. |
| + EXPECT_TRUE(req->status().is_success()); |
| + EXPECT_EQ(200, req->response_headers()->response_code()); |
|
mmenke
2014/11/06 18:49:37
Should probably check if the response was a succes
bengr
2014/11/06 23:58:01
Done.
|
| + EXPECT_EQ("hello", d.data_received()); |
| + EXPECT_EQ(1, d.response_started_count()); |
| + EXPECT_EQ(0, d.received_redirect_count()); |
| + |
| + EXPECT_EQ(1, default_network_delegate()->created_requests()); |
| + EXPECT_EQ(2, default_network_delegate()->before_send_headers_count()); |
| + EXPECT_EQ(2, default_network_delegate()->headers_received_count()); |
| +} |
| + |
| class HTTPSRequestTest : public testing::Test { |
| public: |
| HTTPSRequestTest() : default_context_(true) { |