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

Side by Side Diff: content/browser/loader/detachable_resource_handler_unittest.cc

Issue 2668603003: Make ResourceHandler::OnWillRead able to complete asynchronously. (Closed)
Patch Set: One bot doesn't like 256 day timers. :( Created 3 years, 10 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 2017 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/detachable_resource_handler.h"
6
7 #include <string>
8
9 #include "base/logging.h"
10 #include "base/macros.h"
11 #include "base/memory/ptr_util.h"
12 #include "base/memory/weak_ptr.h"
13 #include "base/single_thread_task_runner.h"
14 #include "base/threading/thread_task_runner_handle.h"
15 #include "base/time/time.h"
16 #include "content/browser/loader/mock_resource_loader.h"
17 #include "content/browser/loader/resource_controller.h"
18 #include "content/browser/loader/test_resource_handler.h"
19 #include "content/public/browser/resource_request_info.h"
20 #include "content/public/common/resource_response.h"
21 #include "content/public/test/test_browser_thread_bundle.h"
22 #include "net/base/net_errors.h"
23 #include "net/url_request/redirect_info.h"
24 #include "net/url_request/url_request_context.h"
25 #include "net/url_request/url_request_status.h"
26 #include "net/url_request/url_request_test_util.h"
27 #include "testing/gtest/include/gtest/gtest.h"
28 #include "url/gurl.h"
29
30 namespace content {
31
32 namespace {
33
34 // Full response body.
35 const char kResponseBody[] = "Nifty response body.";
36 // Two separate reads allow for testing cancellation in the middle of one read,
37 // and between reads.
38 const char kFirstBodyRead[] = "Nifty";
39 const char kSecondBodyRead[] = " response body.";
40
41 enum class DetachPhase {
42 DETACHED_FROM_CREATION,
43 ON_WILL_START,
44 REQUEST_REDIRECTED,
45 ON_RESPONSE_STARTED,
46 FIRST_ON_WILL_READ,
47 FIRST_ON_READ_COMPLETED,
48 SECOND_ON_WILL_READ,
49 SECOND_ON_READ_COMPLETED,
50 ON_READ_EOF,
51 ON_RESPONSE_COMPLETED,
52 NEVER_DETACH,
53 };
54
55 class DetachableResourceHandlerTest
56 : public testing::TestWithParam<DetachPhase> {
Charlie Harrison 2017/02/16 21:25:04 Very clever
57 public:
58 DetachableResourceHandlerTest()
59 : request_(context_.CreateRequest(GURL("http://foo/"),
60 net::DEFAULT_PRIORITY,
61 nullptr)) {
62 ResourceRequestInfo::AllocateForTesting(request_.get(),
63 RESOURCE_TYPE_MAIN_FRAME,
64 nullptr, // context
65 0, // render_process_id
66 0, // render_view_id
67 0, // render_frame_id
68 true, // is_main_frame
69 false, // parent_is_main_frame
70 true, // allow_download
71 true, // is_async
72 PREVIEWS_OFF); // previews_state
73
74 std::unique_ptr<TestResourceHandler> test_handler;
75 if (GetParam() != DetachPhase::DETACHED_FROM_CREATION) {
76 test_handler = base::MakeUnique<TestResourceHandler>();
77 test_handler_ = test_handler->GetWeakPtr();
78 }
79 // TODO(mmenke): This file currently has no timeout tests. Should it?
Charlie Harrison 2017/02/16 21:25:04 You have a bunch of double spaces here and in a fe
mmenke 2017/03/08 19:16:07 It doesn't. And you're supposed to use double-spa
Charlie Harrison 2017/03/08 21:12:46 OK. It doesn't matter to me as long as it's consis
80 detachable_handler_ = base::MakeUnique<DetachableResourceHandler>(
81 request_.get(), base::TimeDelta::FromMinutes(30),
82 std::move(test_handler));
83 mock_loader_ =
84 base::MakeUnique<MockResourceLoader>(detachable_handler_.get());
85 }
86
87 protected:
88 TestBrowserThreadBundle thread_bundle_;
89 net::TestURLRequestContext context_;
90 std::unique_ptr<net::URLRequest> request_;
91
92 base::WeakPtr<TestResourceHandler> test_handler_;
93
94 std::unique_ptr<DetachableResourceHandler> detachable_handler_;
95 std::unique_ptr<MockResourceLoader> mock_loader_;
96 };
97
98 // Tests where ResourceHandler completes synchronously. Handler is detached
99 // just before the phase indicated by the DetachPhase parameter.
100 TEST_P(DetachableResourceHandlerTest, Sync) {
101 if (GetParam() == DetachPhase::ON_WILL_START) {
Charlie Harrison 2017/02/16 21:25:04 One way to condense these tests would be to do som
mmenke 2017/03/08 19:16:06 Done. Not sure it makes the tests any easier to r
Charlie Harrison 2017/03/08 21:12:45 Thanks. For me these tests are now much easier to
102 detachable_handler_->Detach();
103 ASSERT_FALSE(test_handler_);
104 }
105 ASSERT_EQ(MockResourceLoader::Status::IDLE,
106 mock_loader_->OnWillStart(request_->url()));
107 if (GetParam() > DetachPhase::ON_WILL_START) {
108 EXPECT_EQ(1, test_handler_->on_will_start_called());
109 EXPECT_EQ(0, test_handler_->on_request_redirected_called());
110 } else {
111 EXPECT_FALSE(test_handler_);
112 }
113
114 if (GetParam() == DetachPhase::REQUEST_REDIRECTED) {
115 detachable_handler_->Detach();
116 ASSERT_FALSE(test_handler_);
117 }
118 ASSERT_EQ(
119 MockResourceLoader::Status::IDLE,
120 mock_loader_->OnRequestRedirected(
121 net::RedirectInfo(), make_scoped_refptr(new ResourceResponse())));
122 if (GetParam() > DetachPhase::REQUEST_REDIRECTED) {
123 EXPECT_EQ(1, test_handler_->on_request_redirected_called());
124 EXPECT_EQ(0, test_handler_->on_response_started_called());
125 } else {
126 EXPECT_FALSE(test_handler_);
127 }
128
129 if (GetParam() == DetachPhase::ON_RESPONSE_STARTED) {
130 detachable_handler_->Detach();
131 ASSERT_FALSE(test_handler_);
132 }
133 ASSERT_EQ(MockResourceLoader::Status::IDLE,
134 mock_loader_->OnResponseStarted(
135 make_scoped_refptr(new ResourceResponse())));
136 if (GetParam() > DetachPhase::ON_RESPONSE_STARTED) {
137 EXPECT_EQ(1, test_handler_->on_request_redirected_called());
138 EXPECT_EQ(1, test_handler_->on_response_started_called());
139 EXPECT_EQ(0, test_handler_->on_will_read_called());
140 } else {
141 EXPECT_FALSE(test_handler_);
142 }
143
144 if (GetParam() == DetachPhase::FIRST_ON_WILL_READ) {
145 detachable_handler_->Detach();
146 ASSERT_FALSE(test_handler_);
147 }
148 ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
149 if (GetParam() > DetachPhase::FIRST_ON_WILL_READ) {
150 EXPECT_EQ(1, test_handler_->on_will_read_called());
151 EXPECT_EQ(0, test_handler_->on_read_completed_called());
152 } else {
153 EXPECT_FALSE(test_handler_);
154 }
155
156 if (GetParam() == DetachPhase::FIRST_ON_READ_COMPLETED) {
157 detachable_handler_->Detach();
158 ASSERT_FALSE(test_handler_);
159 }
160 ASSERT_EQ(MockResourceLoader::Status::IDLE,
161 mock_loader_->OnReadCompleted(kFirstBodyRead));
162 if (GetParam() > DetachPhase::FIRST_ON_READ_COMPLETED) {
163 EXPECT_EQ(1, test_handler_->on_read_completed_called());
164 EXPECT_EQ(kFirstBodyRead, test_handler_->body());
165 } else {
166 EXPECT_FALSE(test_handler_);
167 }
168
169 if (GetParam() == DetachPhase::SECOND_ON_WILL_READ) {
170 detachable_handler_->Detach();
171 ASSERT_FALSE(test_handler_);
172 }
173 ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
174 if (GetParam() > DetachPhase::SECOND_ON_WILL_READ) {
175 EXPECT_EQ(2, test_handler_->on_will_read_called());
176 EXPECT_EQ(1, test_handler_->on_read_completed_called());
177 } else {
178 EXPECT_FALSE(test_handler_);
179 }
180
181 if (GetParam() == DetachPhase::SECOND_ON_READ_COMPLETED) {
182 detachable_handler_->Detach();
183 ASSERT_FALSE(test_handler_);
184 }
185 ASSERT_EQ(MockResourceLoader::Status::IDLE,
186 mock_loader_->OnReadCompleted(kSecondBodyRead));
187 if (GetParam() > DetachPhase::SECOND_ON_READ_COMPLETED) {
188 EXPECT_EQ(2, test_handler_->on_will_read_called());
189 EXPECT_EQ(2, test_handler_->on_read_completed_called());
190 EXPECT_EQ(kResponseBody, test_handler_->body());
191 } else {
192 EXPECT_FALSE(test_handler_);
193 }
194
195 ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
196 if (GetParam() > DetachPhase::SECOND_ON_READ_COMPLETED) {
197 EXPECT_EQ(3, test_handler_->on_will_read_called());
198 EXPECT_EQ(2, test_handler_->on_read_completed_called());
199 EXPECT_EQ(0, test_handler_->on_response_completed_called());
200 } else {
201 EXPECT_FALSE(test_handler_);
202 }
203
204 if (GetParam() == DetachPhase::ON_READ_EOF) {
205 detachable_handler_->Detach();
206 ASSERT_FALSE(test_handler_);
207 }
208 ASSERT_EQ(MockResourceLoader::Status::IDLE,
209 mock_loader_->OnReadCompleted(""));
210 if (GetParam() > DetachPhase::ON_READ_EOF) {
211 EXPECT_EQ(3, test_handler_->on_read_completed_called());
212 EXPECT_EQ(1, test_handler_->on_read_eof_called());
213 EXPECT_EQ(0, test_handler_->on_response_completed_called());
214 } else {
215 EXPECT_FALSE(test_handler_);
216 }
217
218 if (GetParam() == DetachPhase::ON_RESPONSE_COMPLETED) {
219 detachable_handler_->Detach();
220 ASSERT_FALSE(test_handler_);
221 }
222 ASSERT_EQ(MockResourceLoader::Status::IDLE,
223 mock_loader_->OnResponseCompleted(
224 net::URLRequestStatus::FromError(net::OK)));
225 if (GetParam() > DetachPhase::ON_RESPONSE_COMPLETED) {
226 EXPECT_EQ(1, test_handler_->on_response_completed_called());
227 EXPECT_EQ(kResponseBody, test_handler_->body());
228 } else {
229 EXPECT_FALSE(test_handler_);
230 }
231 }
232
233 // Tests where ResourceHandler completes asynchronously. Handler is detached
234 // during the phase indicated by the DetachPhase parameter. Async casees where
Charlie Harrison 2017/02/16 21:25:04 s/casees/cases
mmenke 2017/03/08 19:16:07 Done.
235 // the handler is detached between phases are similar enough to the sync tests
236 // that they wouldn't provide meaningfully better test coverage.
237 //
238 // Before the handler is detached, all calls complete asynchronously.
239 // Afterwards, they all complete synchronously.
240 TEST_P(DetachableResourceHandlerTest, Async) {
241 if (GetParam() != DetachPhase::DETACHED_FROM_CREATION) {
242 test_handler_->set_defer_on_will_start(true);
243 test_handler_->set_defer_on_request_redirected(true);
244 test_handler_->set_defer_on_response_started(true);
245 test_handler_->set_defer_on_will_read(true);
246 test_handler_->set_defer_on_read_completed(true);
247 test_handler_->set_defer_on_read_eof(true);
248 // Note: Can't set |defer_on_response_completed|, since the
249 // DetachableResourceHandler DCHECKs when the next handler tried to defer
250 // the ERR_ABORTED message it sends downstream.
251 }
252
253 if (GetParam() < DetachPhase::ON_WILL_START) {
254 ASSERT_EQ(MockResourceLoader::Status::IDLE,
255 mock_loader_->OnWillStart(request_->url()));
256 } else {
257 ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
258 mock_loader_->OnWillStart(request_->url()));
259 EXPECT_EQ(1, test_handler_->on_will_start_called());
260 EXPECT_EQ(0, test_handler_->on_request_redirected_called());
261 if (GetParam() == DetachPhase::ON_WILL_START) {
262 detachable_handler_->Detach();
263 ASSERT_FALSE(test_handler_);
264 } else {
265 test_handler_->Resume();
266 }
267 }
268 ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->status());
269
270 if (GetParam() < DetachPhase::REQUEST_REDIRECTED) {
Charlie Harrison 2017/02/16 21:25:04 I don't think we could use the helper methods I de
mmenke 2017/03/08 19:16:07 Done.
271 EXPECT_FALSE(test_handler_);
272 ASSERT_EQ(
273 MockResourceLoader::Status::IDLE,
274 mock_loader_->OnRequestRedirected(
275 net::RedirectInfo(), make_scoped_refptr(new ResourceResponse())));
276 } else {
277 ASSERT_EQ(
278 MockResourceLoader::Status::CALLBACK_PENDING,
279 mock_loader_->OnRequestRedirected(
280 net::RedirectInfo(), make_scoped_refptr(new ResourceResponse())));
281 EXPECT_EQ(1, test_handler_->on_request_redirected_called());
282 EXPECT_EQ(0, test_handler_->on_response_started_called());
283 if (GetParam() == DetachPhase::REQUEST_REDIRECTED) {
284 detachable_handler_->Detach();
285 ASSERT_FALSE(test_handler_);
286 } else {
287 test_handler_->Resume();
288 }
289 }
290 ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->status());
291
292 if (GetParam() < DetachPhase::ON_RESPONSE_STARTED) {
293 EXPECT_FALSE(test_handler_);
294 ASSERT_EQ(MockResourceLoader::Status::IDLE,
295 mock_loader_->OnResponseStarted(
296 make_scoped_refptr(new ResourceResponse())));
297 } else {
298 ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
299 mock_loader_->OnResponseStarted(
300 make_scoped_refptr(new ResourceResponse())));
301 EXPECT_EQ(1, test_handler_->on_request_redirected_called());
302 EXPECT_EQ(1, test_handler_->on_response_started_called());
303 EXPECT_EQ(0, test_handler_->on_will_read_called());
304 if (GetParam() == DetachPhase::ON_RESPONSE_STARTED) {
305 detachable_handler_->Detach();
306 ASSERT_FALSE(test_handler_);
307 } else {
308 test_handler_->Resume();
309 }
310 }
311 ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->status());
312
313 if (GetParam() < DetachPhase::FIRST_ON_WILL_READ) {
314 EXPECT_FALSE(test_handler_);
315 ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
316 } else {
317 ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
318 mock_loader_->OnWillRead());
319 EXPECT_EQ(1, test_handler_->on_will_read_called());
320 EXPECT_EQ(0, test_handler_->on_read_completed_called());
321 if (GetParam() == DetachPhase::FIRST_ON_WILL_READ) {
322 detachable_handler_->Detach();
323 ASSERT_FALSE(test_handler_);
324 } else {
325 test_handler_->Resume();
326 }
327 }
328 ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->status());
329
330 if (GetParam() < DetachPhase::FIRST_ON_READ_COMPLETED) {
331 EXPECT_FALSE(test_handler_);
332 ASSERT_EQ(MockResourceLoader::Status::IDLE,
333 mock_loader_->OnReadCompleted(kFirstBodyRead));
334 } else {
335 ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
336 mock_loader_->OnReadCompleted(kFirstBodyRead));
337 EXPECT_EQ(1, test_handler_->on_read_completed_called());
338 EXPECT_EQ(kFirstBodyRead, test_handler_->body());
339 if (GetParam() == DetachPhase::FIRST_ON_READ_COMPLETED) {
340 detachable_handler_->Detach();
341 ASSERT_FALSE(test_handler_);
342 } else {
343 test_handler_->Resume();
344 }
345 }
346 ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->status());
347
348 if (GetParam() < DetachPhase::SECOND_ON_WILL_READ) {
349 EXPECT_FALSE(test_handler_);
350 ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
351 } else {
352 test_handler_->set_defer_on_will_read(true);
353 ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
354 mock_loader_->OnWillRead());
355 EXPECT_EQ(2, test_handler_->on_will_read_called());
356 EXPECT_EQ(1, test_handler_->on_read_completed_called());
357 if (GetParam() == DetachPhase::SECOND_ON_WILL_READ) {
358 detachable_handler_->Detach();
359 ASSERT_FALSE(test_handler_);
360 } else {
361 test_handler_->Resume();
362 }
363 }
364 ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->status());
365
366 if (GetParam() < DetachPhase::SECOND_ON_READ_COMPLETED) {
367 EXPECT_FALSE(test_handler_);
368 ASSERT_EQ(MockResourceLoader::Status::IDLE,
369 mock_loader_->OnReadCompleted(kSecondBodyRead));
370 } else {
371 test_handler_->set_defer_on_read_completed(true);
372 ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
373 mock_loader_->OnReadCompleted(kSecondBodyRead));
374 EXPECT_EQ(2, test_handler_->on_will_read_called());
375 EXPECT_EQ(2, test_handler_->on_read_completed_called());
376 EXPECT_EQ(kResponseBody, test_handler_->body());
377 if (GetParam() == DetachPhase::SECOND_ON_READ_COMPLETED) {
378 detachable_handler_->Detach();
379 ASSERT_FALSE(test_handler_);
380 } else {
381 test_handler_->Resume();
382 }
383 }
384 ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->status());
385
386 // Test doesn't check detaching on thie third OnWillRead call.
Charlie Harrison 2017/02/16 21:25:04 s/thie/the
mmenke 2017/03/08 19:16:07 Done.
387 ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
388 if (GetParam() > DetachPhase::SECOND_ON_READ_COMPLETED) {
389 EXPECT_EQ(3, test_handler_->on_will_read_called());
390 EXPECT_EQ(2, test_handler_->on_read_completed_called());
391 EXPECT_EQ(0, test_handler_->on_response_completed_called());
392 } else {
393 EXPECT_FALSE(test_handler_);
394 }
395
396 if (GetParam() < DetachPhase::ON_READ_EOF) {
397 EXPECT_FALSE(test_handler_);
398 ASSERT_EQ(MockResourceLoader::Status::IDLE,
399 mock_loader_->OnReadCompleted(""));
400 } else {
401 test_handler_->set_defer_on_read_completed(true);
402 ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
403 mock_loader_->OnReadCompleted(""));
404 EXPECT_EQ(3, test_handler_->on_read_completed_called());
405 EXPECT_EQ(1, test_handler_->on_read_eof_called());
406 EXPECT_EQ(0, test_handler_->on_response_completed_called());
407 if (GetParam() == DetachPhase::ON_READ_EOF) {
408 detachable_handler_->Detach();
409 ASSERT_FALSE(test_handler_);
410 } else {
411 test_handler_->Resume();
412 }
413 }
414 ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->status());
415
416 if (GetParam() < DetachPhase::ON_RESPONSE_COMPLETED) {
417 EXPECT_FALSE(test_handler_);
418 ASSERT_EQ(MockResourceLoader::Status::IDLE,
419 mock_loader_->OnResponseCompleted(
420 net::URLRequestStatus::FromError(net::OK)));
421 } else {
422 test_handler_->set_defer_on_response_completed(true);
423 ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
424 mock_loader_->OnResponseCompleted(
425 net::URLRequestStatus::FromError(net::OK)));
426 EXPECT_EQ(1, test_handler_->on_response_completed_called());
427 EXPECT_EQ(kResponseBody, test_handler_->body());
428 if (GetParam() == DetachPhase::ON_RESPONSE_COMPLETED) {
429 detachable_handler_->Detach();
430 ASSERT_FALSE(test_handler_);
431 } else {
432 test_handler_->Resume();
433 }
434 }
435 ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->status());
436 }
437
438 INSTANTIATE_TEST_CASE_P(/* No prefix needed*/,
439 DetachableResourceHandlerTest,
440 testing::Values(DetachPhase::DETACHED_FROM_CREATION,
441 DetachPhase::ON_WILL_START,
442 DetachPhase::REQUEST_REDIRECTED,
443 DetachPhase::ON_RESPONSE_STARTED,
444 DetachPhase::FIRST_ON_WILL_READ,
445 DetachPhase::FIRST_ON_READ_COMPLETED,
446 DetachPhase::SECOND_ON_WILL_READ,
447 DetachPhase::SECOND_ON_READ_COMPLETED,
448 DetachPhase::ON_READ_EOF,
449 DetachPhase::ON_RESPONSE_COMPLETED,
450 DetachPhase::NEVER_DETACH));
451
452 } // namespace
453
454 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698