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

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

Issue 1970693002: Use mojo for Chrome Loading, Part 1 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/loader/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

Powered by Google App Engine
This is Rietveld 408576698