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

Side by Side 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, 5 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/browser/loader/mojo_async_resource_handler.h"
6
7 #include <string.h>
8
9 #include <utility>
10
11 #include "base/bind.h"
12 #include "base/callback.h"
13 #include "base/files/file_path.h"
14 #include "base/memory/ptr_util.h"
15 #include "base/memory/scoped_vector.h"
16 #include "base/memory/weak_ptr.h"
17 #include "base/run_loop.h"
18 #include "content/browser/loader/mojo_async_resource_handler_test_util.h"
19 #include "content/browser/loader/resource_dispatcher_host_impl.h"
20 #include "content/browser/loader/resource_request_info_impl.h"
21 #include "content/common/resource_request_completion_status.h"
22 #include "content/common/url_loader.mojom.h"
23 #include "content/public/browser/appcache_service.h"
24 #include "content/public/browser/navigation_data.h"
25 #include "content/public/browser/resource_context.h"
26 #include "content/public/browser/resource_controller.h"
27 #include "content/public/browser/resource_dispatcher_host_delegate.h"
28 #include "content/public/browser/resource_throttle.h"
29 #include "content/public/browser/stream_info.h"
30 #include "content/public/common/resource_response.h"
31 #include "content/public/common/resource_type.h"
32 #include "content/public/test/test_browser_context.h"
33 #include "content/public/test/test_browser_thread_bundle.h"
34 #include "mojo/public/c/system/data_pipe.h"
35 #include "mojo/public/c/system/types.h"
36 #include "mojo/public/cpp/system/data_pipe.h"
37 #include "net/base/auth.h"
38 #include "net/base/net_errors.h"
39 #include "net/http/http_response_headers.h"
40 #include "net/http/http_response_info.h"
41 #include "net/http/http_status_code.h"
42 #include "net/http/http_util.h"
43 #include "net/ssl/client_cert_store.h"
44 #include "net/test/url_request/url_request_failed_job.h"
45 #include "net/url_request/url_request.h"
46 #include "net/url_request/url_request_context.h"
47 #include "net/url_request/url_request_filter.h"
48 #include "net/url_request/url_request_status.h"
49 #include "net/url_request/url_request_test_util.h"
50 #include "testing/gtest/include/gtest/gtest.h"
51 #include "ui/base/page_transition_types.h"
52
53 namespace content {
54 namespace {
55
56 class FakeResourceDispatcherHostDelegate
57 : public ResourceDispatcherHostDelegate {
58 public:
59 FakeResourceDispatcherHostDelegate() {}
60 ~FakeResourceDispatcherHostDelegate() override {}
61
62 bool ShouldBeginRequest(const std::string& method,
63 const GURL& url,
64 ResourceType resource_type,
65 ResourceContext* resource_context) override {
66 ADD_FAILURE() << "ShouldBeginRequest should not be called.";
67 return false;
68 }
69
70 void RequestBeginning(net::URLRequest* request,
71 ResourceContext* resource_context,
72 AppCacheService* appcache_service,
73 ResourceType resource_type,
74 ScopedVector<ResourceThrottle>* throttles) override {
75 ADD_FAILURE() << "RequestBeginning should not be called.";
76 }
77
78 void DownloadStarting(net::URLRequest* request,
79 ResourceContext* resource_context,
80 int child_id,
81 int route_id,
82 bool is_content_initiated,
83 bool must_download,
84 ScopedVector<ResourceThrottle>* throttles) override {
85 ADD_FAILURE() << "DownloadStarting should not be called.";
86 }
87
88 ResourceDispatcherHostLoginDelegate* CreateLoginDelegate(
89 net::AuthChallengeInfo* auth_info,
90 net::URLRequest* request) override {
91 ADD_FAILURE() << "CreateLoginDelegate should not be called.";
92 return nullptr;
93 }
94
95 bool HandleExternalProtocol(
96 const GURL& url,
97 int child_id,
98 const ResourceRequestInfo::WebContentsGetter& web_contents_getter,
99 bool is_main_frame,
100 ui::PageTransition page_transition,
101 bool has_user_gesture,
102 ResourceContext* resource_context) override {
103 ADD_FAILURE() << "HandleExternalProtocol should not be called.";
104 return false;
105 }
106
107 bool ShouldForceDownloadResource(const GURL& url,
108 const std::string& mime_type) override {
109 ADD_FAILURE() << "ShouldForceDownloadResource should not be called.";
110 return false;
111 }
112
113 bool ShouldInterceptResourceAsStream(net::URLRequest* request,
114 const base::FilePath& plugin_path,
115 const std::string& mime_type,
116 GURL* origin,
117 std::string* payload) override {
118 ADD_FAILURE() << "ShouldInterceptResourceAsStream should not be called.";
119 return false;
120 }
121
122 void OnStreamCreated(net::URLRequest* request,
123 std::unique_ptr<content::StreamInfo> stream) override {
124 ADD_FAILURE() << "OnStreamCreated should not be called.";
125 }
126
127 void OnResponseStarted(net::URLRequest* request,
128 ResourceContext* resource_context,
129 ResourceResponse* response) override {
130 is_on_response_started_called_ = true;
131 }
132
133 void OnRequestRedirected(const GURL& redirect_url,
134 net::URLRequest* request,
135 ResourceContext* resource_context,
136 ResourceResponse* response) override {
137 ADD_FAILURE() << "OnRequestRedirected should not be called.";
138 }
139
140 void RequestComplete(net::URLRequest* url_request) override {
141 ADD_FAILURE() << "RequestComplete should not be called.";
142 }
143
144 bool ShouldEnableLoFiMode(
145 const net::URLRequest& url_request,
146 content::ResourceContext* resource_context) override {
147 ADD_FAILURE() << "ShouldEnableLoFiMode should not be called.";
148 return false;
149 }
150
151 NavigationData* GetNavigationData(net::URLRequest* request) const override {
152 ADD_FAILURE() << "GetNavigationData should not be called.";
153 return nullptr;
154 }
155
156 std::unique_ptr<net::ClientCertStore> CreateClientCertStore(
157 ResourceContext* resource_context) override {
158 ADD_FAILURE() << "CreateClientCertStore should not be called.";
159 return nullptr;
160 }
161
162 bool is_on_response_started_called() const {
163 return is_on_response_started_called_;
164 }
165
166 private:
167 bool is_on_response_started_called_ = false;
mmenke 2016/07/25 22:03:54 is -> was? Or better, make this an integer, and c
yhirano 2016/07/27 16:13:28 Done.
168
169 DISALLOW_COPY_AND_ASSIGN(FakeResourceDispatcherHostDelegate);
mmenke 2016/07/25 22:03:54 include base/macros.h
yhirano 2016/07/27 16:13:29 My understanding is mojo_async_resource_handler.h
mmenke 2016/07/27 16:49:36 Hrm...I've always considered foo.h the related hea
170 };
171
172 class FakeResourceController : public ResourceController {
173 public:
174 FakeResourceController() {}
175 ~FakeResourceController() override {}
176
177 void Cancel() override { ADD_FAILURE() << "Cancel should not be called."; }
178
179 void CancelAndIgnore() override {
180 ADD_FAILURE() << "CancelAndIgnore should not be called.";
181 }
182
183 void CancelWithError(int error_code) override {
184 is_cancel_with_error_called_ = true;
185 error_ = error_code;
186 if (quit_closure_)
187 quit_closure_.Run();
188 }
189
190 void Resume() override {
191 ++num_resume_calls_;
192 if (quit_closure_)
193 quit_closure_.Run();
194 }
195
196 void set_quit_closure(const base::Closure& quit_closure) {
197 quit_closure_ = quit_closure;
198 }
199
200 bool is_cancel_with_error_called() const {
201 return is_cancel_with_error_called_;
202 }
203 int error() const { return error_; }
204 int num_resume_calls() const { return num_resume_calls_; }
205
206 private:
207 bool is_cancel_with_error_called_ = false;
208 int error_ = net::OK;
209 int num_resume_calls_ = 0;
210 base::Closure quit_closure_;
211
212 DISALLOW_COPY_AND_ASSIGN(FakeResourceController);
213 };
214
215 class MojoAsyncResourceHandlerWithCustomDataPipeOperations
216 : public MojoAsyncResourceHandler {
217 public:
218 MojoAsyncResourceHandlerWithCustomDataPipeOperations(
219 net::URLRequest* request,
220 ResourceDispatcherHostImpl* rdh,
221 mojo::InterfaceRequest<mojom::URLLoader> mojo_request,
222 mojom::URLLoaderClientPtr url_loader_client)
223 : MojoAsyncResourceHandler(request,
224 rdh,
225 std::move(mojo_request),
226 std::move(url_loader_client)) {}
227 ~MojoAsyncResourceHandlerWithCustomDataPipeOperations() override {}
228
229 void set_begin_write_expectation(MojoResult begin_write_expectation) {
230 is_begin_write_expectation_set_ = true;
231 begin_write_expectation_ = begin_write_expectation;
232 }
233 void set_end_write_expectation(MojoResult end_write_expectation) {
234 is_end_write_expectation_set_ = true;
235 end_write_expectation_ = end_write_expectation;
236 }
237
238 private:
239 MojoResult BeginWrite(void** data, uint32_t* available) override {
240 if (is_begin_write_expectation_set_)
241 return begin_write_expectation_;
242 return MojoAsyncResourceHandler::BeginWrite(data, available);
243 }
244 MojoResult EndWrite(uint32_t written) override {
245 if (is_end_write_expectation_set_)
246 return end_write_expectation_;
247 return MojoAsyncResourceHandler::EndWrite(written);
248 }
249
250 bool is_begin_write_expectation_set_ = false;
251 bool is_end_write_expectation_set_ = false;
252 MojoResult begin_write_expectation_ = MOJO_RESULT_UNKNOWN;
253 MojoResult end_write_expectation_ = MOJO_RESULT_UNKNOWN;
254
255 DISALLOW_COPY_AND_ASSIGN(
256 MojoAsyncResourceHandlerWithCustomDataPipeOperations);
257 };
258
259 class MojoAsyncResourceHandlerTestBase {
260 public:
261 MojoAsyncResourceHandlerTestBase()
262 : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
263 browser_context_(new TestBrowserContext()) {
264 MojoAsyncResourceHandler::SetAllocationSizeForTesting(32 * 1024);
265
266 // Calling this function creates a request context.
267 browser_context_->GetResourceContext()->GetRequestContext();
268 base::RunLoop().RunUntilIdle();
269
270 url_request_delegate_.reset(new net::TestDelegate());
271 net::URLRequestContext* request_context =
272 browser_context_->GetResourceContext()->GetRequestContext();
273 request_ = request_context->CreateRequest(
274 net::URLRequestFailedJob::GetMockHttpUrl(net::ERR_TIMED_OUT),
275 net::DEFAULT_PRIORITY, url_request_delegate_.get());
276 ResourceRequestInfo::AllocateForTesting(
277 request_.get(), RESOURCE_TYPE_XHR,
278 browser_context_->GetResourceContext(), 2, 0, 0, true, false, false,
279 true, false);
280 handler_.reset(new MojoAsyncResourceHandlerWithCustomDataPipeOperations(
281 request_.get(), &rdh_, nullptr,
282 url_loader_client_.CreateInterfacePtrAndBind()));
283 handler_->SetController(&resource_controller_);
284 }
285
286 virtual ~MojoAsyncResourceHandlerTestBase() {
287 rdh_.SetDelegate(nullptr);
mmenke 2016/07/25 22:03:54 Should we just make rdh_delegate_ part of the test
yhirano 2016/07/27 16:13:28 Done.
288 net::URLRequestFilter::GetInstance()->ClearHandlers();
289 MojoAsyncResourceHandler::SetAllocationSizeForTesting(
290 MojoAsyncResourceHandler::kDefaultAllocationSize);
291 }
292
293 void RunUntilNextNotification() {
294 base::RunLoop run_loop;
295 url_loader_client_.set_quit_closure(run_loop.QuitClosure());
296 resource_controller_.set_quit_closure(run_loop.QuitClosure());
297 run_loop.Run();
298 }
299
300 TestBrowserThreadBundle thread_bundle_;
301 ResourceDispatcherHostImpl rdh_;
302 FakeURLLoaderClient url_loader_client_;
303 FakeResourceController resource_controller_;
304 std::unique_ptr<TestBrowserContext> browser_context_;
305 std::unique_ptr<net::TestDelegate> url_request_delegate_;
306 std::unique_ptr<net::URLRequest> request_;
307 std::unique_ptr<MojoAsyncResourceHandlerWithCustomDataPipeOperations>
308 handler_;
309
310 DISALLOW_COPY_AND_ASSIGN(MojoAsyncResourceHandlerTestBase);
311 };
312
313 class MojoAsyncResourceHandlerTest : public MojoAsyncResourceHandlerTestBase,
314 public ::testing::Test {};
315
316 // This test class is parameterized with MojoAsyncResourceHandler's allocation
317 // size.
318 class MojoAsyncResourceHandlerWithAllocationSizeTest
319 : public MojoAsyncResourceHandlerTestBase,
320 public ::testing::TestWithParam<size_t> {
321 protected:
322 MojoAsyncResourceHandlerWithAllocationSizeTest() {
323 MojoAsyncResourceHandler::SetAllocationSizeForTesting(GetParam());
324 }
325 };
326
327 TEST_F(MojoAsyncResourceHandlerTest, InFlightRequests) {
328 EXPECT_EQ(0, rdh_.num_in_flight_requests_for_testing());
329 handler_ = nullptr;
330 EXPECT_EQ(0, rdh_.num_in_flight_requests_for_testing());
331 }
332
333 TEST_F(MojoAsyncResourceHandlerTest, OnResponseStarted) {
334 scoped_refptr<ResourceResponse> response = new ResourceResponse();
335 FakeResourceDispatcherHostDelegate rdh_delegate;
336 response->head.content_length = 99;
337 response->head.request_start =
338 base::TimeTicks::UnixEpoch() + base::TimeDelta::FromDays(14);
339 response->head.response_start =
340 base::TimeTicks::UnixEpoch() + base::TimeDelta::FromDays(28);
341
342 bool defer = false;
343
344 base::TimeTicks now1 = base::TimeTicks::Now();
mmenke 2016/07/25 22:03:54 Call OnWillStart?
345 rdh_.SetDelegate(&rdh_delegate);
346 ASSERT_TRUE(handler_->OnResponseStarted(response.get(), &defer));
347 rdh_.SetDelegate(nullptr);
348 base::TimeTicks now2 = base::TimeTicks::Now();
349
350 EXPECT_FALSE(defer);
351 EXPECT_EQ(request_->creation_time(), response->head.request_start);
352 EXPECT_LE(now1, response->head.response_start);
353 EXPECT_LE(response->head.response_start, now2);
354 EXPECT_TRUE(rdh_delegate.is_on_response_started_called());
355
356 RunUntilNextNotification();
mmenke 2016/07/25 22:03:54 What do you think of more specific methods for the
yhirano 2016/07/27 16:13:29 Done.
357 EXPECT_TRUE(url_loader_client_.has_received_response());
358 EXPECT_EQ(response->head.request_start,
359 url_loader_client_.response_head().request_start);
360 EXPECT_EQ(response->head.response_start,
361 url_loader_client_.response_head().response_start);
362 EXPECT_EQ(99, url_loader_client_.response_head().content_length);
363 }
364
365 TEST_F(MojoAsyncResourceHandlerTest, OnWillStart) {
mmenke 2016/07/25 22:03:53 Seems like this should be first - it's always call
yhirano 2016/07/27 16:13:29 Done.
366 bool defer = false;
367 EXPECT_TRUE(handler_->OnWillStart(request_->url(), &defer));
368 EXPECT_FALSE(defer);
369 }
370
371 TEST_F(MojoAsyncResourceHandlerTest, OnBeforeNetworkStart) {
372 bool defer = false;
373 EXPECT_TRUE(handler_->OnBeforeNetworkStart(request_->url(), &defer));
mmenke 2016/07/25 22:03:54 Now this method really has been removed, honest!
yhirano 2016/07/27 16:13:28 Done.
374 EXPECT_FALSE(defer);
375 }
376
377 TEST_F(MojoAsyncResourceHandlerTest, OnWillReadAndInFlightRequests) {
378 EXPECT_EQ(0, rdh_.num_in_flight_requests_for_testing());
379 scoped_refptr<net::IOBuffer> buffer;
380 int buf_size;
381 EXPECT_TRUE(handler_->OnWillRead(&buffer, &buf_size, -1));
mmenke 2016/07/25 22:03:54 Just calling this method seems weird - normally we
yhirano 2016/07/27 16:13:28 Having more tests sounds a good idea. Done. I thi
mmenke 2016/07/27 16:49:36 I really think we should mimic real world usage as
yhirano 2016/07/28 14:50:46 Done.
382 EXPECT_EQ(1, rdh_.num_in_flight_requests_for_testing());
383 handler_ = nullptr;
384 EXPECT_EQ(0, rdh_.num_in_flight_requests_for_testing());
385 }
386
387 TEST_F(MojoAsyncResourceHandlerTest, OnWillReadWithInsufficientResource) {
388 rdh_.set_max_num_in_flight_requests_per_process(0);
389
390 scoped_refptr<net::IOBuffer> buffer;
391 int buf_size = 0;
392 EXPECT_FALSE(handler_->OnWillRead(&buffer, &buf_size, -1));
mmenke 2016/07/25 22:03:53 Not going to comment for all of these, but think t
393 EXPECT_FALSE(buffer);
394 EXPECT_EQ(0, buf_size);
395 EXPECT_EQ(1, rdh_.num_in_flight_requests_for_testing());
396 EXPECT_TRUE(resource_controller_.is_cancel_with_error_called());
397 EXPECT_EQ(net::ERR_INSUFFICIENT_RESOURCES, resource_controller_.error());
398 handler_ = nullptr;
399 EXPECT_EQ(0, rdh_.num_in_flight_requests_for_testing());
400 }
401
402 TEST_F(MojoAsyncResourceHandlerTest, OnWillReadAndOnReadCompleted) {
403 bool defer = false;
404 scoped_refptr<net::IOBuffer> buffer;
405 int buf_size;
406
407 ASSERT_TRUE(handler_->OnWillRead(&buffer, &buf_size, -1));
408 ASSERT_TRUE(buffer);
409 // The buffer size that the mime sniffer requires implicitly.
410 ASSERT_GE(buf_size, 2 * 1024);
411
412 RunUntilNextNotification();
413 ASSERT_TRUE(url_loader_client_.response_body().is_valid());
414
415 buffer->data()[0] = 'A';
416 buffer->data()[1] = 'B';
417 ASSERT_TRUE(handler_->OnReadCompleted(2, &defer));
418 EXPECT_FALSE(defer);
419
420 std::string contents;
mmenke 2016/07/25 22:03:54 include <string>?
yhirano 2016/07/27 16:13:28 It's included in mojo_async_resource_handler.h.
421 do {
422 char buffer[16];
mmenke 2016/07/25 22:03:53 There's another local called buffer outside this l
yhirano 2016/07/27 16:13:28 Done.
423 uint32_t read = sizeof(buffer);
mmenke 2016/07/25 22:03:54 include stdint.h?
mmenke 2016/07/25 22:03:54 sizeof => arraysize?
yhirano 2016/07/27 16:13:28 sizeof is more preferable here, as the argument re
yhirano 2016/07/27 16:13:28 It's included in mojo_async_resource_handler.h.
424 MojoResult result =
425 mojo::ReadDataRaw(url_loader_client_.response_body(), buffer, &read,
426 MOJO_READ_DATA_FLAG_NONE);
427 if (result == MOJO_RESULT_SHOULD_WAIT)
mmenke 2016/07/25 22:03:54 Is there any spec on what we have to do if we get
yhirano 2016/07/27 16:13:28 In production code, we use mojo::Watcher to be not
428 continue;
429 contents.append(buffer, read);
430 } while (contents.size() < 2);
mmenke 2016/07/25 22:03:53 optional: Suggest switching to a while() loop - t
yhirano 2016/07/27 16:13:28 Done.
431 EXPECT_EQ("AB", contents);
432 }
433
434 TEST_F(MojoAsyncResourceHandlerTest,
435 OnWillReadAndOnReadCompletedWithInsufficientInitialCapacity) {
436 MojoAsyncResourceHandler::SetAllocationSizeForTesting(2);
437
438 bool defer = false;
439 scoped_refptr<net::IOBuffer> buffer;
440 int buf_size;
441
442 ASSERT_TRUE(handler_->OnWillRead(&buffer, &buf_size, -1));
443 ASSERT_TRUE(buffer);
444 // The buffer size that the mime sniffer requires implicitly.
445 ASSERT_GE(buf_size, 2 * 1024);
446
447 RunUntilNextNotification();
448 ASSERT_TRUE(url_loader_client_.response_body().is_valid());
449
450 const std::string data("abcdefgh");
451 strcpy(buffer->data(), data.c_str());
452 ASSERT_TRUE(handler_->OnReadCompleted(data.size(), &defer));
453 EXPECT_TRUE(defer);
454
455 std::string contents;
456 do {
457 // This is needed for Resume to be called.
458 base::RunLoop().RunUntilIdle();
459 char buffer[16];
mmenke 2016/07/25 22:03:53 There's another local called buffer outside this l
yhirano 2016/07/27 16:13:29 Done.
460 uint32_t read = sizeof(buffer);
461 MojoResult result =
462 mojo::ReadDataRaw(url_loader_client_.response_body(), buffer, &read,
463 MOJO_READ_DATA_FLAG_NONE);
464 if (result == MOJO_RESULT_SHOULD_WAIT)
465 continue;
466 ASSERT_EQ(MOJO_RESULT_OK, result);
467 contents.append(buffer, read);
468 } while (contents.size() < data.size());
mmenke 2016/07/25 22:03:53 Again, suggest a while loop
yhirano 2016/07/27 16:13:29 Done.
469 EXPECT_EQ(data, contents);
470 EXPECT_EQ(0, resource_controller_.num_resume_calls());
471 }
472
473 TEST_F(MojoAsyncResourceHandlerTest,
474 IOBufferFromOnWillReadShouldRemainValidEvenIfHandlerIsGone) {
475 scoped_refptr<net::IOBuffer> io_buffer;
476 int buf_size;
477
478 ASSERT_TRUE(handler_->OnWillRead(&io_buffer, &buf_size, -1));
479 ASSERT_TRUE(io_buffer);
480 // The io_buffer size that the mime sniffer requires implicitly.
481 ASSERT_GE(buf_size, 2 * 1024);
482
483 handler_ = nullptr;
484 url_loader_client_.Unbind();
485 base::RunLoop().RunUntilIdle();
486
487 // Hopefully ASAN checks this operation's validity.
488 io_buffer->data()[0] = 'A';
489 }
490
491 TEST_F(MojoAsyncResourceHandlerTest, OnResponseCompleted) {
492 scoped_refptr<ResourceResponse> response = new ResourceResponse();
493 bool defer = false;
494 ASSERT_TRUE(handler_->OnResponseStarted(response.get(), &defer));
495 EXPECT_FALSE(defer);
496 RunUntilNextNotification();
497 EXPECT_TRUE(url_loader_client_.has_received_response());
498
499 handler_->GetRequestInfoForTesting()->set_was_ignored_by_handler(false);
500 net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, net::OK);
501 std::string security_info = "info0";
502
503 base::TimeTicks now1 = base::TimeTicks::Now();
504 handler_->OnResponseCompleted(status, security_info, &defer);
505 base::TimeTicks now2 = base::TimeTicks::Now();
506 EXPECT_FALSE(defer);
507
508 RunUntilNextNotification();
509 EXPECT_TRUE(url_loader_client_.has_received_completion());
510 EXPECT_EQ(net::OK, url_loader_client_.completion_status().error_code);
511 EXPECT_FALSE(url_loader_client_.completion_status().was_ignored_by_handler);
512 EXPECT_EQ("info0", url_loader_client_.completion_status().security_info);
513 EXPECT_LE(now1, url_loader_client_.completion_status().completion_time);
514 EXPECT_LE(url_loader_client_.completion_status().completion_time, now2);
515 EXPECT_EQ(request_->GetTotalReceivedBytes(),
516 url_loader_client_.completion_status().encoded_data_length);
517 }
518
519 // This test case sets different status values from OnResponseCompleted.
520 TEST_F(MojoAsyncResourceHandlerTest, OnResponseCompleted2) {
521 scoped_refptr<ResourceResponse> response = new ResourceResponse();
522 bool defer = false;
523 ASSERT_TRUE(handler_->OnResponseStarted(response.get(), &defer));
524 EXPECT_FALSE(defer);
525
526 handler_->GetRequestInfoForTesting()->set_was_ignored_by_handler(true);
527 net::URLRequestStatus status(net::URLRequestStatus::CANCELED,
528 net::ERR_ABORTED);
529 std::string security_info = "info1";
530
531 base::TimeTicks now1 = base::TimeTicks::Now();
532 handler_->OnResponseCompleted(status, security_info, &defer);
533 base::TimeTicks now2 = base::TimeTicks::Now();
534 EXPECT_FALSE(defer);
535
536 RunUntilNextNotification();
537 EXPECT_TRUE(url_loader_client_.has_received_completion());
538 EXPECT_EQ(net::ERR_ABORTED,
539 url_loader_client_.completion_status().error_code);
540 EXPECT_TRUE(url_loader_client_.completion_status().was_ignored_by_handler);
541 EXPECT_EQ("info1", url_loader_client_.completion_status().security_info);
542 EXPECT_LE(now1, url_loader_client_.completion_status().completion_time);
543 EXPECT_LE(url_loader_client_.completion_status().completion_time, now2);
544 EXPECT_EQ(request_->GetTotalReceivedBytes(),
545 url_loader_client_.completion_status().encoded_data_length);
546 }
547
548 TEST_F(MojoAsyncResourceHandlerTest, OnResponseCompletedWithCanceledTimedOut) {
549 net::URLRequestStatus status(net::URLRequestStatus::CANCELED,
550 net::ERR_TIMED_OUT);
551 bool defer = false;
552
553 handler_->OnResponseCompleted(status, "security_info", &defer);
554 EXPECT_FALSE(defer);
555
556 RunUntilNextNotification();
557 EXPECT_TRUE(url_loader_client_.has_received_completion());
558 EXPECT_EQ(net::ERR_TIMED_OUT,
559 url_loader_client_.completion_status().error_code);
560 }
561
562 TEST_F(MojoAsyncResourceHandlerTest, OnResponseCompletedWithFailedTimedOut) {
563 net::URLRequestStatus status(net::URLRequestStatus::FAILED,
564 net::ERR_TIMED_OUT);
565 bool defer = false;
566
567 handler_->OnResponseCompleted(status, "security_info", &defer);
568 EXPECT_FALSE(defer);
569
570 RunUntilNextNotification();
571 EXPECT_TRUE(url_loader_client_.has_received_completion());
572 EXPECT_EQ(net::ERR_TIMED_OUT,
573 url_loader_client_.completion_status().error_code);
574 }
575
576 TEST_F(MojoAsyncResourceHandlerTest, ResponseCompletionShouldCloseDataPipe) {
577 scoped_refptr<ResourceResponse> response = new ResourceResponse();
578 bool defer = false;
579 ASSERT_TRUE(handler_->OnResponseStarted(response.get(), &defer));
580 EXPECT_FALSE(defer);
581 RunUntilNextNotification();
582 EXPECT_TRUE(url_loader_client_.has_received_response());
583
584 scoped_refptr<net::IOBuffer> io_buffer;
585 int buf_size;
586 ASSERT_TRUE(handler_->OnWillRead(&io_buffer, &buf_size, -1));
587 RunUntilNextNotification();
588 ASSERT_TRUE(url_loader_client_.response_body().is_valid());
589 ASSERT_TRUE(handler_->OnReadCompleted(0, &defer));
590 EXPECT_FALSE(defer);
591
592 net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, net::OK);
593 handler_->OnResponseCompleted(status, "security_info", &defer);
594 EXPECT_FALSE(defer);
595
596 RunUntilNextNotification();
597 EXPECT_TRUE(url_loader_client_.has_received_completion());
598 EXPECT_EQ(net::OK, url_loader_client_.completion_status().error_code);
599
600 // This is needed because |*io_buffer| may keep the data producer alive.
601 io_buffer = nullptr;
602
603 while (true) {
604 char buffer[16];
605 uint32_t read = sizeof(buffer);
606 MojoResult result =
607 mojo::ReadDataRaw(url_loader_client_.response_body(), buffer, &read,
608 MOJO_READ_DATA_FLAG_NONE);
609 if (result == MOJO_RESULT_FAILED_PRECONDITION)
610 break;
611 ASSERT_EQ(result, MOJO_RESULT_SHOULD_WAIT);
612 }
613 }
614
615 TEST_F(MojoAsyncResourceHandlerTest, ResponseErrorDuringBodyTransmission) {
mmenke 2016/07/25 22:03:54 Should we have a failure like this, but where the
yhirano 2016/07/27 16:13:28 Done.
mmenke 2016/07/27 21:38:21 I don't think it does - in that test, we fail when
yhirano 2016/07/28 14:50:45 Hmm, is CancelWhileWaiting what you want? I have
mmenke 2016/07/29 20:01:14 Looks like it.
616 scoped_refptr<ResourceResponse> response = new ResourceResponse();
617 bool defer = false;
618 ASSERT_TRUE(handler_->OnResponseStarted(response.get(), &defer));
619 EXPECT_FALSE(defer);
620 RunUntilNextNotification();
621 EXPECT_TRUE(url_loader_client_.has_received_response());
622
623 scoped_refptr<net::IOBuffer> io_buffer;
624 int buf_size;
625 ASSERT_TRUE(handler_->OnWillRead(&io_buffer, &buf_size, -1));
626 RunUntilNextNotification();
627 ASSERT_TRUE(url_loader_client_.response_body().is_valid());
628 ASSERT_GT(buf_size, 0);
629 memset(io_buffer->data(), 'a', buf_size);
630 ASSERT_TRUE(handler_->OnReadCompleted(buf_size, &defer));
631
632 defer = false;
633 net::URLRequestStatus status(net::URLRequestStatus::FAILED, net::ERR_FAILED);
634 handler_->OnResponseCompleted(status, "security_info", &defer);
635 EXPECT_FALSE(defer);
636
637 RunUntilNextNotification();
638 EXPECT_TRUE(url_loader_client_.has_received_completion());
639 EXPECT_EQ(net::ERR_FAILED, url_loader_client_.completion_status().error_code);
640
641 // This is needed because |*io_buffer| may keep the data producer alive.
642 io_buffer = nullptr;
643
644 std::string actual;
645 while (true) {
646 char buf[16];
647 uint32_t read = sizeof(buf);
648 MojoResult result = mojo::ReadDataRaw(url_loader_client_.response_body(),
649 buf, &read, MOJO_READ_DATA_FLAG_NONE);
650 if (result == MOJO_RESULT_FAILED_PRECONDITION)
651 break;
652 if (result == MOJO_RESULT_SHOULD_WAIT)
653 continue;
654 EXPECT_EQ(MOJO_RESULT_OK, result);
655 actual.append(buf, read);
656 }
657 EXPECT_EQ(std::string(buf_size, 'a'), actual);
658 }
659
660 TEST_F(MojoAsyncResourceHandlerTest, BeginWriteFailsOnWillRead) {
661 handler_->set_begin_write_expectation(MOJO_RESULT_UNKNOWN);
662 scoped_refptr<net::IOBuffer> io_buffer;
663 int buf_size = 0;
664 ASSERT_FALSE(handler_->OnWillRead(&io_buffer, &buf_size, -1));
665 EXPECT_FALSE(resource_controller_.is_cancel_with_error_called());
666 }
667
668 TEST_F(MojoAsyncResourceHandlerTest, BeginWriteReturnsShouldWaitOnWillRead) {
669 handler_->set_begin_write_expectation(MOJO_RESULT_SHOULD_WAIT);
mmenke 2016/07/25 22:03:54 Seems like we should simulate both the case where
yhirano 2016/07/27 16:13:28 Sorry, what do you mean by "handler is ready"?
mmenke 2016/07/27 16:49:36 Erm... the mojo channel thing is ready for data.
yhirano 2016/07/28 14:50:46 Added BeginWriteReturnsShouldWaitOnWillReadAndThen
670 scoped_refptr<net::IOBuffer> io_buffer;
671 int buf_size = 0;
672 ASSERT_TRUE(handler_->OnWillRead(&io_buffer, &buf_size, -1));
673 EXPECT_TRUE(io_buffer);
674 EXPECT_GT(buf_size, 0);
675 }
676
677 TEST_F(MojoAsyncResourceHandlerTest,
678 EndWriteFailsOnWillReadWithInsufficientInitialCapacity) {
679 MojoAsyncResourceHandler::SetAllocationSizeForTesting(2);
680 handler_->set_end_write_expectation(MOJO_RESULT_UNKNOWN);
681 scoped_refptr<net::IOBuffer> io_buffer;
682 int buf_size = 0;
683 ASSERT_FALSE(handler_->OnWillRead(&io_buffer, &buf_size, -1));
684 }
685
686 TEST_F(MojoAsyncResourceHandlerTest, EndWriteFailsOnReadCompleted) {
687 scoped_refptr<net::IOBuffer> io_buffer;
688 int buf_size = 0;
689 bool defer = false;
690 ASSERT_TRUE(handler_->OnWillRead(&io_buffer, &buf_size, -1));
691
692 handler_->set_end_write_expectation(MOJO_RESULT_SHOULD_WAIT);
693 ASSERT_FALSE(handler_->OnReadCompleted(buf_size, &defer));
694 }
695
696 TEST_F(MojoAsyncResourceHandlerTest,
697 EndWriteFailsOnReadCompletedWithInsufficientInitialCapacity) {
698 MojoAsyncResourceHandler::SetAllocationSizeForTesting(2);
699 scoped_refptr<net::IOBuffer> io_buffer;
700 int buf_size = 0;
701 bool defer = false;
702 ASSERT_TRUE(handler_->OnWillRead(&io_buffer, &buf_size, -1));
703
704 handler_->set_end_write_expectation(MOJO_RESULT_SHOULD_WAIT);
705 ASSERT_FALSE(handler_->OnReadCompleted(buf_size, &defer));
706 }
707
708 TEST_F(MojoAsyncResourceHandlerTest,
709 EndWriteFailsOnResumeWithInsufficientInitialCapacity) {
710 MojoAsyncResourceHandler::SetAllocationSizeForTesting(8);
711 scoped_refptr<net::IOBuffer> io_buffer;
712 int buf_size = 0;
713 ASSERT_TRUE(handler_->OnWillRead(&io_buffer, &buf_size, -1));
714 RunUntilNextNotification();
715 ASSERT_TRUE(url_loader_client_.response_body().is_valid());
716
717 while (true) {
718 bool defer = false;
719 ASSERT_TRUE(handler_->OnReadCompleted(buf_size, &defer));
720 ASSERT_GE(buf_size, 0);
721 if (defer)
722 break;
723 ASSERT_TRUE(handler_->OnWillRead(&io_buffer, &buf_size, -1));
724 }
725
726 while (true) {
727 char buf[16];
728 uint32_t read = sizeof(buf);
729 MojoResult result = mojo::ReadDataRaw(url_loader_client_.response_body(),
730 buf, &read, MOJO_READ_DATA_FLAG_NONE);
731 if (result == MOJO_RESULT_SHOULD_WAIT)
732 break;
733 ASSERT_EQ(MOJO_RESULT_OK, result);
734 }
735
736 handler_->set_end_write_expectation(MOJO_RESULT_SHOULD_WAIT);
737 RunUntilNextNotification();
738 EXPECT_FALSE(url_loader_client_.has_received_completion());
739 EXPECT_TRUE(resource_controller_.is_cancel_with_error_called());
740 EXPECT_EQ(net::ERR_FAILED, resource_controller_.error());
741 }
742
743 TEST_P(MojoAsyncResourceHandlerWithAllocationSizeTest,
744 OnWillReadWithLongContents) {
745 bool defer = false;
746 scoped_refptr<net::IOBuffer> io_buffer;
747 int buf_size = 0;
748
749 ASSERT_TRUE(handler_->OnWillRead(&io_buffer, &buf_size, -1));
750 ASSERT_TRUE(io_buffer);
751 // The io_buffer size that the mime sniffer requires implicitly.
752 ASSERT_GE(buf_size, 2 * 1024);
753 std::string expected;
754 for (int i = 0; i < 3 * buf_size + 2; ++i)
755 expected += ('A' + i % 26);
756
757 ASSERT_TRUE(handler_->OnReadCompleted(0, &defer));
758 ASSERT_FALSE(defer);
759
760 RunUntilNextNotification();
761 ASSERT_TRUE(url_loader_client_.response_body().is_valid());
762
763 size_t written = 0;
764 std::string actual;
765 while (actual.size() < expected.size()) {
766 while (written < expected.size() && !defer) {
767 ASSERT_TRUE(handler_->OnWillRead(&io_buffer, &buf_size, -1));
768 const size_t to_be_written =
769 std::min(static_cast<size_t>(buf_size), expected.size() - written);
770 memcpy(io_buffer->data(), &expected[written], to_be_written);
771 ASSERT_TRUE(handler_->OnReadCompleted(to_be_written, &defer));
772 written += to_be_written;
773 }
774
775 char buf[16];
776 uint32_t read = sizeof(buf);
777 MojoResult result = mojo::ReadDataRaw(url_loader_client_.response_body(),
778 buf, &read, MOJO_READ_DATA_FLAG_NONE);
779 if (result != MOJO_RESULT_SHOULD_WAIT) {
780 ASSERT_EQ(MOJO_RESULT_OK, result);
781 actual.append(buf, read);
782 }
783 int resume_count = resource_controller_.num_resume_calls();
784 base::RunLoop().RunUntilIdle();
785 // Continue writing if controller->Resume() is called.
786 defer = (resume_count == resource_controller_.num_resume_calls());
787 }
788 EXPECT_EQ(expected, actual);
789 }
790
791 TEST_P(MojoAsyncResourceHandlerWithAllocationSizeTest,
792 BeginWriteFailsOnReadCompleted) {
793 scoped_refptr<net::IOBuffer> io_buffer;
794 int buf_size = 0;
795 bool defer = false;
796 ASSERT_TRUE(handler_->OnWillRead(&io_buffer, &buf_size, -1));
797
798 handler_->set_begin_write_expectation(MOJO_RESULT_UNKNOWN);
799 ASSERT_FALSE(handler_->OnReadCompleted(buf_size, &defer));
800 }
801
802 TEST_P(MojoAsyncResourceHandlerWithAllocationSizeTest,
803 BeginWriteReturnsShouldWaitOnReadCompleted) {
804 scoped_refptr<net::IOBuffer> io_buffer;
805 int buf_size = 0;
806 bool defer = false;
807 ASSERT_TRUE(handler_->OnWillRead(&io_buffer, &buf_size, -1));
808
809 handler_->set_begin_write_expectation(MOJO_RESULT_SHOULD_WAIT);
810 ASSERT_TRUE(handler_->OnReadCompleted(buf_size, &defer));
811 EXPECT_TRUE(defer);
812 }
813
814 TEST_P(MojoAsyncResourceHandlerWithAllocationSizeTest,
815 BeginWriteFailsOnResume) {
816 bool defer = false;
817 int buf_size = 0;
818 scoped_refptr<net::IOBuffer> io_buffer;
819
820 ASSERT_TRUE(handler_->OnWillRead(&io_buffer, &buf_size, -1));
821 ASSERT_TRUE(handler_->OnReadCompleted(0, &defer));
822 ASSERT_FALSE(defer);
823 RunUntilNextNotification();
824 ASSERT_TRUE(url_loader_client_.response_body().is_valid());
825
826 while (!defer) {
827 ASSERT_TRUE(handler_->OnWillRead(&io_buffer, &buf_size, -1));
828 ASSERT_TRUE(handler_->OnReadCompleted(buf_size, &defer));
829 }
830 handler_->set_begin_write_expectation(MOJO_RESULT_UNKNOWN);
831
832 while (!resource_controller_.is_cancel_with_error_called()) {
833 char buf[256];
834 uint32_t read = sizeof(buf);
835 MojoResult result = mojo::ReadDataRaw(url_loader_client_.response_body(),
836 buf, &read, MOJO_READ_DATA_FLAG_NONE);
837 ASSERT_TRUE(result == MOJO_RESULT_OK || result == MOJO_RESULT_SHOULD_WAIT);
838 base::RunLoop().RunUntilIdle();
839 }
840
841 EXPECT_FALSE(url_loader_client_.has_received_completion());
842 EXPECT_EQ(net::ERR_FAILED, resource_controller_.error());
843 EXPECT_EQ(0, resource_controller_.num_resume_calls());
844 }
845
846 INSTANTIATE_TEST_CASE_P(MojoAsyncResourceHandlerWithAllocationSizeTest,
847 MojoAsyncResourceHandlerWithAllocationSizeTest,
848 ::testing::Values(8, 32 * 2014));
849 } // namespace
850 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698