| 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..3a642422253cf001c1967d012fba195ce0729268
|
| --- /dev/null
|
| +++ b/content/browser/loader/mojo_async_resource_handler_unittest.cc
|
| @@ -0,0 +1,1151 @@
|
| +// 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 {
|
| +
|
| +constexpr int kSizeMimeSnifferRequiresForFirstOnWillRead = 2048;
|
| +
|
| +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_);
|
| +
|
| + 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(), // request
|
| + RESOURCE_TYPE_XHR, // resource_type
|
| + browser_context_->GetResourceContext(), // context
|
| + 2, // render_process_id
|
| + 0, // render_view_id
|
| + 0, // render_frame_id
|
| + true, // is_main_frame
|
| + false, // parent_is_main_frame
|
| + false, // allow_download
|
| + true, // is_async
|
| + false // is_using_lofi
|
| + );
|
| + 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);
|
| + base::RunLoop().RunUntilIdle();
|
| + }
|
| +
|
| + // 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 = 0;
|
| + 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 = 0;
|
| +
|
| + 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, kSizeMimeSnifferRequiresForFirstOnWillRead);
|
| +
|
| + 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_size = sizeof(buffer);
|
| + MojoResult result =
|
| + mojo::ReadDataRaw(url_loader_client_.response_body(), buffer,
|
| + &read_size, MOJO_READ_DATA_FLAG_NONE);
|
| + if (result == MOJO_RESULT_SHOULD_WAIT) {
|
| + base::RunLoop().RunUntilIdle();
|
| + continue;
|
| + }
|
| + contents.append(buffer, read_size);
|
| + }
|
| + EXPECT_EQ("AB", contents);
|
| +}
|
| +
|
| +TEST_F(MojoAsyncResourceHandlerTest,
|
| + OnWillReadAndOnReadCompletedWithInsufficientInitialCapacity) {
|
| + MojoAsyncResourceHandler::SetAllocationSizeForTesting(2);
|
| +
|
| + 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 buffer size that the mime sniffer requires implicitly.
|
| + ASSERT_GE(io_buffer_size, kSizeMimeSnifferRequiresForFirstOnWillRead);
|
| +
|
| + 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();
|
| + char buffer[16];
|
| + uint32_t read_size = sizeof(buffer);
|
| + MojoResult result =
|
| + mojo::ReadDataRaw(url_loader_client_.response_body(), buffer,
|
| + &read_size, MOJO_READ_DATA_FLAG_NONE);
|
| + if (result == MOJO_RESULT_SHOULD_WAIT)
|
| + continue;
|
| + ASSERT_EQ(MOJO_RESULT_OK, result);
|
| + contents.append(buffer, read_size);
|
| + }
|
| + 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 = 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, kSizeMimeSnifferRequiresForFirstOnWillRead);
|
| +
|
| + 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 = 0;
|
| + 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_size = sizeof(buffer);
|
| + MojoResult result =
|
| + mojo::ReadDataRaw(url_loader_client_.response_body(), buffer,
|
| + &read_size, 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 = 0;
|
| + 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_size = sizeof(buf);
|
| + MojoResult result =
|
| + mojo::ReadDataRaw(url_loader_client_.response_body(), buf, &read_size,
|
| + 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_size);
|
| + }
|
| + 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 = 0;
|
| + 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_size = sizeof(buf);
|
| + MojoResult result =
|
| + mojo::ReadDataRaw(url_loader_client_.response_body(), buf, &read_size,
|
| + 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;
|
| + 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();
|
| +
|
| + std::string actual;
|
| + while (actual.size() < written) {
|
| + char buf[16];
|
| + uint32_t read_size = sizeof(buf);
|
| + MojoResult result =
|
| + mojo::ReadDataRaw(url_loader_client_.response_body(), buf, &read_size,
|
| + 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_size);
|
| + base::RunLoop().RunUntilIdle();
|
| + }
|
| +
|
| + 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;
|
| + 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_size = sizeof(buf);
|
| + MojoResult result =
|
| + mojo::ReadDataRaw(url_loader_client_.response_body(), buf, &read_size,
|
| + 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, kSizeMimeSnifferRequiresForFirstOnWillRead);
|
| + 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_size = sizeof(buf);
|
| + MojoResult result =
|
| + mojo::ReadDataRaw(url_loader_client_.response_body(), buf, &read_size,
|
| + MOJO_READ_DATA_FLAG_NONE);
|
| + if (result != MOJO_RESULT_SHOULD_WAIT) {
|
| + ASSERT_EQ(MOJO_RESULT_OK, result);
|
| + actual.append(buf, read_size);
|
| + }
|
| + 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_size = sizeof(buf);
|
| + MojoResult result =
|
| + mojo::ReadDataRaw(url_loader_client_.response_body(), buf, &read_size,
|
| + 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_size = sizeof(buffer);
|
| + MojoResult result =
|
| + mojo::ReadDataRaw(url_loader_client_.response_body(), buffer,
|
| + &read_size, 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) {
|
| + 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_size = sizeof(buffer);
|
| + MojoResult result =
|
| + mojo::ReadDataRaw(url_loader_client_.response_body(), buffer,
|
| + &read_size, 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_size);
|
| + }
|
| + }
|
| + 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_size = sizeof(buffer);
|
| + MojoResult result =
|
| + mojo::ReadDataRaw(url_loader_client_.response_body(), buffer,
|
| + &read_size, 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_size);
|
| + }
|
| + }
|
| + EXPECT_EQ("B", body);
|
| +}
|
| +
|
| +INSTANTIATE_TEST_CASE_P(MojoAsyncResourceHandlerWithAllocationSizeTest,
|
| + MojoAsyncResourceHandlerWithAllocationSizeTest,
|
| + ::testing::Values(8, 32 * 2014));
|
| +} // namespace
|
| +} // namespace content
|
|
|