1 // Copyright (c) 2012 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.
7 #include "base/memory/ref_counted.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/memory/scoped_vector.h"
10 #include "base/strings/stringprintf.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "net/base/address_list.h"
13 #include "net/base/io_buffer.h"
14 #include "net/base/net_errors.h"
15 #include "net/base/net_util.h"
16 #include "net/base/request_priority.h"
17 #include "net/dns/host_cache.h"
18 #include "net/dns/mock_host_resolver.h"
19 #include "net/http/http_auth_handler_mock.h"
20 #include "net/http/http_network_session.h"
21 #include "net/http/http_network_transaction.h"
22 #include "net/http/http_request_info.h"
23 #include "net/http/http_server_properties_impl.h"
24 #include "net/proxy/proxy_config_service.h"
25 #include "net/proxy/proxy_service.h"
26 #include "net/socket/client_socket_handle.h"
27 #include "net/socket/client_socket_pool_histograms.h"
28 #include "net/socket/client_socket_pool_manager.h"
29 #include "net/socket/socket_test_util.h"
30 #include "net/ssl/ssl_config_service_defaults.h"
31 #include "testing/gmock/include/gmock/gmock.h"
32 #include "testing/gtest/include/gtest/gtest.h"
40 class SimpleProxyConfigService
: public ProxyConfigService
{
42 virtual void AddObserver(Observer
* observer
) OVERRIDE
{
46 virtual void RemoveObserver(Observer
* observer
) OVERRIDE
{
47 if (observer_
== observer
) {
52 virtual ConfigAvailability
GetLatestProxyConfig(
53 ProxyConfig
* config
) OVERRIDE
{
58 void IncrementConfigId() {
59 config_
.set_id(config_
.id() + 1);
60 observer_
->OnProxyConfigChanged(config_
, ProxyConfigService::CONFIG_VALID
);
68 class HttpPipelinedNetworkTransactionTest
: public testing::Test
{
70 HttpPipelinedNetworkTransactionTest()
72 pool_(1, 1, &histograms_
, &factory_
) {
75 void Initialize(bool force_http_pipelining
) {
76 // Normally, this code could just go in SetUp(). For a few of these tests,
77 // we change the default number of sockets per group. That needs to be done
78 // before we construct the HttpNetworkSession.
79 proxy_config_service_
= new SimpleProxyConfigService();
80 proxy_service_
.reset(new ProxyService(proxy_config_service_
, NULL
, NULL
));
81 ssl_config_
= new SSLConfigServiceDefaults
;
82 auth_handler_factory_
.reset(new HttpAuthHandlerMock::Factory());
84 HttpNetworkSession::Params session_params
;
85 session_params
.client_socket_factory
= &factory_
;
86 session_params
.proxy_service
= proxy_service_
.get();
87 session_params
.host_resolver
= &mock_resolver_
;
88 session_params
.ssl_config_service
= ssl_config_
.get();
89 session_params
.http_auth_handler_factory
= auth_handler_factory_
.get();
90 session_params
.http_server_properties
= &http_server_properties_
;
91 session_params
.force_http_pipelining
= force_http_pipelining
;
92 session_params
.http_pipelining_enabled
= true;
93 session_
= new HttpNetworkSession(session_params
);
96 void AddExpectedConnection(MockRead
* reads
, size_t reads_count
,
97 MockWrite
* writes
, size_t writes_count
) {
98 DeterministicSocketData
* data
= new DeterministicSocketData(
99 reads
, reads_count
, writes
, writes_count
);
100 data
->set_connect_data(MockConnect(SYNCHRONOUS
, OK
));
101 if (reads_count
|| writes_count
) {
102 data
->StopAfter(reads_count
+ writes_count
);
104 factory_
.AddSocketDataProvider(data
);
105 data_vector_
.push_back(data
);
108 enum RequestInfoOptions
{
110 REQUEST_MAIN_RESOURCE
,
113 HttpRequestInfo
* GetRequestInfo(
114 const char* filename
, RequestInfoOptions options
= REQUEST_DEFAULT
) {
115 std::string url
= base::StringPrintf("http://localhost/%s", filename
);
116 HttpRequestInfo
* request_info
= new HttpRequestInfo
;
117 request_info
->url
= GURL(url
);
118 request_info
->method
= "GET";
119 if (options
== REQUEST_MAIN_RESOURCE
) {
120 request_info
->load_flags
= LOAD_MAIN_FRAME
;
122 request_info_vector_
.push_back(request_info
);
126 void ExpectResponse(const std::string
& expected
,
127 HttpNetworkTransaction
& transaction
,
129 scoped_refptr
<IOBuffer
> buffer(new IOBuffer(expected
.size()));
130 if (io_mode
== ASYNC
) {
131 EXPECT_EQ(ERR_IO_PENDING
, transaction
.Read(buffer
.get(), expected
.size(),
132 callback_
.callback()));
133 data_vector_
[0]->RunFor(1);
134 EXPECT_EQ(static_cast<int>(expected
.length()), callback_
.WaitForResult());
136 EXPECT_EQ(static_cast<int>(expected
.size()),
137 transaction
.Read(buffer
.get(), expected
.size(),
138 callback_
.callback()));
140 std::string
actual(buffer
->data(), expected
.size());
141 EXPECT_THAT(actual
, StrEq(expected
));
142 EXPECT_EQ(OK
, transaction
.Read(buffer
.get(), expected
.size(),
143 callback_
.callback()));
146 void CompleteTwoRequests(int data_index
, int stop_at_step
) {
147 scoped_ptr
<HttpNetworkTransaction
> one_transaction(
148 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session_
.get()));
149 TestCompletionCallback one_callback
;
150 EXPECT_EQ(ERR_IO_PENDING
,
151 one_transaction
->Start(GetRequestInfo("one.html"),
152 one_callback
.callback(), BoundNetLog()));
153 EXPECT_EQ(OK
, one_callback
.WaitForResult());
155 HttpNetworkTransaction
two_transaction(DEFAULT_PRIORITY
, session_
.get());
156 TestCompletionCallback two_callback
;
157 EXPECT_EQ(ERR_IO_PENDING
,
158 two_transaction
.Start(GetRequestInfo("two.html"),
159 two_callback
.callback(), BoundNetLog()));
161 TestCompletionCallback one_read_callback
;
162 scoped_refptr
<IOBuffer
> buffer(new IOBuffer(8));
163 EXPECT_EQ(ERR_IO_PENDING
,
164 one_transaction
->Read(buffer
.get(), 8,
165 one_read_callback
.callback()));
167 data_vector_
[data_index
]->SetStop(stop_at_step
);
168 data_vector_
[data_index
]->Run();
169 EXPECT_EQ(8, one_read_callback
.WaitForResult());
170 data_vector_
[data_index
]->SetStop(10);
171 std::string
actual(buffer
->data(), 8);
172 EXPECT_THAT(actual
, StrEq("one.html"));
173 EXPECT_EQ(OK
, one_transaction
->Read(buffer
.get(), 8,
174 one_read_callback
.callback()));
176 EXPECT_EQ(OK
, two_callback
.WaitForResult());
177 ExpectResponse("two.html", two_transaction
, SYNCHRONOUS
);
180 void CompleteFourRequests(RequestInfoOptions options
) {
181 scoped_ptr
<HttpNetworkTransaction
> one_transaction(
182 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session_
.get()));
183 TestCompletionCallback one_callback
;
184 EXPECT_EQ(ERR_IO_PENDING
,
185 one_transaction
->Start(GetRequestInfo("one.html", options
),
186 one_callback
.callback(), BoundNetLog()));
187 EXPECT_EQ(OK
, one_callback
.WaitForResult());
189 HttpNetworkTransaction
two_transaction(DEFAULT_PRIORITY
, session_
.get());
190 TestCompletionCallback two_callback
;
191 EXPECT_EQ(ERR_IO_PENDING
,
192 two_transaction
.Start(GetRequestInfo("two.html", options
),
193 two_callback
.callback(), BoundNetLog()));
195 HttpNetworkTransaction
three_transaction(DEFAULT_PRIORITY
, session_
.get());
196 TestCompletionCallback three_callback
;
197 EXPECT_EQ(ERR_IO_PENDING
,
198 three_transaction
.Start(GetRequestInfo("three.html", options
),
199 three_callback
.callback(),
202 HttpNetworkTransaction
four_transaction(DEFAULT_PRIORITY
, session_
.get());
203 TestCompletionCallback four_callback
;
204 EXPECT_EQ(ERR_IO_PENDING
,
205 four_transaction
.Start(GetRequestInfo("four.html", options
),
206 four_callback
.callback(), BoundNetLog()));
208 ExpectResponse("one.html", *one_transaction
.get(), SYNCHRONOUS
);
209 EXPECT_EQ(OK
, two_callback
.WaitForResult());
210 ExpectResponse("two.html", two_transaction
, SYNCHRONOUS
);
211 EXPECT_EQ(OK
, three_callback
.WaitForResult());
212 ExpectResponse("three.html", three_transaction
, SYNCHRONOUS
);
214 one_transaction
.reset();
215 EXPECT_EQ(OK
, four_callback
.WaitForResult());
216 ExpectResponse("four.html", four_transaction
, SYNCHRONOUS
);
219 DeterministicMockClientSocketFactory factory_
;
220 ClientSocketPoolHistograms histograms_
;
221 MockTransportClientSocketPool pool_
;
222 ScopedVector
<DeterministicSocketData
> data_vector_
;
223 TestCompletionCallback callback_
;
224 ScopedVector
<HttpRequestInfo
> request_info_vector_
;
226 SimpleProxyConfigService
* proxy_config_service_
;
227 scoped_ptr
<ProxyService
> proxy_service_
;
228 MockHostResolver mock_resolver_
;
229 scoped_refptr
<SSLConfigService
> ssl_config_
;
230 scoped_ptr
<HttpAuthHandlerMock::Factory
> auth_handler_factory_
;
231 HttpServerPropertiesImpl http_server_properties_
;
232 scoped_refptr
<HttpNetworkSession
> session_
;
235 TEST_F(HttpPipelinedNetworkTransactionTest
, OneRequest
) {
238 MockWrite writes
[] = {
239 MockWrite(SYNCHRONOUS
, 0, "GET /test.html HTTP/1.1\r\n"
240 "Host: localhost\r\n"
241 "Connection: keep-alive\r\n\r\n"),
244 MockRead(SYNCHRONOUS
, 1, "HTTP/1.1 200 OK\r\n"),
245 MockRead(SYNCHRONOUS
, 2, "Content-Length: 9\r\n\r\n"),
246 MockRead(SYNCHRONOUS
, 3, "test.html"),
248 AddExpectedConnection(reads
, arraysize(reads
), writes
, arraysize(writes
));
250 HttpNetworkTransaction
transaction(DEFAULT_PRIORITY
, session_
.get());
251 EXPECT_EQ(ERR_IO_PENDING
,
252 transaction
.Start(GetRequestInfo("test.html"), callback_
.callback(),
254 EXPECT_EQ(OK
, callback_
.WaitForResult());
255 ExpectResponse("test.html", transaction
, SYNCHRONOUS
);
258 TEST_F(HttpPipelinedNetworkTransactionTest
, ReusePipeline
) {
261 MockWrite writes
[] = {
262 MockWrite(SYNCHRONOUS
, 0, "GET /one.html HTTP/1.1\r\n"
263 "Host: localhost\r\n"
264 "Connection: keep-alive\r\n\r\n"),
265 MockWrite(SYNCHRONOUS
, 3, "GET /two.html HTTP/1.1\r\n"
266 "Host: localhost\r\n"
267 "Connection: keep-alive\r\n\r\n"),
270 MockRead(SYNCHRONOUS
, 1, "HTTP/1.1 200 OK\r\n"),
271 MockRead(SYNCHRONOUS
, 2, "Content-Length: 8\r\n\r\n"),
272 MockRead(ASYNC
, 4, "one.html"),
273 MockRead(SYNCHRONOUS
, 5, "HTTP/1.1 200 OK\r\n"),
274 MockRead(SYNCHRONOUS
, 6, "Content-Length: 8\r\n\r\n"),
275 MockRead(SYNCHRONOUS
, 7, "two.html"),
277 AddExpectedConnection(reads
, arraysize(reads
), writes
, arraysize(writes
));
279 CompleteTwoRequests(0, 5);
282 TEST_F(HttpPipelinedNetworkTransactionTest
, ReusesOnSpaceAvailable
) {
283 int old_max_sockets
= ClientSocketPoolManager::max_sockets_per_group(
284 HttpNetworkSession::NORMAL_SOCKET_POOL
);
285 ClientSocketPoolManager::set_max_sockets_per_group(
286 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
289 MockWrite writes
[] = {
290 MockWrite(SYNCHRONOUS
, 0, "GET /one.html HTTP/1.1\r\n"
291 "Host: localhost\r\n"
292 "Connection: keep-alive\r\n\r\n"),
293 MockWrite(SYNCHRONOUS
, 4, "GET /two.html HTTP/1.1\r\n"
294 "Host: localhost\r\n"
295 "Connection: keep-alive\r\n\r\n"),
296 MockWrite(SYNCHRONOUS
, 7, "GET /three.html HTTP/1.1\r\n"
297 "Host: localhost\r\n"
298 "Connection: keep-alive\r\n\r\n"),
299 MockWrite(SYNCHRONOUS
, 12, "GET /four.html HTTP/1.1\r\n"
300 "Host: localhost\r\n"
301 "Connection: keep-alive\r\n\r\n"),
304 MockRead(SYNCHRONOUS
, 1, "HTTP/1.1 200 OK\r\n"),
305 MockRead(SYNCHRONOUS
, 2, "Content-Length: 8\r\n\r\n"),
306 MockRead(SYNCHRONOUS
, 3, "one.html"),
307 MockRead(SYNCHRONOUS
, 5, "HTTP/1.1 200 OK\r\n"),
308 MockRead(SYNCHRONOUS
, 6, "Content-Length: 8\r\n\r\n"),
309 MockRead(SYNCHRONOUS
, 8, "two.html"),
310 MockRead(SYNCHRONOUS
, 9, "HTTP/1.1 200 OK\r\n"),
311 MockRead(SYNCHRONOUS
, 10, "Content-Length: 10\r\n\r\n"),
312 MockRead(SYNCHRONOUS
, 11, "three.html"),
313 MockRead(SYNCHRONOUS
, 13, "HTTP/1.1 200 OK\r\n"),
314 MockRead(SYNCHRONOUS
, 14, "Content-Length: 9\r\n\r\n"),
315 MockRead(SYNCHRONOUS
, 15, "four.html"),
317 AddExpectedConnection(reads
, arraysize(reads
), writes
, arraysize(writes
));
319 CompleteFourRequests(REQUEST_DEFAULT
);
321 ClientSocketPoolManager::set_max_sockets_per_group(
322 HttpNetworkSession::NORMAL_SOCKET_POOL
, old_max_sockets
);
325 TEST_F(HttpPipelinedNetworkTransactionTest
, WontPipelineMainResource
) {
326 int old_max_sockets
= ClientSocketPoolManager::max_sockets_per_group(
327 HttpNetworkSession::NORMAL_SOCKET_POOL
);
328 ClientSocketPoolManager::set_max_sockets_per_group(
329 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
332 MockWrite writes
[] = {
333 MockWrite(SYNCHRONOUS
, 0, "GET /one.html HTTP/1.1\r\n"
334 "Host: localhost\r\n"
335 "Connection: keep-alive\r\n\r\n"),
336 MockWrite(SYNCHRONOUS
, 4, "GET /two.html HTTP/1.1\r\n"
337 "Host: localhost\r\n"
338 "Connection: keep-alive\r\n\r\n"),
339 MockWrite(SYNCHRONOUS
, 8, "GET /three.html HTTP/1.1\r\n"
340 "Host: localhost\r\n"
341 "Connection: keep-alive\r\n\r\n"),
342 MockWrite(SYNCHRONOUS
, 12, "GET /four.html HTTP/1.1\r\n"
343 "Host: localhost\r\n"
344 "Connection: keep-alive\r\n\r\n"),
347 MockRead(SYNCHRONOUS
, 1, "HTTP/1.1 200 OK\r\n"),
348 MockRead(SYNCHRONOUS
, 2, "Content-Length: 8\r\n\r\n"),
349 MockRead(SYNCHRONOUS
, 3, "one.html"),
350 MockRead(SYNCHRONOUS
, 5, "HTTP/1.1 200 OK\r\n"),
351 MockRead(SYNCHRONOUS
, 6, "Content-Length: 8\r\n\r\n"),
352 MockRead(SYNCHRONOUS
, 7, "two.html"),
353 MockRead(SYNCHRONOUS
, 9, "HTTP/1.1 200 OK\r\n"),
354 MockRead(SYNCHRONOUS
, 10, "Content-Length: 10\r\n\r\n"),
355 MockRead(SYNCHRONOUS
, 11, "three.html"),
356 MockRead(SYNCHRONOUS
, 13, "HTTP/1.1 200 OK\r\n"),
357 MockRead(SYNCHRONOUS
, 14, "Content-Length: 9\r\n\r\n"),
358 MockRead(SYNCHRONOUS
, 15, "four.html"),
360 AddExpectedConnection(reads
, arraysize(reads
), writes
, arraysize(writes
));
362 CompleteFourRequests(REQUEST_MAIN_RESOURCE
);
364 ClientSocketPoolManager::set_max_sockets_per_group(
365 HttpNetworkSession::NORMAL_SOCKET_POOL
, old_max_sockets
);
368 TEST_F(HttpPipelinedNetworkTransactionTest
, UnknownSizeEvictsToNewPipeline
) {
371 MockWrite writes
[] = {
372 MockWrite(SYNCHRONOUS
, 0, "GET /one.html HTTP/1.1\r\n"
373 "Host: localhost\r\n"
374 "Connection: keep-alive\r\n\r\n"),
377 MockRead(SYNCHRONOUS
, 1, "HTTP/1.1 200 OK\r\n\r\n"),
378 MockRead(ASYNC
, 2, "one.html"),
379 MockRead(SYNCHRONOUS
, OK
, 3),
381 AddExpectedConnection(reads
, arraysize(reads
), writes
, arraysize(writes
));
383 MockWrite writes2
[] = {
384 MockWrite(SYNCHRONOUS
, 0, "GET /two.html HTTP/1.1\r\n"
385 "Host: localhost\r\n"
386 "Connection: keep-alive\r\n\r\n"),
388 MockRead reads2
[] = {
389 MockRead(SYNCHRONOUS
, 1, "HTTP/1.1 200 OK\r\n"),
390 MockRead(SYNCHRONOUS
, 2, "Content-Length: 8\r\n\r\n"),
391 MockRead(SYNCHRONOUS
, 3, "two.html"),
393 AddExpectedConnection(reads2
, arraysize(reads2
), writes2
, arraysize(writes2
));
395 CompleteTwoRequests(0, 3);
398 TEST_F(HttpPipelinedNetworkTransactionTest
, ConnectionCloseEvictToNewPipeline
) {
401 MockWrite writes
[] = {
402 MockWrite(SYNCHRONOUS
, 0, "GET /one.html HTTP/1.1\r\n"
403 "Host: localhost\r\n"
404 "Connection: keep-alive\r\n\r\n"),
405 MockWrite(SYNCHRONOUS
, 3, "GET /two.html HTTP/1.1\r\n"
406 "Host: localhost\r\n"
407 "Connection: keep-alive\r\n\r\n"),
410 MockRead(SYNCHRONOUS
, 1, "HTTP/1.1 200 OK\r\n"),
411 MockRead(SYNCHRONOUS
, 2, "Content-Length: 8\r\n\r\n"),
412 MockRead(ASYNC
, 4, "one.html"),
413 MockRead(SYNCHRONOUS
, ERR_SOCKET_NOT_CONNECTED
, 5),
415 AddExpectedConnection(reads
, arraysize(reads
), writes
, arraysize(writes
));
417 MockWrite writes2
[] = {
418 MockWrite(SYNCHRONOUS
, 0, "GET /two.html HTTP/1.1\r\n"
419 "Host: localhost\r\n"
420 "Connection: keep-alive\r\n\r\n"),
422 MockRead reads2
[] = {
423 MockRead(SYNCHRONOUS
, 1, "HTTP/1.1 200 OK\r\n"),
424 MockRead(SYNCHRONOUS
, 2, "Content-Length: 8\r\n\r\n"),
425 MockRead(SYNCHRONOUS
, 3, "two.html"),
427 AddExpectedConnection(reads2
, arraysize(reads2
), writes2
, arraysize(writes2
));
429 CompleteTwoRequests(0, 5);
432 TEST_F(HttpPipelinedNetworkTransactionTest
, ErrorEvictsToNewPipeline
) {
435 MockWrite writes
[] = {
436 MockWrite(SYNCHRONOUS
, 0, "GET /one.html HTTP/1.1\r\n"
437 "Host: localhost\r\n"
438 "Connection: keep-alive\r\n\r\n"),
439 MockWrite(SYNCHRONOUS
, 3, "GET /two.html HTTP/1.1\r\n"
440 "Host: localhost\r\n"
441 "Connection: keep-alive\r\n\r\n"),
444 MockRead(SYNCHRONOUS
, 1, "HTTP/1.1 200 OK\r\n\r\n"),
445 MockRead(SYNCHRONOUS
, ERR_FAILED
, 2),
447 AddExpectedConnection(reads
, arraysize(reads
), writes
, arraysize(writes
));
449 MockWrite writes2
[] = {
450 MockWrite(SYNCHRONOUS
, 0, "GET /two.html HTTP/1.1\r\n"
451 "Host: localhost\r\n"
452 "Connection: keep-alive\r\n\r\n"),
454 MockRead reads2
[] = {
455 MockRead(SYNCHRONOUS
, 1, "HTTP/1.1 200 OK\r\n"),
456 MockRead(SYNCHRONOUS
, 2, "Content-Length: 8\r\n\r\n"),
457 MockRead(SYNCHRONOUS
, 3, "two.html"),
459 AddExpectedConnection(reads2
, arraysize(reads2
), writes2
, arraysize(writes2
));
461 HttpNetworkTransaction
one_transaction(DEFAULT_PRIORITY
, session_
.get());
462 TestCompletionCallback one_callback
;
463 EXPECT_EQ(ERR_IO_PENDING
,
464 one_transaction
.Start(GetRequestInfo("one.html"),
465 one_callback
.callback(), BoundNetLog()));
466 EXPECT_EQ(OK
, one_callback
.WaitForResult());
468 HttpNetworkTransaction
two_transaction(DEFAULT_PRIORITY
, session_
.get());
469 TestCompletionCallback two_callback
;
470 EXPECT_EQ(ERR_IO_PENDING
,
471 two_transaction
.Start(GetRequestInfo("two.html"),
472 two_callback
.callback(), BoundNetLog()));
474 scoped_refptr
<IOBuffer
> buffer(new IOBuffer(1));
475 EXPECT_EQ(ERR_FAILED
,
476 one_transaction
.Read(buffer
.get(), 1, callback_
.callback()));
477 EXPECT_EQ(OK
, two_callback
.WaitForResult());
478 ExpectResponse("two.html", two_transaction
, SYNCHRONOUS
);
481 TEST_F(HttpPipelinedNetworkTransactionTest
, SendErrorEvictsToNewPipeline
) {
484 MockWrite writes
[] = {
485 MockWrite(ASYNC
, ERR_FAILED
, 0),
487 AddExpectedConnection(NULL
, 0, writes
, arraysize(writes
));
489 MockWrite writes2
[] = {
490 MockWrite(SYNCHRONOUS
, 0, "GET /two.html HTTP/1.1\r\n"
491 "Host: localhost\r\n"
492 "Connection: keep-alive\r\n\r\n"),
494 MockRead reads2
[] = {
495 MockRead(SYNCHRONOUS
, 1, "HTTP/1.1 200 OK\r\n"),
496 MockRead(SYNCHRONOUS
, 2, "Content-Length: 8\r\n\r\n"),
497 MockRead(SYNCHRONOUS
, 3, "two.html"),
499 AddExpectedConnection(reads2
, arraysize(reads2
), writes2
, arraysize(writes2
));
501 HttpNetworkTransaction
one_transaction(DEFAULT_PRIORITY
, session_
.get());
502 TestCompletionCallback one_callback
;
503 EXPECT_EQ(ERR_IO_PENDING
,
504 one_transaction
.Start(GetRequestInfo("one.html"),
505 one_callback
.callback(), BoundNetLog()));
507 HttpNetworkTransaction
two_transaction(DEFAULT_PRIORITY
, session_
.get());
508 TestCompletionCallback two_callback
;
509 EXPECT_EQ(ERR_IO_PENDING
,
510 two_transaction
.Start(GetRequestInfo("two.html"),
511 two_callback
.callback(), BoundNetLog()));
513 data_vector_
[0]->RunFor(1);
514 EXPECT_EQ(ERR_FAILED
, one_callback
.WaitForResult());
516 EXPECT_EQ(OK
, two_callback
.WaitForResult());
517 ExpectResponse("two.html", two_transaction
, SYNCHRONOUS
);
520 TEST_F(HttpPipelinedNetworkTransactionTest
, RedirectDrained
) {
523 MockWrite writes
[] = {
524 MockWrite(SYNCHRONOUS
, 0, "GET /redirect.html HTTP/1.1\r\n"
525 "Host: localhost\r\n"
526 "Connection: keep-alive\r\n\r\n"),
527 MockWrite(SYNCHRONOUS
, 3, "GET /two.html HTTP/1.1\r\n"
528 "Host: localhost\r\n"
529 "Connection: keep-alive\r\n\r\n"),
532 MockRead(SYNCHRONOUS
, 1, "HTTP/1.1 302 OK\r\n"),
533 MockRead(SYNCHRONOUS
, 2, "Content-Length: 8\r\n\r\n"),
534 MockRead(ASYNC
, 4, "redirect"),
535 MockRead(SYNCHRONOUS
, 5, "HTTP/1.1 200 OK\r\n"),
536 MockRead(SYNCHRONOUS
, 6, "Content-Length: 8\r\n\r\n"),
537 MockRead(SYNCHRONOUS
, 7, "two.html"),
539 AddExpectedConnection(reads
, arraysize(reads
), writes
, arraysize(writes
));
541 scoped_ptr
<HttpNetworkTransaction
> one_transaction(
542 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session_
.get()));
543 TestCompletionCallback one_callback
;
544 EXPECT_EQ(ERR_IO_PENDING
,
545 one_transaction
->Start(GetRequestInfo("redirect.html"),
546 one_callback
.callback(), BoundNetLog()));
547 EXPECT_EQ(OK
, one_callback
.WaitForResult());
549 HttpNetworkTransaction
two_transaction(DEFAULT_PRIORITY
, session_
.get());
550 TestCompletionCallback two_callback
;
551 EXPECT_EQ(ERR_IO_PENDING
,
552 two_transaction
.Start(GetRequestInfo("two.html"),
553 two_callback
.callback(), BoundNetLog()));
555 one_transaction
.reset();
556 data_vector_
[0]->RunFor(2);
557 data_vector_
[0]->SetStop(10);
559 EXPECT_EQ(OK
, two_callback
.WaitForResult());
560 ExpectResponse("two.html", two_transaction
, SYNCHRONOUS
);
563 TEST_F(HttpPipelinedNetworkTransactionTest
, BasicHttpAuthentication
) {
566 MockWrite writes
[] = {
567 MockWrite(SYNCHRONOUS
, 0, "GET /one.html HTTP/1.1\r\n"
568 "Host: localhost\r\n"
569 "Connection: keep-alive\r\n\r\n"),
570 MockWrite(SYNCHRONOUS
, 5, "GET /one.html HTTP/1.1\r\n"
571 "Host: localhost\r\n"
572 "Connection: keep-alive\r\n"
573 "Authorization: auth_token\r\n\r\n"),
576 MockRead(SYNCHRONOUS
, 1, "HTTP/1.1 401 Authentication Required\r\n"),
577 MockRead(SYNCHRONOUS
, 2,
578 "WWW-Authenticate: Basic realm=\"Secure Area\"\r\n"),
579 MockRead(SYNCHRONOUS
, 3, "Content-Length: 20\r\n\r\n"),
580 MockRead(SYNCHRONOUS
, 4, "needs authentication"),
581 MockRead(SYNCHRONOUS
, 6, "HTTP/1.1 200 OK\r\n"),
582 MockRead(SYNCHRONOUS
, 7, "Content-Length: 8\r\n\r\n"),
583 MockRead(SYNCHRONOUS
, 8, "one.html"),
585 AddExpectedConnection(reads
, arraysize(reads
), writes
, arraysize(writes
));
587 HttpAuthHandlerMock
* mock_auth
= new HttpAuthHandlerMock
;
588 std::string challenge_text
= "Basic";
589 HttpAuth::ChallengeTokenizer
challenge(challenge_text
.begin(),
590 challenge_text
.end());
591 GURL
origin("localhost");
592 EXPECT_TRUE(mock_auth
->InitFromChallenge(&challenge
,
593 HttpAuth::AUTH_SERVER
,
596 auth_handler_factory_
->AddMockHandler(mock_auth
, HttpAuth::AUTH_SERVER
);
598 HttpNetworkTransaction
transaction(DEFAULT_PRIORITY
, session_
.get());
599 EXPECT_EQ(ERR_IO_PENDING
,
600 transaction
.Start(GetRequestInfo("one.html"),
601 callback_
.callback(),
603 EXPECT_EQ(OK
, callback_
.WaitForResult());
605 AuthCredentials
credentials(ASCIIToUTF16("user"), ASCIIToUTF16("pass"));
606 EXPECT_EQ(OK
, transaction
.RestartWithAuth(credentials
, callback_
.callback()));
608 ExpectResponse("one.html", transaction
, SYNCHRONOUS
);
611 TEST_F(HttpPipelinedNetworkTransactionTest
, OldVersionDisablesPipelining
) {
614 MockWrite writes
[] = {
615 MockWrite(SYNCHRONOUS
, 0, "GET /pipelined.html HTTP/1.1\r\n"
616 "Host: localhost\r\n"
617 "Connection: keep-alive\r\n\r\n"),
620 MockRead(SYNCHRONOUS
, 1, "HTTP/1.0 200 OK\r\n"),
621 MockRead(SYNCHRONOUS
, 2, "Content-Length: 14\r\n\r\n"),
622 MockRead(SYNCHRONOUS
, 3, "pipelined.html"),
624 AddExpectedConnection(reads
, arraysize(reads
), writes
, arraysize(writes
));
626 MockWrite writes2
[] = {
627 MockWrite(SYNCHRONOUS
, 0, "GET /one.html HTTP/1.1\r\n"
628 "Host: localhost\r\n"
629 "Connection: keep-alive\r\n\r\n"),
631 MockRead reads2
[] = {
632 MockRead(SYNCHRONOUS
, 1, "HTTP/1.1 200 OK\r\n"),
633 MockRead(SYNCHRONOUS
, 2, "Content-Length: 8\r\n\r\n"),
634 MockRead(ASYNC
, 3, "one.html"),
635 MockRead(SYNCHRONOUS
, OK
, 4),
637 AddExpectedConnection(reads2
, arraysize(reads2
), writes2
, arraysize(writes2
));
639 MockWrite writes3
[] = {
640 MockWrite(SYNCHRONOUS
, 0, "GET /two.html HTTP/1.1\r\n"
641 "Host: localhost\r\n"
642 "Connection: keep-alive\r\n\r\n"),
644 MockRead reads3
[] = {
645 MockRead(SYNCHRONOUS
, 1, "HTTP/1.1 200 OK\r\n"),
646 MockRead(SYNCHRONOUS
, 2, "Content-Length: 8\r\n\r\n"),
647 MockRead(SYNCHRONOUS
, 3, "two.html"),
648 MockRead(SYNCHRONOUS
, OK
, 4),
650 AddExpectedConnection(reads3
, arraysize(reads3
), writes3
, arraysize(writes3
));
652 HttpNetworkTransaction
one_transaction(DEFAULT_PRIORITY
, session_
.get());
653 TestCompletionCallback one_callback
;
654 EXPECT_EQ(ERR_IO_PENDING
,
655 one_transaction
.Start(GetRequestInfo("pipelined.html"),
656 one_callback
.callback(), BoundNetLog()));
657 EXPECT_EQ(OK
, one_callback
.WaitForResult());
658 ExpectResponse("pipelined.html", one_transaction
, SYNCHRONOUS
);
660 CompleteTwoRequests(1, 4);
663 TEST_F(HttpPipelinedNetworkTransactionTest
, PipelinesImmediatelyIfKnownGood
) {
664 // The first request gets us an HTTP/1.1. The next 3 test pipelining. When the
665 // 3rd request completes, we know pipelining is safe. After the first 4
666 // complete, the 5th and 6th should then be immediately sent pipelined on a
667 // new HttpPipelinedConnection.
668 int old_max_sockets
= ClientSocketPoolManager::max_sockets_per_group(
669 HttpNetworkSession::NORMAL_SOCKET_POOL
);
670 ClientSocketPoolManager::set_max_sockets_per_group(
671 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
674 MockWrite writes
[] = {
675 MockWrite(SYNCHRONOUS
, 0, "GET /one.html HTTP/1.1\r\n"
676 "Host: localhost\r\n"
677 "Connection: keep-alive\r\n\r\n"),
678 MockWrite(SYNCHRONOUS
, 4, "GET /two.html HTTP/1.1\r\n"
679 "Host: localhost\r\n"
680 "Connection: keep-alive\r\n\r\n"),
681 MockWrite(SYNCHRONOUS
, 7, "GET /three.html HTTP/1.1\r\n"
682 "Host: localhost\r\n"
683 "Connection: keep-alive\r\n\r\n"),
684 MockWrite(SYNCHRONOUS
, 12, "GET /four.html HTTP/1.1\r\n"
685 "Host: localhost\r\n"
686 "Connection: keep-alive\r\n\r\n"),
687 MockWrite(SYNCHRONOUS
, 16, "GET /second-pipeline-one.html HTTP/1.1\r\n"
688 "Host: localhost\r\n"
689 "Connection: keep-alive\r\n\r\n"),
690 MockWrite(SYNCHRONOUS
, 17, "GET /second-pipeline-two.html HTTP/1.1\r\n"
691 "Host: localhost\r\n"
692 "Connection: keep-alive\r\n\r\n"),
695 MockRead(SYNCHRONOUS
, 1, "HTTP/1.1 200 OK\r\n"),
696 MockRead(SYNCHRONOUS
, 2, "Content-Length: 8\r\n\r\n"),
697 MockRead(SYNCHRONOUS
, 3, "one.html"),
698 MockRead(SYNCHRONOUS
, 5, "HTTP/1.1 200 OK\r\n"),
699 MockRead(SYNCHRONOUS
, 6, "Content-Length: 8\r\n\r\n"),
700 MockRead(SYNCHRONOUS
, 8, "two.html"),
701 MockRead(SYNCHRONOUS
, 9, "HTTP/1.1 200 OK\r\n"),
702 MockRead(SYNCHRONOUS
, 10, "Content-Length: 10\r\n\r\n"),
703 MockRead(SYNCHRONOUS
, 11, "three.html"),
704 MockRead(SYNCHRONOUS
, 13, "HTTP/1.1 200 OK\r\n"),
705 MockRead(SYNCHRONOUS
, 14, "Content-Length: 9\r\n\r\n"),
706 MockRead(SYNCHRONOUS
, 15, "four.html"),
707 MockRead(ASYNC
, 18, "HTTP/1.1 200 OK\r\n"),
708 MockRead(ASYNC
, 19, "Content-Length: 24\r\n\r\n"),
709 MockRead(SYNCHRONOUS
, 20, "second-pipeline-one.html"),
710 MockRead(SYNCHRONOUS
, 21, "HTTP/1.1 200 OK\r\n"),
711 MockRead(SYNCHRONOUS
, 22, "Content-Length: 24\r\n\r\n"),
712 MockRead(SYNCHRONOUS
, 23, "second-pipeline-two.html"),
714 AddExpectedConnection(reads
, arraysize(reads
), writes
, arraysize(writes
));
716 CompleteFourRequests(REQUEST_DEFAULT
);
718 HttpNetworkTransaction
second_one_transaction(
719 DEFAULT_PRIORITY
, session_
.get());
720 TestCompletionCallback second_one_callback
;
721 EXPECT_EQ(ERR_IO_PENDING
,
722 second_one_transaction
.Start(
723 GetRequestInfo("second-pipeline-one.html"),
724 second_one_callback
.callback(), BoundNetLog()));
725 base::MessageLoop::current()->RunUntilIdle();
727 HttpNetworkTransaction
second_two_transaction(
728 DEFAULT_PRIORITY
, session_
.get());
729 TestCompletionCallback second_two_callback
;
730 EXPECT_EQ(ERR_IO_PENDING
,
731 second_two_transaction
.Start(
732 GetRequestInfo("second-pipeline-two.html"),
733 second_two_callback
.callback(), BoundNetLog()));
735 data_vector_
[0]->RunFor(3);
736 EXPECT_EQ(OK
, second_one_callback
.WaitForResult());
737 data_vector_
[0]->StopAfter(100);
738 ExpectResponse("second-pipeline-one.html", second_one_transaction
,
740 EXPECT_EQ(OK
, second_two_callback
.WaitForResult());
741 ExpectResponse("second-pipeline-two.html", second_two_transaction
,
744 ClientSocketPoolManager::set_max_sockets_per_group(
745 HttpNetworkSession::NORMAL_SOCKET_POOL
, old_max_sockets
);
748 class DataRunnerObserver
: public base::MessageLoop::TaskObserver
{
750 DataRunnerObserver(DeterministicSocketData
* data
, int run_before_task
)
752 run_before_task_(run_before_task
),
755 virtual void WillProcessTask(const base::PendingTask
& pending_task
) OVERRIDE
{
757 if (current_task_
== run_before_task_
) {
759 base::MessageLoop::current()->RemoveTaskObserver(this);
763 virtual void DidProcessTask(const base::PendingTask
& pending_task
) OVERRIDE
{}
766 DeterministicSocketData
* data_
;
767 int run_before_task_
;
771 TEST_F(HttpPipelinedNetworkTransactionTest
, OpenPipelinesWhileBinding
) {
772 // There was a racy crash in the pipelining code. This test recreates that
773 // race. The steps are:
774 // 1. The first request starts a pipeline and requests headers.
775 // 2. HttpStreamFactoryImpl::Job tries to bind a pending request to a new
776 // pipeline and queues a task to do so.
777 // 3. Before that task runs, the first request receives its headers and
778 // determines this host is probably capable of pipelining.
779 // 4. All of the hosts' pipelines are notified they have capacity in a loop.
780 // 5. On the first iteration, the first pipeline is opened up to accept new
781 // requests and steals the request from step #2.
782 // 6. The pipeline from #2 is deleted because it has no streams.
783 // 7. On the second iteration, the host tries to notify the pipeline from step
784 // #2 that it has capacity. This is a use-after-free.
787 MockWrite writes
[] = {
788 MockWrite(SYNCHRONOUS
, 0, "GET /one.html HTTP/1.1\r\n"
789 "Host: localhost\r\n"
790 "Connection: keep-alive\r\n\r\n"),
791 MockWrite(ASYNC
, 3, "GET /two.html HTTP/1.1\r\n"
792 "Host: localhost\r\n"
793 "Connection: keep-alive\r\n\r\n"),
796 MockRead(SYNCHRONOUS
, 1, "HTTP/1.1 200 OK\r\n"),
797 MockRead(ASYNC
, 2, "Content-Length: 8\r\n\r\n"),
798 MockRead(SYNCHRONOUS
, 4, "one.html"),
799 MockRead(SYNCHRONOUS
, 5, "HTTP/1.1 200 OK\r\n"),
800 MockRead(SYNCHRONOUS
, 6, "Content-Length: 8\r\n\r\n"),
801 MockRead(SYNCHRONOUS
, 7, "two.html"),
803 AddExpectedConnection(reads
, arraysize(reads
), writes
, arraysize(writes
));
805 AddExpectedConnection(NULL
, 0, NULL
, 0);
807 HttpNetworkTransaction
one_transaction(DEFAULT_PRIORITY
, session_
.get());
808 TestCompletionCallback one_callback
;
809 EXPECT_EQ(ERR_IO_PENDING
,
810 one_transaction
.Start(GetRequestInfo("one.html"),
811 one_callback
.callback(), BoundNetLog()));
813 data_vector_
[0]->SetStop(2);
814 data_vector_
[0]->Run();
816 HttpNetworkTransaction
two_transaction(DEFAULT_PRIORITY
, session_
.get());
817 TestCompletionCallback two_callback
;
818 EXPECT_EQ(ERR_IO_PENDING
,
819 two_transaction
.Start(GetRequestInfo("two.html"),
820 two_callback
.callback(), BoundNetLog()));
821 // Posted tasks should be:
822 // 1. MockHostResolverBase::ResolveNow
823 // 2. HttpStreamFactoryImpl::Job::OnStreamReadyCallback for job 1
824 // 3. HttpStreamFactoryImpl::Job::OnStreamReadyCallback for job 2
826 // We need to make sure that the response that triggers OnPipelineFeedback(OK)
827 // is called in between when task #3 is scheduled and when it runs. The
828 // DataRunnerObserver does that.
829 DataRunnerObserver
observer(data_vector_
[0], 3);
830 base::MessageLoop::current()->AddTaskObserver(&observer
);
831 data_vector_
[0]->SetStop(4);
832 base::MessageLoop::current()->RunUntilIdle();
833 data_vector_
[0]->SetStop(10);
835 EXPECT_EQ(OK
, one_callback
.WaitForResult());
836 ExpectResponse("one.html", one_transaction
, SYNCHRONOUS
);
837 EXPECT_EQ(OK
, two_callback
.WaitForResult());
838 ExpectResponse("two.html", two_transaction
, SYNCHRONOUS
);
841 TEST_F(HttpPipelinedNetworkTransactionTest
, ProxyChangesWhileConnecting
) {
844 DeterministicSocketData
data(NULL
, 0, NULL
, 0);
845 data
.set_connect_data(MockConnect(ASYNC
, ERR_CONNECTION_REFUSED
));
846 factory_
.AddSocketDataProvider(&data
);
848 DeterministicSocketData
data2(NULL
, 0, NULL
, 0);
849 data2
.set_connect_data(MockConnect(ASYNC
, ERR_FAILED
));
850 factory_
.AddSocketDataProvider(&data2
);
852 HttpNetworkTransaction
transaction(DEFAULT_PRIORITY
, session_
.get());
853 EXPECT_EQ(ERR_IO_PENDING
,
854 transaction
.Start(GetRequestInfo("test.html"), callback_
.callback(),
857 proxy_config_service_
->IncrementConfigId();
859 EXPECT_EQ(ERR_FAILED
, callback_
.WaitForResult());
862 TEST_F(HttpPipelinedNetworkTransactionTest
, ForcedPipelineSharesConnection
) {
865 MockWrite writes
[] = {
866 MockWrite(ASYNC
, 0, "GET /one.html HTTP/1.1\r\n"
867 "Host: localhost\r\n"
868 "Connection: keep-alive\r\n\r\n"
869 "GET /two.html HTTP/1.1\r\n"
870 "Host: localhost\r\n"
871 "Connection: keep-alive\r\n\r\n"),
874 MockRead(ASYNC
, 1, "HTTP/1.1 200 OK\r\n"),
875 MockRead(ASYNC
, 2, "Content-Length: 8\r\n\r\n"),
876 MockRead(ASYNC
, 3, "one.html"),
877 MockRead(ASYNC
, 4, "HTTP/1.1 200 OK\r\n"),
878 MockRead(ASYNC
, 5, "Content-Length: 8\r\n\r\n"),
879 MockRead(ASYNC
, 6, "two.html"),
881 AddExpectedConnection(reads
, arraysize(reads
), writes
, arraysize(writes
));
883 scoped_ptr
<HttpNetworkTransaction
> one_transaction(
884 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session_
.get()));
885 TestCompletionCallback one_callback
;
886 EXPECT_EQ(ERR_IO_PENDING
,
887 one_transaction
->Start(GetRequestInfo("one.html"),
888 one_callback
.callback(), BoundNetLog()));
890 HttpNetworkTransaction
two_transaction(DEFAULT_PRIORITY
, session_
.get());
891 TestCompletionCallback two_callback
;
892 EXPECT_EQ(ERR_IO_PENDING
,
893 two_transaction
.Start(GetRequestInfo("two.html"),
894 two_callback
.callback(), BoundNetLog()));
896 data_vector_
[0]->RunFor(3); // Send + 2 lines of headers.
897 EXPECT_EQ(OK
, one_callback
.WaitForResult());
898 ExpectResponse("one.html", *one_transaction
.get(), ASYNC
);
899 one_transaction
.reset();
901 data_vector_
[0]->RunFor(2); // 2 lines of headers.
902 EXPECT_EQ(OK
, two_callback
.WaitForResult());
903 ExpectResponse("two.html", two_transaction
, ASYNC
);
906 TEST_F(HttpPipelinedNetworkTransactionTest
,
907 ForcedPipelineConnectionErrorFailsBoth
) {
910 DeterministicSocketData
data(NULL
, 0, NULL
, 0);
911 data
.set_connect_data(MockConnect(ASYNC
, ERR_FAILED
));
912 factory_
.AddSocketDataProvider(&data
);
914 scoped_ptr
<HttpNetworkTransaction
> one_transaction(
915 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session_
.get()));
916 TestCompletionCallback one_callback
;
917 EXPECT_EQ(ERR_IO_PENDING
,
918 one_transaction
->Start(GetRequestInfo("one.html"),
919 one_callback
.callback(), BoundNetLog()));
921 HttpNetworkTransaction
two_transaction(DEFAULT_PRIORITY
, session_
.get());
922 TestCompletionCallback two_callback
;
923 EXPECT_EQ(ERR_IO_PENDING
,
924 two_transaction
.Start(GetRequestInfo("two.html"),
925 two_callback
.callback(), BoundNetLog()));
928 EXPECT_EQ(ERR_FAILED
, one_callback
.WaitForResult());
929 EXPECT_EQ(ERR_FAILED
, two_callback
.WaitForResult());
932 TEST_F(HttpPipelinedNetworkTransactionTest
, ForcedPipelineEvictionIsFatal
) {
935 MockWrite writes
[] = {
936 MockWrite(ASYNC
, 0, "GET /one.html HTTP/1.1\r\n"
937 "Host: localhost\r\n"
938 "Connection: keep-alive\r\n\r\n"
939 "GET /two.html HTTP/1.1\r\n"
940 "Host: localhost\r\n"
941 "Connection: keep-alive\r\n\r\n"),
944 MockRead(ASYNC
, ERR_FAILED
, 1),
946 AddExpectedConnection(reads
, arraysize(reads
), writes
, arraysize(writes
));
948 scoped_ptr
<HttpNetworkTransaction
> one_transaction(
949 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session_
.get()));
950 TestCompletionCallback one_callback
;
951 EXPECT_EQ(ERR_IO_PENDING
,
952 one_transaction
->Start(GetRequestInfo("one.html"),
953 one_callback
.callback(), BoundNetLog()));
955 HttpNetworkTransaction
two_transaction(DEFAULT_PRIORITY
, session_
.get());
956 TestCompletionCallback two_callback
;
957 EXPECT_EQ(ERR_IO_PENDING
,
958 two_transaction
.Start(GetRequestInfo("two.html"),
959 two_callback
.callback(), BoundNetLog()));
961 data_vector_
[0]->RunFor(2);
962 EXPECT_EQ(ERR_FAILED
, one_callback
.WaitForResult());
963 one_transaction
.reset();
964 EXPECT_EQ(ERR_PIPELINE_EVICTION
, two_callback
.WaitForResult());
967 TEST_F(HttpPipelinedNetworkTransactionTest
, ForcedPipelineOrder
) {
970 MockWrite writes
[] = {
972 "GET /one.html HTTP/1.1\r\n"
973 "Host: localhost\r\n"
974 "Connection: keep-alive\r\n\r\n"
975 "GET /two.html HTTP/1.1\r\n"
976 "Host: localhost\r\n"
977 "Connection: keep-alive\r\n\r\n"
978 "GET /three.html HTTP/1.1\r\n"
979 "Host: localhost\r\n"
980 "Connection: keep-alive\r\n\r\n"
981 "GET /four.html HTTP/1.1\r\n"
982 "Host: localhost\r\n"
983 "Connection: keep-alive\r\n\r\n"
987 MockRead(ASYNC
, ERR_FAILED
, 1),
989 DeterministicSocketData
data(
990 reads
, arraysize(reads
), writes
, arraysize(writes
));
991 data
.set_connect_data(MockConnect(ASYNC
, OK
));
992 factory_
.AddSocketDataProvider(&data
);
994 scoped_ptr
<HttpNetworkTransaction
> one_transaction(
995 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session_
.get()));
996 TestCompletionCallback one_callback
;
997 EXPECT_EQ(ERR_IO_PENDING
,
998 one_transaction
->Start(GetRequestInfo("one.html"),
999 one_callback
.callback(), BoundNetLog()));
1001 scoped_ptr
<HttpNetworkTransaction
> two_transaction(
1002 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session_
.get()));
1003 TestCompletionCallback two_callback
;
1004 EXPECT_EQ(ERR_IO_PENDING
,
1005 two_transaction
->Start(GetRequestInfo("two.html"),
1006 two_callback
.callback(), BoundNetLog()));
1008 scoped_ptr
<HttpNetworkTransaction
> three_transaction(
1009 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session_
.get()));
1010 TestCompletionCallback three_callback
;
1011 EXPECT_EQ(ERR_IO_PENDING
,
1012 three_transaction
->Start(GetRequestInfo("three.html"),
1013 three_callback
.callback(), BoundNetLog()));
1015 scoped_ptr
<HttpNetworkTransaction
> four_transaction(
1016 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session_
.get()));
1017 TestCompletionCallback four_callback
;
1018 EXPECT_EQ(ERR_IO_PENDING
,
1019 four_transaction
->Start(GetRequestInfo("four.html"),
1020 four_callback
.callback(), BoundNetLog()));
1023 EXPECT_EQ(ERR_FAILED
, one_callback
.WaitForResult());
1024 one_transaction
.reset();
1025 EXPECT_EQ(ERR_PIPELINE_EVICTION
, two_callback
.WaitForResult());
1026 two_transaction
.reset();
1027 EXPECT_EQ(ERR_PIPELINE_EVICTION
, three_callback
.WaitForResult());
1028 three_transaction
.reset();
1029 EXPECT_EQ(ERR_PIPELINE_EVICTION
, four_callback
.WaitForResult());
1032 } // anonymous namespace