Pass CreateDirectory errors up to IndexedDB.
[chromium-blink-merge.git] / net / http / http_pipelined_network_transaction_unittest.cc
blobaf620b31c9a2614a7de0fe835b7cb7ddab56361c
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.
5 #include <string>
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"
34 using testing::StrEq;
36 namespace net {
38 namespace {
40 class SimpleProxyConfigService : public ProxyConfigService {
41 public:
42 virtual void AddObserver(Observer* observer) OVERRIDE {
43 observer_ = observer;
46 virtual void RemoveObserver(Observer* observer) OVERRIDE {
47 if (observer_ == observer) {
48 observer_ = NULL;
52 virtual ConfigAvailability GetLatestProxyConfig(
53 ProxyConfig* config) OVERRIDE {
54 *config = config_;
55 return CONFIG_VALID;
58 void IncrementConfigId() {
59 config_.set_id(config_.id() + 1);
60 observer_->OnProxyConfigChanged(config_, ProxyConfigService::CONFIG_VALID);
63 private:
64 ProxyConfig config_;
65 Observer* observer_;
68 class HttpPipelinedNetworkTransactionTest : public testing::Test {
69 public:
70 HttpPipelinedNetworkTransactionTest()
71 : histograms_("a"),
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 {
109 REQUEST_DEFAULT,
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);
123 return request_info;
126 void ExpectResponse(const std::string& expected,
127 HttpNetworkTransaction& transaction,
128 IoMode io_mode) {
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());
135 } else {
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(),
200 BoundNetLog()));
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) {
236 Initialize(false);
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"),
243 MockRead reads[] = {
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(),
253 BoundNetLog()));
254 EXPECT_EQ(OK, callback_.WaitForResult());
255 ExpectResponse("test.html", transaction, SYNCHRONOUS);
258 TEST_F(HttpPipelinedNetworkTransactionTest, ReusePipeline) {
259 Initialize(false);
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"),
269 MockRead reads[] = {
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);
287 Initialize(false);
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"),
303 MockRead reads[] = {
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);
330 Initialize(false);
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"),
346 MockRead reads[] = {
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) {
369 Initialize(false);
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"),
376 MockRead reads[] = {
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) {
399 Initialize(false);
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"),
409 MockRead reads[] = {
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) {
433 Initialize(false);
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"),
443 MockRead reads[] = {
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) {
482 Initialize(false);
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) {
521 Initialize(false);
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"),
531 MockRead reads[] = {
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) {
564 Initialize(false);
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"),
575 MockRead reads[] = {
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,
594 origin,
595 BoundNetLog()));
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(),
602 BoundNetLog()));
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) {
612 Initialize(false);
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"),
619 MockRead reads[] = {
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);
672 Initialize(false);
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"),
694 MockRead reads[] = {
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,
739 SYNCHRONOUS);
740 EXPECT_EQ(OK, second_two_callback.WaitForResult());
741 ExpectResponse("second-pipeline-two.html", second_two_transaction,
742 SYNCHRONOUS);
744 ClientSocketPoolManager::set_max_sockets_per_group(
745 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_sockets);
748 class DataRunnerObserver : public base::MessageLoop::TaskObserver {
749 public:
750 DataRunnerObserver(DeterministicSocketData* data, int run_before_task)
751 : data_(data),
752 run_before_task_(run_before_task),
753 current_task_(0) { }
755 virtual void WillProcessTask(const base::PendingTask& pending_task) OVERRIDE {
756 ++current_task_;
757 if (current_task_ == run_before_task_) {
758 data_->Run();
759 base::MessageLoop::current()->RemoveTaskObserver(this);
763 virtual void DidProcessTask(const base::PendingTask& pending_task) OVERRIDE {}
765 private:
766 DeterministicSocketData* data_;
767 int run_before_task_;
768 int current_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.
785 Initialize(false);
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"),
795 MockRead reads[] = {
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) {
842 Initialize(false);
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(),
855 BoundNetLog()));
857 proxy_config_service_->IncrementConfigId();
859 EXPECT_EQ(ERR_FAILED, callback_.WaitForResult());
862 TEST_F(HttpPipelinedNetworkTransactionTest, ForcedPipelineSharesConnection) {
863 Initialize(true);
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"),
873 MockRead reads[] = {
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) {
908 Initialize(true);
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()));
927 data.Run();
928 EXPECT_EQ(ERR_FAILED, one_callback.WaitForResult());
929 EXPECT_EQ(ERR_FAILED, two_callback.WaitForResult());
932 TEST_F(HttpPipelinedNetworkTransactionTest, ForcedPipelineEvictionIsFatal) {
933 Initialize(true);
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"),
943 MockRead reads[] = {
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) {
968 Initialize(true);
970 MockWrite writes[] = {
971 MockWrite(ASYNC, 0,
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"
986 MockRead reads[] = {
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()));
1022 data.RunFor(3);
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
1034 } // namespace net