Index: content/browser/loader/mojo_async_resource_handler_unittest.cc |
diff --git a/content/browser/loader/mojo_async_resource_handler_unittest.cc b/content/browser/loader/mojo_async_resource_handler_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..ac8f75d11f5d2a0d2cef27aa5e54f732e2c10d13 |
--- /dev/null |
+++ b/content/browser/loader/mojo_async_resource_handler_unittest.cc |
@@ -0,0 +1,1139 @@ |
+// Copyright 2016 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/mojo_async_resource_handler.h" |
+ |
+#include <string.h> |
+ |
+#include <utility> |
+ |
+#include "base/bind.h" |
+#include "base/callback.h" |
+#include "base/files/file_path.h" |
+#include "base/memory/ptr_util.h" |
+#include "base/memory/scoped_vector.h" |
+#include "base/memory/weak_ptr.h" |
+#include "base/run_loop.h" |
+#include "content/browser/loader/resource_dispatcher_host_impl.h" |
+#include "content/browser/loader/resource_request_info_impl.h" |
+#include "content/browser/loader/test_url_loader_client.h" |
+#include "content/common/resource_request_completion_status.h" |
+#include "content/common/url_loader.mojom.h" |
+#include "content/public/browser/appcache_service.h" |
+#include "content/public/browser/navigation_data.h" |
+#include "content/public/browser/resource_context.h" |
+#include "content/public/browser/resource_controller.h" |
+#include "content/public/browser/resource_dispatcher_host_delegate.h" |
+#include "content/public/browser/resource_throttle.h" |
+#include "content/public/browser/stream_info.h" |
+#include "content/public/common/resource_response.h" |
+#include "content/public/common/resource_type.h" |
+#include "content/public/test/test_browser_context.h" |
+#include "content/public/test/test_browser_thread_bundle.h" |
+#include "mojo/public/c/system/data_pipe.h" |
+#include "mojo/public/c/system/types.h" |
+#include "mojo/public/cpp/system/data_pipe.h" |
+#include "net/base/auth.h" |
+#include "net/base/net_errors.h" |
+#include "net/http/http_response_headers.h" |
+#include "net/http/http_response_info.h" |
+#include "net/http/http_status_code.h" |
+#include "net/http/http_util.h" |
+#include "net/ssl/client_cert_store.h" |
+#include "net/test/url_request/url_request_failed_job.h" |
+#include "net/url_request/url_request.h" |
+#include "net/url_request/url_request_context.h" |
+#include "net/url_request/url_request_filter.h" |
+#include "net/url_request/url_request_status.h" |
+#include "net/url_request/url_request_test_util.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+#include "ui/base/page_transition_types.h" |
+ |
+namespace content { |
+namespace { |
+ |
+class TestResourceDispatcherHostDelegate final |
+ : public ResourceDispatcherHostDelegate { |
+ public: |
+ TestResourceDispatcherHostDelegate() = default; |
+ ~TestResourceDispatcherHostDelegate() override { |
+ EXPECT_EQ(num_on_response_started_calls_expectation_, |
+ num_on_response_started_calls_); |
+ } |
+ |
+ bool ShouldBeginRequest(const std::string& method, |
+ const GURL& url, |
+ ResourceType resource_type, |
+ ResourceContext* resource_context) override { |
+ ADD_FAILURE() << "ShouldBeginRequest should not be called."; |
+ return false; |
+ } |
+ |
+ void RequestBeginning(net::URLRequest* request, |
+ ResourceContext* resource_context, |
+ AppCacheService* appcache_service, |
+ ResourceType resource_type, |
+ ScopedVector<ResourceThrottle>* throttles) override { |
+ ADD_FAILURE() << "RequestBeginning should not be called."; |
+ } |
+ |
+ void DownloadStarting(net::URLRequest* request, |
+ ResourceContext* resource_context, |
+ int child_id, |
+ int route_id, |
+ bool is_content_initiated, |
+ bool must_download, |
+ ScopedVector<ResourceThrottle>* throttles) override { |
+ ADD_FAILURE() << "DownloadStarting should not be called."; |
+ } |
+ |
+ ResourceDispatcherHostLoginDelegate* CreateLoginDelegate( |
+ net::AuthChallengeInfo* auth_info, |
+ net::URLRequest* request) override { |
+ ADD_FAILURE() << "CreateLoginDelegate should not be called."; |
+ return nullptr; |
+ } |
+ |
+ bool HandleExternalProtocol( |
+ const GURL& url, |
+ int child_id, |
+ const ResourceRequestInfo::WebContentsGetter& web_contents_getter, |
+ bool is_main_frame, |
+ ui::PageTransition page_transition, |
+ bool has_user_gesture, |
+ ResourceContext* resource_context) override { |
+ ADD_FAILURE() << "HandleExternalProtocol should not be called."; |
+ return false; |
+ } |
+ |
+ bool ShouldForceDownloadResource(const GURL& url, |
+ const std::string& mime_type) override { |
+ ADD_FAILURE() << "ShouldForceDownloadResource should not be called."; |
+ return false; |
+ } |
+ |
+ bool ShouldInterceptResourceAsStream(net::URLRequest* request, |
+ const base::FilePath& plugin_path, |
+ const std::string& mime_type, |
+ GURL* origin, |
+ std::string* payload) override { |
+ ADD_FAILURE() << "ShouldInterceptResourceAsStream should not be called."; |
+ return false; |
+ } |
+ |
+ void OnStreamCreated(net::URLRequest* request, |
+ std::unique_ptr<content::StreamInfo> stream) override { |
+ ADD_FAILURE() << "OnStreamCreated should not be called."; |
+ } |
+ |
+ void OnResponseStarted(net::URLRequest* request, |
+ ResourceContext* resource_context, |
+ ResourceResponse* response) override { |
+ ++num_on_response_started_calls_; |
+ } |
+ |
+ void OnRequestRedirected(const GURL& redirect_url, |
+ net::URLRequest* request, |
+ ResourceContext* resource_context, |
+ ResourceResponse* response) override { |
+ ADD_FAILURE() << "OnRequestRedirected should not be called."; |
+ } |
+ |
+ void RequestComplete(net::URLRequest* url_request) override { |
+ ADD_FAILURE() << "RequestComplete should not be called."; |
+ } |
+ |
+ bool ShouldEnableLoFiMode( |
+ const net::URLRequest& url_request, |
+ content::ResourceContext* resource_context) override { |
+ ADD_FAILURE() << "ShouldEnableLoFiMode should not be called."; |
+ return false; |
+ } |
+ |
+ NavigationData* GetNavigationData(net::URLRequest* request) const override { |
+ ADD_FAILURE() << "GetNavigationData should not be called."; |
+ return nullptr; |
+ } |
+ |
+ std::unique_ptr<net::ClientCertStore> CreateClientCertStore( |
+ ResourceContext* resource_context) override { |
+ ADD_FAILURE() << "CreateClientCertStore should not be called."; |
+ return nullptr; |
+ } |
+ |
+ int num_on_response_started_calls() const { |
+ return num_on_response_started_calls_; |
+ } |
+ void set_num_on_response_started_calls_expectation(int expectation) { |
+ num_on_response_started_calls_expectation_ = expectation; |
+ } |
+ |
+ private: |
+ int num_on_response_started_calls_ = 0; |
+ int num_on_response_started_calls_expectation_ = 0; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(TestResourceDispatcherHostDelegate); |
+}; |
+ |
+class TestResourceController : public ResourceController { |
+ public: |
+ TestResourceController() {} |
+ ~TestResourceController() override {} |
+ |
+ void Cancel() override { ADD_FAILURE() << "Cancel should not be called."; } |
+ |
+ void CancelAndIgnore() override { |
+ ADD_FAILURE() << "CancelAndIgnore should not be called."; |
+ } |
+ |
+ void CancelWithError(int error_code) override { |
+ is_cancel_with_error_called_ = true; |
+ error_ = error_code; |
+ if (quit_closure_) |
+ quit_closure_.Run(); |
+ } |
+ |
+ void Resume() override { ++num_resume_calls_; } |
+ |
+ void RunUntilCancelWithErrorCalled() { |
+ base::RunLoop run_loop; |
+ quit_closure_ = run_loop.QuitClosure(); |
+ run_loop.Run(); |
+ } |
+ |
+ void set_quit_closure(const base::Closure& quit_closure) { |
+ quit_closure_ = quit_closure; |
+ } |
+ |
+ bool is_cancel_with_error_called() const { |
+ return is_cancel_with_error_called_; |
+ } |
+ int error() const { return error_; } |
+ int num_resume_calls() const { return num_resume_calls_; } |
+ |
+ private: |
+ bool is_cancel_with_error_called_ = false; |
+ int error_ = net::OK; |
+ int num_resume_calls_ = 0; |
+ base::Closure quit_closure_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(TestResourceController); |
+}; |
+ |
+class MojoAsyncResourceHandlerWithCustomDataPipeOperations |
+ : public MojoAsyncResourceHandler { |
+ public: |
+ MojoAsyncResourceHandlerWithCustomDataPipeOperations( |
+ net::URLRequest* request, |
+ ResourceDispatcherHostImpl* rdh, |
+ mojo::InterfaceRequest<mojom::URLLoader> mojo_request, |
+ mojom::URLLoaderClientPtr url_loader_client) |
+ : MojoAsyncResourceHandler(request, |
+ rdh, |
+ std::move(mojo_request), |
+ std::move(url_loader_client)) {} |
+ ~MojoAsyncResourceHandlerWithCustomDataPipeOperations() override {} |
+ |
+ void ResetBeginWriteExpectation() { is_begin_write_expectation_set_ = false; } |
+ |
+ void set_begin_write_expectation(MojoResult begin_write_expectation) { |
+ is_begin_write_expectation_set_ = true; |
+ begin_write_expectation_ = begin_write_expectation; |
+ } |
+ void set_end_write_expectation(MojoResult end_write_expectation) { |
+ is_end_write_expectation_set_ = true; |
+ end_write_expectation_ = end_write_expectation; |
+ } |
+ |
+ private: |
+ MojoResult BeginWrite(void** data, uint32_t* available) override { |
+ if (is_begin_write_expectation_set_) |
+ return begin_write_expectation_; |
+ return MojoAsyncResourceHandler::BeginWrite(data, available); |
+ } |
+ MojoResult EndWrite(uint32_t written) override { |
+ if (is_end_write_expectation_set_) |
+ return end_write_expectation_; |
+ return MojoAsyncResourceHandler::EndWrite(written); |
+ } |
+ |
+ bool is_begin_write_expectation_set_ = false; |
+ bool is_end_write_expectation_set_ = false; |
+ MojoResult begin_write_expectation_ = MOJO_RESULT_UNKNOWN; |
+ MojoResult end_write_expectation_ = MOJO_RESULT_UNKNOWN; |
+ |
+ DISALLOW_COPY_AND_ASSIGN( |
+ MojoAsyncResourceHandlerWithCustomDataPipeOperations); |
+}; |
+ |
+class MojoAsyncResourceHandlerTestBase { |
+ public: |
+ MojoAsyncResourceHandlerTestBase() |
+ : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP), |
+ browser_context_(new TestBrowserContext()) { |
+ MojoAsyncResourceHandler::SetAllocationSizeForTesting(32 * 1024); |
+ rdh_.SetDelegate(&rdh_delegate_); |
+ |
+ // Calling this function creates a request context. |
+ browser_context_->GetResourceContext()->GetRequestContext(); |
kinuko
2016/08/04 16:07:02
We get request_context right below on line 283, do
yhirano
2016/08/05 12:21:39
I needed them but it looks we don't need them any
|
+ base::RunLoop().RunUntilIdle(); |
+ |
+ url_request_delegate_.reset(new net::TestDelegate()); |
+ net::URLRequestContext* request_context = |
+ browser_context_->GetResourceContext()->GetRequestContext(); |
+ request_ = request_context->CreateRequest( |
+ net::URLRequestFailedJob::GetMockHttpUrl(net::ERR_TIMED_OUT), |
+ net::DEFAULT_PRIORITY, url_request_delegate_.get()); |
+ ResourceRequestInfo::AllocateForTesting( |
+ request_.get(), RESOURCE_TYPE_XHR, |
+ browser_context_->GetResourceContext(), 2, 0, 0, true, false, false, |
+ true, false); |
kinuko
2016/08/04 16:07:02
nit: would be nice to have short comments for some
yhirano
2016/08/05 12:21:39
Done.
|
+ handler_.reset(new MojoAsyncResourceHandlerWithCustomDataPipeOperations( |
+ request_.get(), &rdh_, nullptr, |
+ url_loader_client_.CreateInterfacePtrAndBind())); |
+ handler_->SetController(&resource_controller_); |
+ } |
+ |
+ virtual ~MojoAsyncResourceHandlerTestBase() { |
+ net::URLRequestFilter::GetInstance()->ClearHandlers(); |
+ MojoAsyncResourceHandler::SetAllocationSizeForTesting( |
+ MojoAsyncResourceHandler::kDefaultAllocationSize); |
+ } |
+ |
+ // Returns false if something bad happens. |
+ bool CallOnWillStart() { |
+ bool defer = false; |
+ if (!handler_->OnWillStart(request_->url(), &defer)) { |
+ ADD_FAILURE() << "OnWillStart returns false."; |
+ return false; |
+ } |
+ if (defer) { |
+ ADD_FAILURE() << "OnWillStart sets |defer| true."; |
+ return false; |
+ } |
+ return true; |
+ } |
+ |
+ // Returns false if something bad happens. |
+ bool CallOnWillStartAndOnResponseStarted() { |
+ rdh_delegate_.set_num_on_response_started_calls_expectation(1); |
+ if (!CallOnWillStart()) |
+ return false; |
+ |
+ scoped_refptr<ResourceResponse> response = new ResourceResponse(); |
+ bool defer = false; |
+ if (!handler_->OnResponseStarted(response.get(), &defer)) { |
+ ADD_FAILURE() << "OnResponseStarted returns false."; |
+ return false; |
+ } |
+ if (defer) { |
+ ADD_FAILURE() << "OnResponseStarted sets |defer| true."; |
+ return false; |
+ } |
+ if (url_loader_client_.has_received_response()) { |
+ ADD_FAILURE() << "URLLoaderClient unexpectedly gets a response."; |
+ return false; |
+ } |
+ url_loader_client_.RunUntilResponseReceived(); |
+ return true; |
+ } |
+ |
+ TestBrowserThreadBundle thread_bundle_; |
+ TestResourceDispatcherHostDelegate rdh_delegate_; |
+ ResourceDispatcherHostImpl rdh_; |
+ TestURLLoaderClient url_loader_client_; |
+ TestResourceController resource_controller_; |
+ std::unique_ptr<TestBrowserContext> browser_context_; |
+ std::unique_ptr<net::TestDelegate> url_request_delegate_; |
+ std::unique_ptr<net::URLRequest> request_; |
+ std::unique_ptr<MojoAsyncResourceHandlerWithCustomDataPipeOperations> |
+ handler_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(MojoAsyncResourceHandlerTestBase); |
+}; |
+ |
+class MojoAsyncResourceHandlerTest : public MojoAsyncResourceHandlerTestBase, |
+ public ::testing::Test {}; |
+ |
+// This test class is parameterized with MojoAsyncResourceHandler's allocation |
+// size. |
+class MojoAsyncResourceHandlerWithAllocationSizeTest |
+ : public MojoAsyncResourceHandlerTestBase, |
+ public ::testing::TestWithParam<size_t> { |
+ protected: |
+ MojoAsyncResourceHandlerWithAllocationSizeTest() { |
+ MojoAsyncResourceHandler::SetAllocationSizeForTesting(GetParam()); |
+ } |
+}; |
+ |
+TEST_F(MojoAsyncResourceHandlerTest, InFlightRequests) { |
+ EXPECT_EQ(0, rdh_.num_in_flight_requests_for_testing()); |
+ handler_ = nullptr; |
+ EXPECT_EQ(0, rdh_.num_in_flight_requests_for_testing()); |
+} |
+ |
+TEST_F(MojoAsyncResourceHandlerTest, OnWillStart) { |
+ bool defer = false; |
+ EXPECT_TRUE(handler_->OnWillStart(request_->url(), &defer)); |
+ EXPECT_FALSE(defer); |
+} |
+ |
+TEST_F(MojoAsyncResourceHandlerTest, OnResponseStarted) { |
+ rdh_delegate_.set_num_on_response_started_calls_expectation(1); |
+ ASSERT_TRUE(CallOnWillStart()); |
+ |
+ scoped_refptr<ResourceResponse> response = new ResourceResponse(); |
+ response->head.content_length = 99; |
+ response->head.request_start = |
+ base::TimeTicks::UnixEpoch() + base::TimeDelta::FromDays(14); |
+ response->head.response_start = |
+ base::TimeTicks::UnixEpoch() + base::TimeDelta::FromDays(28); |
+ |
+ bool defer = false; |
+ |
+ EXPECT_EQ(0, rdh_delegate_.num_on_response_started_calls()); |
+ base::TimeTicks now1 = base::TimeTicks::Now(); |
+ ASSERT_TRUE(handler_->OnResponseStarted(response.get(), &defer)); |
+ base::TimeTicks now2 = base::TimeTicks::Now(); |
+ |
+ EXPECT_FALSE(defer); |
+ EXPECT_EQ(request_->creation_time(), response->head.request_start); |
+ EXPECT_LE(now1, response->head.response_start); |
+ EXPECT_LE(response->head.response_start, now2); |
+ EXPECT_EQ(1, rdh_delegate_.num_on_response_started_calls()); |
+ |
+ url_loader_client_.RunUntilResponseReceived(); |
+ EXPECT_EQ(response->head.request_start, |
+ url_loader_client_.response_head().request_start); |
+ EXPECT_EQ(response->head.response_start, |
+ url_loader_client_.response_head().response_start); |
+ EXPECT_EQ(99, url_loader_client_.response_head().content_length); |
+} |
+ |
+TEST_F(MojoAsyncResourceHandlerTest, OnWillReadAndInFlightRequests) { |
+ ASSERT_TRUE(CallOnWillStartAndOnResponseStarted()); |
+ EXPECT_EQ(0, rdh_.num_in_flight_requests_for_testing()); |
+ scoped_refptr<net::IOBuffer> io_buffer; |
+ int io_buffer_size; |
+ EXPECT_TRUE(handler_->OnWillRead(&io_buffer, &io_buffer_size, -1)); |
+ EXPECT_EQ(1, rdh_.num_in_flight_requests_for_testing()); |
+ handler_ = nullptr; |
+ EXPECT_EQ(0, rdh_.num_in_flight_requests_for_testing()); |
+} |
+ |
+TEST_F(MojoAsyncResourceHandlerTest, OnWillReadWithInsufficientResource) { |
+ rdh_.set_max_num_in_flight_requests_per_process(0); |
+ ASSERT_TRUE(CallOnWillStartAndOnResponseStarted()); |
+ |
+ scoped_refptr<net::IOBuffer> io_buffer; |
+ int io_buffer_size = 0; |
+ EXPECT_FALSE(handler_->OnWillRead(&io_buffer, &io_buffer_size, -1)); |
+ EXPECT_FALSE(io_buffer); |
+ EXPECT_EQ(0, io_buffer_size); |
+ EXPECT_EQ(1, rdh_.num_in_flight_requests_for_testing()); |
+ EXPECT_TRUE(resource_controller_.is_cancel_with_error_called()); |
+ EXPECT_EQ(net::ERR_INSUFFICIENT_RESOURCES, resource_controller_.error()); |
+ handler_ = nullptr; |
+ EXPECT_EQ(0, rdh_.num_in_flight_requests_for_testing()); |
+} |
+ |
+TEST_F(MojoAsyncResourceHandlerTest, OnWillReadAndOnReadCompleted) { |
+ bool defer = false; |
+ scoped_refptr<net::IOBuffer> io_buffer; |
+ int io_buffer_size; |
+ |
+ ASSERT_TRUE(CallOnWillStartAndOnResponseStarted()); |
+ ASSERT_TRUE(handler_->OnWillRead(&io_buffer, &io_buffer_size, -1)); |
+ ASSERT_TRUE(io_buffer); |
+ // The buffer size that the mime sniffer requires implicitly. |
+ ASSERT_GE(io_buffer_size, 2 * 1024); |
kinuko
2016/08/04 16:07:02
Do you mean kMinAllocationSize? Could we refer to
yhirano
2016/08/05 12:21:39
Done.
|
+ |
+ url_loader_client_.RunUntilResponseBodyArrived(); |
+ ASSERT_TRUE(url_loader_client_.response_body().is_valid()); |
+ |
+ io_buffer->data()[0] = 'A'; |
+ io_buffer->data()[1] = 'B'; |
+ ASSERT_TRUE(handler_->OnReadCompleted(2, &defer)); |
+ EXPECT_FALSE(defer); |
+ |
+ std::string contents; |
+ while (contents.size() < 2) { |
+ char buffer[16]; |
+ uint32_t read = sizeof(buffer); |
kinuko
2016/08/04 16:07:03
nit: 'read' -> 'read_size' for clarity?
yhirano
2016/08/05 12:21:39
Done.
|
+ MojoResult result = |
+ mojo::ReadDataRaw(url_loader_client_.response_body(), buffer, &read, |
+ MOJO_READ_DATA_FLAG_NONE); |
+ if (result == MOJO_RESULT_SHOULD_WAIT) { |
+ base::RunLoop().RunUntilIdle(); |
+ continue; |
+ } |
+ contents.append(buffer, read); |
+ } |
+ EXPECT_EQ("AB", contents); |
+} |
+ |
+TEST_F(MojoAsyncResourceHandlerTest, |
+ OnWillReadAndOnReadCompletedWithInsufficientInitialCapacity) { |
+ MojoAsyncResourceHandler::SetAllocationSizeForTesting(2); |
+ |
+ bool defer = false; |
+ scoped_refptr<net::IOBuffer> io_buffer; |
+ int io_buffer_size; |
+ |
+ ASSERT_TRUE(CallOnWillStartAndOnResponseStarted()); |
+ ASSERT_TRUE(handler_->OnWillRead(&io_buffer, &io_buffer_size, -1)); |
+ ASSERT_TRUE(io_buffer); |
+ // The buffer size that the mime sniffer requires implicitly. |
+ ASSERT_GE(io_buffer_size, 2 * 1024); |
kinuko
2016/08/04 16:07:02
ditto
yhirano
2016/08/05 12:21:39
Done.
|
+ |
+ url_loader_client_.RunUntilResponseBodyArrived(); |
+ ASSERT_TRUE(url_loader_client_.response_body().is_valid()); |
+ |
+ const std::string data("abcdefgh"); |
+ strcpy(io_buffer->data(), data.c_str()); |
+ ASSERT_TRUE(handler_->OnReadCompleted(data.size(), &defer)); |
+ EXPECT_TRUE(defer); |
+ |
+ std::string contents; |
+ while (contents.size() < data.size()) { |
+ // This is needed for Resume to be called. |
+ base::RunLoop().RunUntilIdle(); |
kinuko
2016/08/04 16:07:02
We call this in MOJO_RESULT_SHOULD_WAIT condition
mmenke
2016/08/04 16:12:44
If we get MOJO_RESULT_SHOULD_WAIT in the ReadDataR
kinuko
2016/08/04 16:57:09
Uh, yeah... wasn't really reading the code. Thank
|
+ char buffer[16]; |
+ uint32_t read = sizeof(buffer); |
kinuko
2016/08/04 16:07:02
ditto
yhirano
2016/08/05 12:21:39
Done.
|
+ MojoResult result = |
+ mojo::ReadDataRaw(url_loader_client_.response_body(), buffer, &read, |
+ MOJO_READ_DATA_FLAG_NONE); |
+ if (result == MOJO_RESULT_SHOULD_WAIT) |
+ continue; |
+ ASSERT_EQ(MOJO_RESULT_OK, result); |
+ contents.append(buffer, read); |
+ } |
+ EXPECT_EQ(data, contents); |
+ EXPECT_EQ(0, resource_controller_.num_resume_calls()); |
+} |
+ |
+TEST_F(MojoAsyncResourceHandlerTest, |
+ IOBufferFromOnWillReadShouldRemainValidEvenIfHandlerIsGone) { |
+ scoped_refptr<net::IOBuffer> io_buffer; |
+ int io_buffer_size; |
+ |
+ ASSERT_TRUE(CallOnWillStartAndOnResponseStarted()); |
+ ASSERT_TRUE(handler_->OnWillRead(&io_buffer, &io_buffer_size, -1)); |
+ ASSERT_TRUE(io_buffer); |
+ // The io_buffer size that the mime sniffer requires implicitly. |
+ ASSERT_GE(io_buffer_size, 2 * 1024); |
kinuko
2016/08/04 16:07:02
ditto... or if we use this magic number repeatedly
yhirano
2016/08/05 12:21:39
Done.
|
+ |
+ handler_ = nullptr; |
+ url_loader_client_.Unbind(); |
+ base::RunLoop().RunUntilIdle(); |
+ |
+ // Hopefully ASAN checks this operation's validity. |
+ io_buffer->data()[0] = 'A'; |
+} |
+ |
+TEST_F(MojoAsyncResourceHandlerTest, OnResponseCompleted) { |
+ bool defer = false; |
+ ASSERT_TRUE(CallOnWillStartAndOnResponseStarted()); |
+ |
+ ResourceRequestInfoImpl::ForRequest(request_.get()) |
+ ->set_was_ignored_by_handler(false); |
+ net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, net::OK); |
+ std::string security_info = "info0"; |
+ |
+ base::TimeTicks now1 = base::TimeTicks::Now(); |
+ handler_->OnResponseCompleted(status, security_info, &defer); |
+ base::TimeTicks now2 = base::TimeTicks::Now(); |
+ EXPECT_FALSE(defer); |
+ |
+ url_loader_client_.RunUntilComplete(); |
+ EXPECT_TRUE(url_loader_client_.has_received_completion()); |
+ EXPECT_EQ(net::OK, url_loader_client_.completion_status().error_code); |
+ EXPECT_FALSE(url_loader_client_.completion_status().was_ignored_by_handler); |
+ EXPECT_EQ("info0", url_loader_client_.completion_status().security_info); |
+ EXPECT_LE(now1, url_loader_client_.completion_status().completion_time); |
+ EXPECT_LE(url_loader_client_.completion_status().completion_time, now2); |
+ EXPECT_EQ(request_->GetTotalReceivedBytes(), |
+ url_loader_client_.completion_status().encoded_data_length); |
+} |
+ |
+// This test case sets different status values from OnResponseCompleted. |
+TEST_F(MojoAsyncResourceHandlerTest, OnResponseCompleted2) { |
+ rdh_.SetDelegate(nullptr); |
+ bool defer = false; |
+ // Don't use CallOnWillStartAndOnResponseStarted as this test case manually |
+ // sets the null delegate. |
+ ASSERT_TRUE(CallOnWillStart()); |
+ scoped_refptr<ResourceResponse> response = new ResourceResponse(); |
+ ASSERT_TRUE(handler_->OnResponseStarted(response.get(), &defer)); |
+ ASSERT_FALSE(defer); |
+ ASSERT_FALSE(url_loader_client_.has_received_response()); |
+ url_loader_client_.RunUntilResponseReceived(); |
+ |
+ ResourceRequestInfoImpl::ForRequest(request_.get()) |
+ ->set_was_ignored_by_handler(true); |
+ net::URLRequestStatus status(net::URLRequestStatus::CANCELED, |
+ net::ERR_ABORTED); |
+ std::string security_info = "info1"; |
+ |
+ base::TimeTicks now1 = base::TimeTicks::Now(); |
+ handler_->OnResponseCompleted(status, security_info, &defer); |
+ base::TimeTicks now2 = base::TimeTicks::Now(); |
+ EXPECT_FALSE(defer); |
+ |
+ url_loader_client_.RunUntilComplete(); |
+ EXPECT_TRUE(url_loader_client_.has_received_completion()); |
+ EXPECT_EQ(net::ERR_ABORTED, |
+ url_loader_client_.completion_status().error_code); |
+ EXPECT_TRUE(url_loader_client_.completion_status().was_ignored_by_handler); |
+ EXPECT_EQ("info1", url_loader_client_.completion_status().security_info); |
+ EXPECT_LE(now1, url_loader_client_.completion_status().completion_time); |
+ EXPECT_LE(url_loader_client_.completion_status().completion_time, now2); |
+ EXPECT_EQ(request_->GetTotalReceivedBytes(), |
+ url_loader_client_.completion_status().encoded_data_length); |
+} |
+ |
+TEST_F(MojoAsyncResourceHandlerTest, OnResponseCompletedWithCanceledTimedOut) { |
+ net::URLRequestStatus status(net::URLRequestStatus::CANCELED, |
+ net::ERR_TIMED_OUT); |
+ bool defer = false; |
+ |
+ ASSERT_TRUE(CallOnWillStartAndOnResponseStarted()); |
+ handler_->OnResponseCompleted(status, "security_info", &defer); |
+ EXPECT_FALSE(defer); |
+ |
+ url_loader_client_.RunUntilComplete(); |
+ EXPECT_TRUE(url_loader_client_.has_received_completion()); |
+ EXPECT_EQ(net::ERR_TIMED_OUT, |
+ url_loader_client_.completion_status().error_code); |
+} |
+ |
+TEST_F(MojoAsyncResourceHandlerTest, OnResponseCompletedWithFailedTimedOut) { |
+ net::URLRequestStatus status(net::URLRequestStatus::FAILED, |
+ net::ERR_TIMED_OUT); |
+ bool defer = false; |
+ |
+ ASSERT_TRUE(CallOnWillStartAndOnResponseStarted()); |
+ handler_->OnResponseCompleted(status, "security_info", &defer); |
+ EXPECT_FALSE(defer); |
+ |
+ url_loader_client_.RunUntilComplete(); |
+ EXPECT_TRUE(url_loader_client_.has_received_completion()); |
+ EXPECT_EQ(net::ERR_TIMED_OUT, |
+ url_loader_client_.completion_status().error_code); |
+} |
+ |
+TEST_F(MojoAsyncResourceHandlerTest, ResponseCompletionShouldCloseDataPipe) { |
+ ASSERT_TRUE(CallOnWillStartAndOnResponseStarted()); |
+ |
+ scoped_refptr<net::IOBuffer> io_buffer; |
+ int io_buffer_size; |
+ bool defer = false; |
+ ASSERT_TRUE(handler_->OnWillRead(&io_buffer, &io_buffer_size, -1)); |
+ url_loader_client_.RunUntilResponseBodyArrived(); |
+ ASSERT_TRUE(url_loader_client_.response_body().is_valid()); |
+ ASSERT_TRUE(handler_->OnReadCompleted(0, &defer)); |
+ EXPECT_FALSE(defer); |
+ |
+ net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, net::OK); |
+ handler_->OnResponseCompleted(status, "security_info", &defer); |
+ EXPECT_FALSE(defer); |
+ |
+ url_loader_client_.RunUntilComplete(); |
+ EXPECT_TRUE(url_loader_client_.has_received_completion()); |
+ EXPECT_EQ(net::OK, url_loader_client_.completion_status().error_code); |
+ |
+ // This is needed because |*io_buffer| may keep the data producer alive. |
+ io_buffer = nullptr; |
+ |
+ while (true) { |
+ char buffer[16]; |
+ uint32_t read = sizeof(buffer); |
kinuko
2016/08/04 16:07:03
ditto
yhirano
2016/08/05 12:21:39
Done.
|
+ MojoResult result = |
+ mojo::ReadDataRaw(url_loader_client_.response_body(), buffer, &read, |
+ MOJO_READ_DATA_FLAG_NONE); |
+ if (result == MOJO_RESULT_FAILED_PRECONDITION) |
+ break; |
+ ASSERT_EQ(result, MOJO_RESULT_SHOULD_WAIT); |
+ } |
+} |
+ |
+TEST_F(MojoAsyncResourceHandlerTest, ResponseErrorDuringBodyTransmission) { |
+ ASSERT_TRUE(CallOnWillStartAndOnResponseStarted()); |
+ |
+ scoped_refptr<net::IOBuffer> io_buffer; |
+ int io_buffer_size; |
+ ASSERT_TRUE(handler_->OnWillRead(&io_buffer, &io_buffer_size, -1)); |
+ url_loader_client_.RunUntilResponseBodyArrived(); |
+ ASSERT_TRUE(url_loader_client_.response_body().is_valid()); |
+ ASSERT_GT(io_buffer_size, 0); |
+ memset(io_buffer->data(), 'a', io_buffer_size); |
+ bool defer = false; |
+ ASSERT_TRUE(handler_->OnReadCompleted(io_buffer_size, &defer)); |
+ // We don't care |defer|'s value here. |
+ |
+ defer = false; |
+ net::URLRequestStatus status(net::URLRequestStatus::FAILED, net::ERR_FAILED); |
+ handler_->OnResponseCompleted(status, "security_info", &defer); |
+ EXPECT_FALSE(defer); |
+ |
+ url_loader_client_.RunUntilComplete(); |
+ EXPECT_TRUE(url_loader_client_.has_received_completion()); |
+ EXPECT_EQ(net::ERR_FAILED, url_loader_client_.completion_status().error_code); |
+ |
+ // This is needed because |*io_buffer| may keep the data producer alive. |
+ io_buffer = nullptr; |
+ |
+ std::string actual; |
+ while (true) { |
+ char buf[16]; |
+ uint32_t read = sizeof(buf); |
+ MojoResult result = mojo::ReadDataRaw(url_loader_client_.response_body(), |
+ buf, &read, MOJO_READ_DATA_FLAG_NONE); |
+ if (result == MOJO_RESULT_FAILED_PRECONDITION) |
+ break; |
+ if (result == MOJO_RESULT_SHOULD_WAIT) { |
+ base::RunLoop().RunUntilIdle(); |
+ continue; |
+ } |
+ EXPECT_EQ(MOJO_RESULT_OK, result); |
+ actual.append(buf, read); |
+ } |
+ EXPECT_EQ(std::string(io_buffer_size, 'a'), actual); |
+} |
+ |
+// In this case, an error is notified after OnWillRead, before OnReadCompleted. |
+TEST_F(MojoAsyncResourceHandlerTest, ResponseErrorDuringBodyTransmission2) { |
+ ASSERT_TRUE(CallOnWillStartAndOnResponseStarted()); |
+ |
+ scoped_refptr<net::IOBuffer> io_buffer; |
+ int io_buffer_size; |
+ ASSERT_TRUE(handler_->OnWillRead(&io_buffer, &io_buffer_size, -1)); |
+ url_loader_client_.RunUntilResponseBodyArrived(); |
+ ASSERT_TRUE(url_loader_client_.response_body().is_valid()); |
+ bool defer = false; |
+ net::URLRequestStatus status(net::URLRequestStatus::FAILED, net::ERR_FAILED); |
+ handler_->OnResponseCompleted(status, "security_info", &defer); |
+ EXPECT_FALSE(defer); |
+ |
+ url_loader_client_.RunUntilComplete(); |
+ EXPECT_TRUE(url_loader_client_.has_received_completion()); |
+ EXPECT_EQ(net::ERR_FAILED, url_loader_client_.completion_status().error_code); |
+ |
+ // This is needed because |*io_buffer| may keep the data producer alive. |
+ io_buffer = nullptr; |
+ |
+ while (true) { |
+ char buf[16]; |
+ uint32_t read = sizeof(buf); |
+ MojoResult result = mojo::ReadDataRaw(url_loader_client_.response_body(), |
+ buf, &read, MOJO_READ_DATA_FLAG_NONE); |
+ if (result == MOJO_RESULT_FAILED_PRECONDITION) |
+ break; |
+ ASSERT_EQ(MOJO_RESULT_SHOULD_WAIT, result); |
+ base::RunLoop().RunUntilIdle(); |
+ } |
+} |
+ |
+TEST_F(MojoAsyncResourceHandlerTest, BeginWriteFailsOnWillRead) { |
+ handler_->set_begin_write_expectation(MOJO_RESULT_UNKNOWN); |
+ scoped_refptr<net::IOBuffer> io_buffer; |
+ int io_buffer_size = 0; |
+ ASSERT_TRUE(CallOnWillStartAndOnResponseStarted()); |
+ ASSERT_FALSE(handler_->OnWillRead(&io_buffer, &io_buffer_size, -1)); |
+ EXPECT_FALSE(resource_controller_.is_cancel_with_error_called()); |
+} |
+ |
+TEST_F(MojoAsyncResourceHandlerTest, BeginWriteReturnsShouldWaitOnWillRead) { |
+ handler_->set_begin_write_expectation(MOJO_RESULT_SHOULD_WAIT); |
+ scoped_refptr<net::IOBuffer> io_buffer; |
+ int io_buffer_size = 0; |
+ ASSERT_TRUE(CallOnWillStartAndOnResponseStarted()); |
+ ASSERT_TRUE(handler_->OnWillRead(&io_buffer, &io_buffer_size, -1)); |
+ EXPECT_TRUE(io_buffer); |
+ EXPECT_GT(io_buffer_size, 0); |
+} |
+ |
+TEST_F(MojoAsyncResourceHandlerTest, |
+ BeginWriteReturnsShouldWaitOnWillReadAndThenReturnsOK) { |
+ handler_->set_begin_write_expectation(MOJO_RESULT_SHOULD_WAIT); |
+ ASSERT_TRUE(CallOnWillStartAndOnResponseStarted()); |
+ size_t written = 0; |
+ std::string actual; |
kinuko
2016/08/04 16:07:02
nit: actual's not used until line 782, maybe move
yhirano
2016/08/05 12:21:39
Done.
|
+ while (true) { |
+ scoped_refptr<net::IOBuffer> io_buffer; |
+ int io_buffer_size = 0; |
+ ASSERT_TRUE(handler_->OnWillRead(&io_buffer, &io_buffer_size, -1)); |
+ EXPECT_TRUE(io_buffer); |
+ EXPECT_GT(io_buffer_size, 0); |
+ memset(io_buffer->data(), 'X', io_buffer_size); |
+ written += io_buffer_size; |
+ bool defer = false; |
+ ASSERT_TRUE(handler_->OnReadCompleted(io_buffer_size, &defer)); |
+ if (defer) |
+ break; |
+ } |
+ |
+ url_loader_client_.RunUntilResponseBodyArrived(); |
+ ASSERT_TRUE(url_loader_client_.response_body().is_valid()); |
+ handler_->ResetBeginWriteExpectation(); |
+ handler_->ResumeForTesting(); |
+ |
+ while (actual.size() < written) { |
+ char buf[16]; |
+ uint32_t read = sizeof(buf); |
+ MojoResult result = mojo::ReadDataRaw(url_loader_client_.response_body(), |
+ buf, &read, MOJO_READ_DATA_FLAG_NONE); |
+ ASSERT_TRUE(result == MOJO_RESULT_OK || result == MOJO_RESULT_SHOULD_WAIT); |
+ if (result == MOJO_RESULT_OK) |
+ actual.append(buf, read); |
+ base::RunLoop().RunUntilIdle(); |
+ } |
+ |
+ base::RunLoop().RunUntilIdle(); |
kinuko
2016/08/04 16:07:02
nit: we always seem to run loop at the end of whil
yhirano
2016/08/05 12:21:39
Done.
|
+ |
+ EXPECT_EQ(std::string(written, 'X'), actual); |
+ EXPECT_EQ(1, resource_controller_.num_resume_calls()); |
+} |
+ |
+TEST_F(MojoAsyncResourceHandlerTest, |
+ EndWriteFailsOnWillReadWithInsufficientInitialCapacity) { |
+ MojoAsyncResourceHandler::SetAllocationSizeForTesting(2); |
+ ASSERT_TRUE(CallOnWillStartAndOnResponseStarted()); |
+ handler_->set_end_write_expectation(MOJO_RESULT_UNKNOWN); |
+ scoped_refptr<net::IOBuffer> io_buffer; |
+ int io_buffer_size = 0; |
kinuko
2016/08/04 16:07:02
nit: we initialize io_buffer_size before calling O
yhirano
2016/08/05 12:21:39
Done.
|
+ ASSERT_FALSE(handler_->OnWillRead(&io_buffer, &io_buffer_size, -1)); |
+} |
+ |
+TEST_F(MojoAsyncResourceHandlerTest, EndWriteFailsOnReadCompleted) { |
+ scoped_refptr<net::IOBuffer> io_buffer; |
+ int io_buffer_size = 0; |
+ bool defer = false; |
+ ASSERT_TRUE(CallOnWillStartAndOnResponseStarted()); |
+ ASSERT_TRUE(handler_->OnWillRead(&io_buffer, &io_buffer_size, -1)); |
+ |
+ handler_->set_end_write_expectation(MOJO_RESULT_SHOULD_WAIT); |
+ ASSERT_FALSE(handler_->OnReadCompleted(io_buffer_size, &defer)); |
+} |
+ |
+TEST_F(MojoAsyncResourceHandlerTest, |
+ EndWriteFailsOnReadCompletedWithInsufficientInitialCapacity) { |
+ MojoAsyncResourceHandler::SetAllocationSizeForTesting(2); |
+ scoped_refptr<net::IOBuffer> io_buffer; |
+ int io_buffer_size = 0; |
+ bool defer = false; |
+ ASSERT_TRUE(CallOnWillStartAndOnResponseStarted()); |
+ ASSERT_TRUE(handler_->OnWillRead(&io_buffer, &io_buffer_size, -1)); |
+ |
+ handler_->set_end_write_expectation(MOJO_RESULT_SHOULD_WAIT); |
+ ASSERT_FALSE(handler_->OnReadCompleted(io_buffer_size, &defer)); |
+} |
+ |
+TEST_F(MojoAsyncResourceHandlerTest, |
+ EndWriteFailsOnResumeWithInsufficientInitialCapacity) { |
+ MojoAsyncResourceHandler::SetAllocationSizeForTesting(8); |
+ ASSERT_TRUE(CallOnWillStartAndOnResponseStarted()); |
+ scoped_refptr<net::IOBuffer> io_buffer; |
+ int io_buffer_size = 0; |
+ ASSERT_TRUE(handler_->OnWillRead(&io_buffer, &io_buffer_size, -1)); |
+ url_loader_client_.RunUntilResponseBodyArrived(); |
+ ASSERT_TRUE(url_loader_client_.response_body().is_valid()); |
+ |
+ while (true) { |
+ bool defer = false; |
+ ASSERT_TRUE(handler_->OnReadCompleted(io_buffer_size, &defer)); |
+ ASSERT_GE(io_buffer_size, 0); |
+ if (defer) |
+ break; |
+ ASSERT_TRUE(handler_->OnWillRead(&io_buffer, &io_buffer_size, -1)); |
+ } |
+ |
+ while (true) { |
+ char buf[16]; |
+ uint32_t read = sizeof(buf); |
kinuko
2016/08/04 16:07:03
ditto
yhirano
2016/08/05 12:21:39
Done.
|
+ MojoResult result = mojo::ReadDataRaw(url_loader_client_.response_body(), |
+ buf, &read, MOJO_READ_DATA_FLAG_NONE); |
+ if (result == MOJO_RESULT_SHOULD_WAIT) |
+ break; |
+ ASSERT_EQ(MOJO_RESULT_OK, result); |
+ } |
+ |
+ handler_->set_end_write_expectation(MOJO_RESULT_SHOULD_WAIT); |
+ resource_controller_.RunUntilCancelWithErrorCalled(); |
+ EXPECT_FALSE(url_loader_client_.has_received_completion()); |
+ EXPECT_TRUE(resource_controller_.is_cancel_with_error_called()); |
+ EXPECT_EQ(net::ERR_FAILED, resource_controller_.error()); |
+} |
+ |
+TEST_P(MojoAsyncResourceHandlerWithAllocationSizeTest, |
+ OnWillReadWithLongContents) { |
+ bool defer = false; |
+ scoped_refptr<net::IOBuffer> io_buffer; |
+ int io_buffer_size = 0; |
+ |
+ ASSERT_TRUE(CallOnWillStartAndOnResponseStarted()); |
+ ASSERT_TRUE(handler_->OnWillRead(&io_buffer, &io_buffer_size, -1)); |
+ ASSERT_TRUE(io_buffer); |
+ // The io_buffer size that the mime sniffer requires implicitly. |
+ ASSERT_GE(io_buffer_size, 2 * 1024); |
kinuko
2016/08/04 16:07:02
ditto
yhirano
2016/08/05 12:21:39
Done.
|
+ std::string expected; |
+ for (int i = 0; i < 3 * io_buffer_size + 2; ++i) |
+ expected += ('A' + i % 26); |
+ |
+ ASSERT_TRUE(handler_->OnReadCompleted(0, &defer)); |
+ ASSERT_FALSE(defer); |
+ |
+ url_loader_client_.RunUntilResponseBodyArrived(); |
+ ASSERT_TRUE(url_loader_client_.response_body().is_valid()); |
+ |
+ size_t written = 0; |
+ std::string actual; |
+ while (actual.size() < expected.size()) { |
+ while (written < expected.size() && !defer) { |
+ ASSERT_TRUE(handler_->OnWillRead(&io_buffer, &io_buffer_size, -1)); |
+ const size_t to_be_written = std::min(static_cast<size_t>(io_buffer_size), |
+ expected.size() - written); |
+ memcpy(io_buffer->data(), &expected[written], to_be_written); |
+ ASSERT_TRUE(handler_->OnReadCompleted(to_be_written, &defer)); |
+ written += to_be_written; |
+ } |
+ |
+ char buf[16]; |
+ uint32_t read = sizeof(buf); |
+ MojoResult result = mojo::ReadDataRaw(url_loader_client_.response_body(), |
+ buf, &read, MOJO_READ_DATA_FLAG_NONE); |
+ if (result != MOJO_RESULT_SHOULD_WAIT) { |
+ ASSERT_EQ(MOJO_RESULT_OK, result); |
+ actual.append(buf, read); |
+ } |
+ int resume_count = resource_controller_.num_resume_calls(); |
+ base::RunLoop().RunUntilIdle(); |
+ // Continue writing if controller->Resume() is called. |
+ defer = (resume_count == resource_controller_.num_resume_calls()); |
+ } |
+ EXPECT_EQ(expected, actual); |
+} |
+ |
+TEST_P(MojoAsyncResourceHandlerWithAllocationSizeTest, |
+ BeginWriteFailsOnReadCompleted) { |
+ scoped_refptr<net::IOBuffer> io_buffer; |
+ int io_buffer_size = 0; |
+ bool defer = false; |
+ ASSERT_TRUE(CallOnWillStartAndOnResponseStarted()); |
+ ASSERT_TRUE(handler_->OnWillRead(&io_buffer, &io_buffer_size, -1)); |
+ |
+ handler_->set_begin_write_expectation(MOJO_RESULT_UNKNOWN); |
+ ASSERT_FALSE(handler_->OnReadCompleted(io_buffer_size, &defer)); |
+} |
+ |
+TEST_P(MojoAsyncResourceHandlerWithAllocationSizeTest, |
+ BeginWriteReturnsShouldWaitOnReadCompleted) { |
+ scoped_refptr<net::IOBuffer> io_buffer; |
+ int io_buffer_size = 0; |
+ bool defer = false; |
+ ASSERT_TRUE(CallOnWillStartAndOnResponseStarted()); |
+ ASSERT_TRUE(handler_->OnWillRead(&io_buffer, &io_buffer_size, -1)); |
+ |
+ handler_->set_begin_write_expectation(MOJO_RESULT_SHOULD_WAIT); |
+ ASSERT_TRUE(handler_->OnReadCompleted(io_buffer_size, &defer)); |
+ EXPECT_TRUE(defer); |
+} |
+ |
+TEST_P(MojoAsyncResourceHandlerWithAllocationSizeTest, |
+ BeginWriteFailsOnResume) { |
+ bool defer = false; |
+ int io_buffer_size = 0; |
+ scoped_refptr<net::IOBuffer> io_buffer; |
+ |
+ ASSERT_TRUE(CallOnWillStartAndOnResponseStarted()); |
+ ASSERT_TRUE(handler_->OnWillRead(&io_buffer, &io_buffer_size, -1)); |
+ ASSERT_TRUE(handler_->OnReadCompleted(0, &defer)); |
+ ASSERT_FALSE(defer); |
+ url_loader_client_.RunUntilResponseBodyArrived(); |
+ ASSERT_TRUE(url_loader_client_.response_body().is_valid()); |
+ |
+ while (!defer) { |
+ ASSERT_TRUE(handler_->OnWillRead(&io_buffer, &io_buffer_size, -1)); |
+ ASSERT_TRUE(handler_->OnReadCompleted(io_buffer_size, &defer)); |
+ } |
+ handler_->set_begin_write_expectation(MOJO_RESULT_UNKNOWN); |
+ |
+ while (!resource_controller_.is_cancel_with_error_called()) { |
+ char buf[256]; |
+ uint32_t read = sizeof(buf); |
+ MojoResult result = mojo::ReadDataRaw(url_loader_client_.response_body(), |
+ buf, &read, MOJO_READ_DATA_FLAG_NONE); |
+ ASSERT_TRUE(result == MOJO_RESULT_OK || result == MOJO_RESULT_SHOULD_WAIT); |
+ base::RunLoop().RunUntilIdle(); |
+ } |
+ |
+ EXPECT_FALSE(url_loader_client_.has_received_completion()); |
+ EXPECT_EQ(net::ERR_FAILED, resource_controller_.error()); |
+ EXPECT_EQ(0, resource_controller_.num_resume_calls()); |
+} |
+ |
+TEST_P(MojoAsyncResourceHandlerWithAllocationSizeTest, CancelWhileWaiting) { |
+ bool defer = false; |
+ ASSERT_TRUE(CallOnWillStartAndOnResponseStarted()); |
+ |
+ while (!defer) { |
+ scoped_refptr<net::IOBuffer> io_buffer; |
+ int io_buffer_size = 0; |
+ ASSERT_TRUE(handler_->OnWillRead(&io_buffer, &io_buffer_size, -1)); |
+ ASSERT_TRUE(handler_->OnReadCompleted(io_buffer_size, &defer)); |
+ } |
+ |
+ url_loader_client_.RunUntilResponseBodyArrived(); |
+ ASSERT_TRUE(url_loader_client_.response_body().is_valid()); |
+ |
+ defer = false; |
+ net::URLRequestStatus status(net::URLRequestStatus::CANCELED, |
+ net::ERR_ABORTED); |
+ handler_->OnResponseCompleted(status, "security_info", &defer); |
+ |
+ ASSERT_FALSE(url_loader_client_.has_received_completion()); |
+ url_loader_client_.RunUntilComplete(); |
+ EXPECT_EQ(net::ERR_ABORTED, |
+ url_loader_client_.completion_status().error_code); |
+ |
+ while (true) { |
+ char buffer[16]; |
+ uint32_t read = sizeof(buffer); |
+ MojoResult result = |
+ mojo::ReadDataRaw(url_loader_client_.response_body(), buffer, &read, |
+ MOJO_READ_DATA_FLAG_NONE); |
+ if (result == MOJO_RESULT_FAILED_PRECONDITION) |
+ break; |
+ base::RunLoop().RunUntilIdle(); |
+ DCHECK(result == MOJO_RESULT_SHOULD_WAIT || result == MOJO_RESULT_OK); |
+ } |
+ |
+ base::RunLoop().RunUntilIdle(); |
+ EXPECT_EQ(0, resource_controller_.num_resume_calls()); |
+} |
+ |
+// Typically ResourceHandler methods are called in this order. |
+TEST_P( |
+ MojoAsyncResourceHandlerWithAllocationSizeTest, |
+ OnWillStartThenOnResponseStartedThenOnWillReadThenOnReadCompletedThenOnResponseCompleted) { |
kinuko
2016/08/04 16:07:02
o_O
|
+ rdh_delegate_.set_num_on_response_started_calls_expectation(1); |
+ bool defer = false; |
+ |
+ ASSERT_TRUE(handler_->OnWillStart(request_->url(), &defer)); |
+ ASSERT_FALSE(defer); |
+ scoped_refptr<ResourceResponse> response = new ResourceResponse(); |
+ ASSERT_TRUE(handler_->OnResponseStarted(response.get(), &defer)); |
+ ASSERT_FALSE(defer); |
+ |
+ ASSERT_FALSE(url_loader_client_.has_received_response()); |
+ url_loader_client_.RunUntilResponseReceived(); |
+ |
+ int io_buffer_size = 0; |
+ scoped_refptr<net::IOBuffer> io_buffer; |
+ ASSERT_TRUE(handler_->OnWillRead(&io_buffer, &io_buffer_size, -1)); |
+ ASSERT_TRUE(io_buffer); |
+ ASSERT_GT(io_buffer_size, 0); |
+ io_buffer->data()[0] = 'A'; |
+ |
+ ASSERT_FALSE(url_loader_client_.response_body().is_valid()); |
+ url_loader_client_.RunUntilResponseBodyArrived(); |
+ ASSERT_TRUE(url_loader_client_.response_body().is_valid()); |
+ |
+ ASSERT_TRUE(handler_->OnReadCompleted(1, &defer)); |
+ ASSERT_FALSE(defer); |
+ net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, net::OK); |
+ handler_->OnResponseCompleted(status, "security info", &defer); |
+ ASSERT_FALSE(defer); |
+ |
+ ASSERT_FALSE(url_loader_client_.has_received_completion()); |
+ url_loader_client_.RunUntilComplete(); |
+ EXPECT_EQ(net::OK, url_loader_client_.completion_status().error_code); |
+ |
+ // This is needed because |*io_buffer| may keep the data producer alive. |
+ io_buffer = nullptr; |
+ |
+ std::string body; |
+ while (true) { |
+ char buffer[16]; |
+ uint32_t read = sizeof(buffer); |
+ MojoResult result = |
+ mojo::ReadDataRaw(url_loader_client_.response_body(), buffer, &read, |
+ MOJO_READ_DATA_FLAG_NONE); |
+ if (result == MOJO_RESULT_FAILED_PRECONDITION) |
+ break; |
+ if (result == MOJO_RESULT_SHOULD_WAIT) { |
+ base::RunLoop().RunUntilIdle(); |
+ } else { |
+ ASSERT_EQ(result, MOJO_RESULT_OK); |
+ body.append(buffer, read); |
+ } |
+ } |
+ EXPECT_EQ("A", body); |
+} |
+ |
+// MimeResourceHandler calls delegated ResourceHandler's methods in this order. |
+TEST_P( |
+ MojoAsyncResourceHandlerWithAllocationSizeTest, |
+ OnWillStartThenOnWillReadThenOnResponseStartedThenOnReadCompletedThenOnResponseCompleted) { |
+ rdh_delegate_.set_num_on_response_started_calls_expectation(1); |
+ bool defer = false; |
+ |
+ ASSERT_TRUE(handler_->OnWillStart(request_->url(), &defer)); |
+ ASSERT_FALSE(defer); |
+ |
+ int io_buffer_size = 0; |
+ scoped_refptr<net::IOBuffer> io_buffer; |
+ ASSERT_TRUE(handler_->OnWillRead(&io_buffer, &io_buffer_size, -1)); |
+ ASSERT_TRUE(io_buffer); |
+ ASSERT_GT(io_buffer_size, 0); |
+ io_buffer->data()[0] = 'B'; |
+ |
+ ASSERT_FALSE(url_loader_client_.response_body().is_valid()); |
+ url_loader_client_.RunUntilResponseBodyArrived(); |
+ ASSERT_TRUE(url_loader_client_.response_body().is_valid()); |
+ |
+ scoped_refptr<ResourceResponse> response = new ResourceResponse(); |
+ ASSERT_TRUE(handler_->OnResponseStarted(response.get(), &defer)); |
+ ASSERT_FALSE(defer); |
+ |
+ ASSERT_FALSE(url_loader_client_.has_received_response()); |
+ url_loader_client_.RunUntilResponseReceived(); |
+ |
+ ASSERT_TRUE(handler_->OnReadCompleted(1, &defer)); |
+ ASSERT_FALSE(defer); |
+ net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, net::OK); |
+ handler_->OnResponseCompleted(status, "security info", &defer); |
+ ASSERT_FALSE(defer); |
+ |
+ ASSERT_FALSE(url_loader_client_.has_received_completion()); |
+ url_loader_client_.RunUntilComplete(); |
+ EXPECT_EQ(net::OK, url_loader_client_.completion_status().error_code); |
+ |
+ // This is needed because |*io_buffer| may keep the data producer alive. |
+ io_buffer = nullptr; |
+ |
+ std::string body; |
+ while (true) { |
+ char buffer[16]; |
+ uint32_t read = sizeof(buffer); |
+ MojoResult result = |
+ mojo::ReadDataRaw(url_loader_client_.response_body(), buffer, &read, |
+ MOJO_READ_DATA_FLAG_NONE); |
+ if (result == MOJO_RESULT_FAILED_PRECONDITION) |
+ break; |
+ if (result == MOJO_RESULT_SHOULD_WAIT) { |
+ base::RunLoop().RunUntilIdle(); |
+ } else { |
+ ASSERT_EQ(result, MOJO_RESULT_OK); |
+ body.append(buffer, read); |
+ } |
+ } |
+ EXPECT_EQ("B", body); |
+} |
+ |
+INSTANTIATE_TEST_CASE_P(MojoAsyncResourceHandlerWithAllocationSizeTest, |
+ MojoAsyncResourceHandlerWithAllocationSizeTest, |
+ ::testing::Values(8, 32 * 2014)); |
+} // namespace |
+} // namespace content |