- add sources.
[platform/framework/web/crosswalk.git] / src / net / http / http_pipelined_network_transaction_unittest.cc
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.
4
5 #include <string>
6
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"
33
34 using testing::StrEq;
35
36 namespace net {
37
38 namespace {
39
40 class SimpleProxyConfigService : public ProxyConfigService {
41  public:
42   virtual void AddObserver(Observer* observer) OVERRIDE {
43     observer_ = observer;
44   }
45
46   virtual void RemoveObserver(Observer* observer) OVERRIDE {
47     if (observer_ == observer) {
48       observer_ = NULL;
49     }
50   }
51
52   virtual ConfigAvailability GetLatestProxyConfig(
53       ProxyConfig* config) OVERRIDE {
54     *config = config_;
55     return CONFIG_VALID;
56   }
57
58   void IncrementConfigId() {
59     config_.set_id(config_.id() + 1);
60     observer_->OnProxyConfigChanged(config_, ProxyConfigService::CONFIG_VALID);
61   }
62
63  private:
64   ProxyConfig config_;
65   Observer* observer_;
66 };
67
68 class HttpPipelinedNetworkTransactionTest : public testing::Test {
69  public:
70   HttpPipelinedNetworkTransactionTest()
71       : histograms_("a"),
72         pool_(1, 1, &histograms_, &factory_) {
73   }
74
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());
83
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 =
91         http_server_properties_.GetWeakPtr();
92     session_params.force_http_pipelining = force_http_pipelining;
93     session_params.http_pipelining_enabled = true;
94     session_ = new HttpNetworkSession(session_params);
95   }
96
97   void AddExpectedConnection(MockRead* reads, size_t reads_count,
98                              MockWrite* writes, size_t writes_count) {
99     DeterministicSocketData* data = new DeterministicSocketData(
100         reads, reads_count, writes, writes_count);
101     data->set_connect_data(MockConnect(SYNCHRONOUS, OK));
102     if (reads_count || writes_count) {
103       data->StopAfter(reads_count + writes_count);
104     }
105     factory_.AddSocketDataProvider(data);
106     data_vector_.push_back(data);
107   }
108
109   enum RequestInfoOptions {
110     REQUEST_DEFAULT,
111     REQUEST_MAIN_RESOURCE,
112   };
113
114   HttpRequestInfo* GetRequestInfo(
115       const char* filename, RequestInfoOptions options = REQUEST_DEFAULT) {
116     std::string url = base::StringPrintf("http://localhost/%s", filename);
117     HttpRequestInfo* request_info = new HttpRequestInfo;
118     request_info->url = GURL(url);
119     request_info->method = "GET";
120     if (options == REQUEST_MAIN_RESOURCE) {
121       request_info->load_flags = LOAD_MAIN_FRAME;
122     }
123     request_info_vector_.push_back(request_info);
124     return request_info;
125   }
126
127   void ExpectResponse(const std::string& expected,
128                       HttpNetworkTransaction& transaction,
129                       IoMode io_mode) {
130     scoped_refptr<IOBuffer> buffer(new IOBuffer(expected.size()));
131     if (io_mode == ASYNC) {
132       EXPECT_EQ(ERR_IO_PENDING, transaction.Read(buffer.get(), expected.size(),
133                                                  callback_.callback()));
134       data_vector_[0]->RunFor(1);
135       EXPECT_EQ(static_cast<int>(expected.length()), callback_.WaitForResult());
136     } else {
137       EXPECT_EQ(static_cast<int>(expected.size()),
138                 transaction.Read(buffer.get(), expected.size(),
139                                  callback_.callback()));
140     }
141     std::string actual(buffer->data(), expected.size());
142     EXPECT_THAT(actual, StrEq(expected));
143     EXPECT_EQ(OK, transaction.Read(buffer.get(), expected.size(),
144                                    callback_.callback()));
145   }
146
147   void CompleteTwoRequests(int data_index, int stop_at_step) {
148     scoped_ptr<HttpNetworkTransaction> one_transaction(
149         new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
150     TestCompletionCallback one_callback;
151     EXPECT_EQ(ERR_IO_PENDING,
152               one_transaction->Start(GetRequestInfo("one.html"),
153                                      one_callback.callback(), BoundNetLog()));
154     EXPECT_EQ(OK, one_callback.WaitForResult());
155
156     HttpNetworkTransaction two_transaction(DEFAULT_PRIORITY, session_.get());
157     TestCompletionCallback two_callback;
158     EXPECT_EQ(ERR_IO_PENDING,
159               two_transaction.Start(GetRequestInfo("two.html"),
160                                     two_callback.callback(), BoundNetLog()));
161
162     TestCompletionCallback one_read_callback;
163     scoped_refptr<IOBuffer> buffer(new IOBuffer(8));
164     EXPECT_EQ(ERR_IO_PENDING,
165               one_transaction->Read(buffer.get(), 8,
166                                     one_read_callback.callback()));
167
168     data_vector_[data_index]->SetStop(stop_at_step);
169     data_vector_[data_index]->Run();
170     EXPECT_EQ(8, one_read_callback.WaitForResult());
171     data_vector_[data_index]->SetStop(10);
172     std::string actual(buffer->data(), 8);
173     EXPECT_THAT(actual, StrEq("one.html"));
174     EXPECT_EQ(OK, one_transaction->Read(buffer.get(), 8,
175                                         one_read_callback.callback()));
176
177     EXPECT_EQ(OK, two_callback.WaitForResult());
178     ExpectResponse("two.html", two_transaction, SYNCHRONOUS);
179   }
180
181   void CompleteFourRequests(RequestInfoOptions options) {
182     scoped_ptr<HttpNetworkTransaction> one_transaction(
183         new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
184     TestCompletionCallback one_callback;
185     EXPECT_EQ(ERR_IO_PENDING,
186               one_transaction->Start(GetRequestInfo("one.html", options),
187                                      one_callback.callback(), BoundNetLog()));
188     EXPECT_EQ(OK, one_callback.WaitForResult());
189
190     HttpNetworkTransaction two_transaction(DEFAULT_PRIORITY, session_.get());
191     TestCompletionCallback two_callback;
192     EXPECT_EQ(ERR_IO_PENDING,
193               two_transaction.Start(GetRequestInfo("two.html", options),
194                                     two_callback.callback(), BoundNetLog()));
195
196     HttpNetworkTransaction three_transaction(DEFAULT_PRIORITY, session_.get());
197     TestCompletionCallback three_callback;
198     EXPECT_EQ(ERR_IO_PENDING,
199               three_transaction.Start(GetRequestInfo("three.html", options),
200                                       three_callback.callback(),
201                                       BoundNetLog()));
202
203     HttpNetworkTransaction four_transaction(DEFAULT_PRIORITY, session_.get());
204     TestCompletionCallback four_callback;
205     EXPECT_EQ(ERR_IO_PENDING,
206               four_transaction.Start(GetRequestInfo("four.html", options),
207                                      four_callback.callback(), BoundNetLog()));
208
209     ExpectResponse("one.html", *one_transaction.get(), SYNCHRONOUS);
210     EXPECT_EQ(OK, two_callback.WaitForResult());
211     ExpectResponse("two.html", two_transaction, SYNCHRONOUS);
212     EXPECT_EQ(OK, three_callback.WaitForResult());
213     ExpectResponse("three.html", three_transaction, SYNCHRONOUS);
214
215     one_transaction.reset();
216     EXPECT_EQ(OK, four_callback.WaitForResult());
217     ExpectResponse("four.html", four_transaction, SYNCHRONOUS);
218   }
219
220   DeterministicMockClientSocketFactory factory_;
221   ClientSocketPoolHistograms histograms_;
222   MockTransportClientSocketPool pool_;
223   ScopedVector<DeterministicSocketData> data_vector_;
224   TestCompletionCallback callback_;
225   ScopedVector<HttpRequestInfo> request_info_vector_;
226
227   SimpleProxyConfigService* proxy_config_service_;
228   scoped_ptr<ProxyService> proxy_service_;
229   MockHostResolver mock_resolver_;
230   scoped_refptr<SSLConfigService> ssl_config_;
231   scoped_ptr<HttpAuthHandlerMock::Factory> auth_handler_factory_;
232   HttpServerPropertiesImpl http_server_properties_;
233   scoped_refptr<HttpNetworkSession> session_;
234 };
235
236 TEST_F(HttpPipelinedNetworkTransactionTest, OneRequest) {
237   Initialize(false);
238
239   MockWrite writes[] = {
240     MockWrite(SYNCHRONOUS, 0, "GET /test.html HTTP/1.1\r\n"
241               "Host: localhost\r\n"
242               "Connection: keep-alive\r\n\r\n"),
243   };
244   MockRead reads[] = {
245     MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"),
246     MockRead(SYNCHRONOUS, 2, "Content-Length: 9\r\n\r\n"),
247     MockRead(SYNCHRONOUS, 3, "test.html"),
248   };
249   AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
250
251   HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session_.get());
252   EXPECT_EQ(ERR_IO_PENDING,
253             transaction.Start(GetRequestInfo("test.html"), callback_.callback(),
254                               BoundNetLog()));
255   EXPECT_EQ(OK, callback_.WaitForResult());
256   ExpectResponse("test.html", transaction, SYNCHRONOUS);
257 }
258
259 TEST_F(HttpPipelinedNetworkTransactionTest, ReusePipeline) {
260   Initialize(false);
261
262   MockWrite writes[] = {
263     MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n"
264               "Host: localhost\r\n"
265               "Connection: keep-alive\r\n\r\n"),
266     MockWrite(SYNCHRONOUS, 3, "GET /two.html HTTP/1.1\r\n"
267               "Host: localhost\r\n"
268               "Connection: keep-alive\r\n\r\n"),
269   };
270   MockRead reads[] = {
271     MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"),
272     MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"),
273     MockRead(ASYNC, 4, "one.html"),
274     MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"),
275     MockRead(SYNCHRONOUS, 6, "Content-Length: 8\r\n\r\n"),
276     MockRead(SYNCHRONOUS, 7, "two.html"),
277   };
278   AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
279
280   CompleteTwoRequests(0, 5);
281 }
282
283 TEST_F(HttpPipelinedNetworkTransactionTest, ReusesOnSpaceAvailable) {
284   int old_max_sockets = ClientSocketPoolManager::max_sockets_per_group(
285       HttpNetworkSession::NORMAL_SOCKET_POOL);
286   ClientSocketPoolManager::set_max_sockets_per_group(
287       HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
288   Initialize(false);
289
290   MockWrite writes[] = {
291     MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n"
292               "Host: localhost\r\n"
293               "Connection: keep-alive\r\n\r\n"),
294     MockWrite(SYNCHRONOUS, 4, "GET /two.html HTTP/1.1\r\n"
295               "Host: localhost\r\n"
296               "Connection: keep-alive\r\n\r\n"),
297     MockWrite(SYNCHRONOUS, 7, "GET /three.html HTTP/1.1\r\n"
298               "Host: localhost\r\n"
299               "Connection: keep-alive\r\n\r\n"),
300     MockWrite(SYNCHRONOUS, 12, "GET /four.html HTTP/1.1\r\n"
301               "Host: localhost\r\n"
302               "Connection: keep-alive\r\n\r\n"),
303   };
304   MockRead reads[] = {
305     MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"),
306     MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"),
307     MockRead(SYNCHRONOUS, 3, "one.html"),
308     MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"),
309     MockRead(SYNCHRONOUS, 6, "Content-Length: 8\r\n\r\n"),
310     MockRead(SYNCHRONOUS, 8, "two.html"),
311     MockRead(SYNCHRONOUS, 9, "HTTP/1.1 200 OK\r\n"),
312     MockRead(SYNCHRONOUS, 10, "Content-Length: 10\r\n\r\n"),
313     MockRead(SYNCHRONOUS, 11, "three.html"),
314     MockRead(SYNCHRONOUS, 13, "HTTP/1.1 200 OK\r\n"),
315     MockRead(SYNCHRONOUS, 14, "Content-Length: 9\r\n\r\n"),
316     MockRead(SYNCHRONOUS, 15, "four.html"),
317   };
318   AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
319
320   CompleteFourRequests(REQUEST_DEFAULT);
321
322   ClientSocketPoolManager::set_max_sockets_per_group(
323       HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_sockets);
324 }
325
326 TEST_F(HttpPipelinedNetworkTransactionTest, WontPipelineMainResource) {
327   int old_max_sockets = ClientSocketPoolManager::max_sockets_per_group(
328       HttpNetworkSession::NORMAL_SOCKET_POOL);
329   ClientSocketPoolManager::set_max_sockets_per_group(
330       HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
331   Initialize(false);
332
333   MockWrite writes[] = {
334     MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n"
335               "Host: localhost\r\n"
336               "Connection: keep-alive\r\n\r\n"),
337     MockWrite(SYNCHRONOUS, 4, "GET /two.html HTTP/1.1\r\n"
338               "Host: localhost\r\n"
339               "Connection: keep-alive\r\n\r\n"),
340     MockWrite(SYNCHRONOUS, 8, "GET /three.html HTTP/1.1\r\n"
341               "Host: localhost\r\n"
342               "Connection: keep-alive\r\n\r\n"),
343     MockWrite(SYNCHRONOUS, 12, "GET /four.html HTTP/1.1\r\n"
344               "Host: localhost\r\n"
345               "Connection: keep-alive\r\n\r\n"),
346   };
347   MockRead reads[] = {
348     MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"),
349     MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"),
350     MockRead(SYNCHRONOUS, 3, "one.html"),
351     MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"),
352     MockRead(SYNCHRONOUS, 6, "Content-Length: 8\r\n\r\n"),
353     MockRead(SYNCHRONOUS, 7, "two.html"),
354     MockRead(SYNCHRONOUS, 9, "HTTP/1.1 200 OK\r\n"),
355     MockRead(SYNCHRONOUS, 10, "Content-Length: 10\r\n\r\n"),
356     MockRead(SYNCHRONOUS, 11, "three.html"),
357     MockRead(SYNCHRONOUS, 13, "HTTP/1.1 200 OK\r\n"),
358     MockRead(SYNCHRONOUS, 14, "Content-Length: 9\r\n\r\n"),
359     MockRead(SYNCHRONOUS, 15, "four.html"),
360   };
361   AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
362
363   CompleteFourRequests(REQUEST_MAIN_RESOURCE);
364
365   ClientSocketPoolManager::set_max_sockets_per_group(
366       HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_sockets);
367 }
368
369 TEST_F(HttpPipelinedNetworkTransactionTest, UnknownSizeEvictsToNewPipeline) {
370   Initialize(false);
371
372   MockWrite writes[] = {
373     MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n"
374               "Host: localhost\r\n"
375               "Connection: keep-alive\r\n\r\n"),
376   };
377   MockRead reads[] = {
378     MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n\r\n"),
379     MockRead(ASYNC, 2, "one.html"),
380     MockRead(SYNCHRONOUS, OK, 3),
381   };
382   AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
383
384   MockWrite writes2[] = {
385     MockWrite(SYNCHRONOUS, 0, "GET /two.html HTTP/1.1\r\n"
386               "Host: localhost\r\n"
387               "Connection: keep-alive\r\n\r\n"),
388   };
389   MockRead reads2[] = {
390     MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"),
391     MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"),
392     MockRead(SYNCHRONOUS, 3, "two.html"),
393   };
394   AddExpectedConnection(reads2, arraysize(reads2), writes2, arraysize(writes2));
395
396   CompleteTwoRequests(0, 3);
397 }
398
399 TEST_F(HttpPipelinedNetworkTransactionTest, ConnectionCloseEvictToNewPipeline) {
400   Initialize(false);
401
402   MockWrite writes[] = {
403     MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n"
404               "Host: localhost\r\n"
405               "Connection: keep-alive\r\n\r\n"),
406     MockWrite(SYNCHRONOUS, 3, "GET /two.html HTTP/1.1\r\n"
407               "Host: localhost\r\n"
408               "Connection: keep-alive\r\n\r\n"),
409   };
410   MockRead reads[] = {
411     MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"),
412     MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"),
413     MockRead(ASYNC, 4, "one.html"),
414     MockRead(SYNCHRONOUS, ERR_SOCKET_NOT_CONNECTED, 5),
415   };
416   AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
417
418   MockWrite writes2[] = {
419     MockWrite(SYNCHRONOUS, 0, "GET /two.html HTTP/1.1\r\n"
420               "Host: localhost\r\n"
421               "Connection: keep-alive\r\n\r\n"),
422   };
423   MockRead reads2[] = {
424     MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"),
425     MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"),
426     MockRead(SYNCHRONOUS, 3, "two.html"),
427   };
428   AddExpectedConnection(reads2, arraysize(reads2), writes2, arraysize(writes2));
429
430   CompleteTwoRequests(0, 5);
431 }
432
433 TEST_F(HttpPipelinedNetworkTransactionTest, ErrorEvictsToNewPipeline) {
434   Initialize(false);
435
436   MockWrite writes[] = {
437     MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n"
438               "Host: localhost\r\n"
439               "Connection: keep-alive\r\n\r\n"),
440     MockWrite(SYNCHRONOUS, 3, "GET /two.html HTTP/1.1\r\n"
441               "Host: localhost\r\n"
442               "Connection: keep-alive\r\n\r\n"),
443   };
444   MockRead reads[] = {
445     MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n\r\n"),
446     MockRead(SYNCHRONOUS, ERR_FAILED, 2),
447   };
448   AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
449
450   MockWrite writes2[] = {
451     MockWrite(SYNCHRONOUS, 0, "GET /two.html HTTP/1.1\r\n"
452               "Host: localhost\r\n"
453               "Connection: keep-alive\r\n\r\n"),
454   };
455   MockRead reads2[] = {
456     MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"),
457     MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"),
458     MockRead(SYNCHRONOUS, 3, "two.html"),
459   };
460   AddExpectedConnection(reads2, arraysize(reads2), writes2, arraysize(writes2));
461
462   HttpNetworkTransaction one_transaction(DEFAULT_PRIORITY, session_.get());
463   TestCompletionCallback one_callback;
464   EXPECT_EQ(ERR_IO_PENDING,
465             one_transaction.Start(GetRequestInfo("one.html"),
466                                   one_callback.callback(), BoundNetLog()));
467   EXPECT_EQ(OK, one_callback.WaitForResult());
468
469   HttpNetworkTransaction two_transaction(DEFAULT_PRIORITY, session_.get());
470   TestCompletionCallback two_callback;
471   EXPECT_EQ(ERR_IO_PENDING,
472             two_transaction.Start(GetRequestInfo("two.html"),
473                                   two_callback.callback(), BoundNetLog()));
474
475   scoped_refptr<IOBuffer> buffer(new IOBuffer(1));
476   EXPECT_EQ(ERR_FAILED,
477             one_transaction.Read(buffer.get(), 1, callback_.callback()));
478   EXPECT_EQ(OK, two_callback.WaitForResult());
479   ExpectResponse("two.html", two_transaction, SYNCHRONOUS);
480 }
481
482 TEST_F(HttpPipelinedNetworkTransactionTest, SendErrorEvictsToNewPipeline) {
483   Initialize(false);
484
485   MockWrite writes[] = {
486     MockWrite(ASYNC, ERR_FAILED, 0),
487   };
488   AddExpectedConnection(NULL, 0, writes, arraysize(writes));
489
490   MockWrite writes2[] = {
491     MockWrite(SYNCHRONOUS, 0, "GET /two.html HTTP/1.1\r\n"
492               "Host: localhost\r\n"
493               "Connection: keep-alive\r\n\r\n"),
494   };
495   MockRead reads2[] = {
496     MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"),
497     MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"),
498     MockRead(SYNCHRONOUS, 3, "two.html"),
499   };
500   AddExpectedConnection(reads2, arraysize(reads2), writes2, arraysize(writes2));
501
502   HttpNetworkTransaction one_transaction(DEFAULT_PRIORITY, session_.get());
503   TestCompletionCallback one_callback;
504   EXPECT_EQ(ERR_IO_PENDING,
505             one_transaction.Start(GetRequestInfo("one.html"),
506                                   one_callback.callback(), BoundNetLog()));
507
508   HttpNetworkTransaction two_transaction(DEFAULT_PRIORITY, session_.get());
509   TestCompletionCallback two_callback;
510   EXPECT_EQ(ERR_IO_PENDING,
511             two_transaction.Start(GetRequestInfo("two.html"),
512                                   two_callback.callback(), BoundNetLog()));
513
514   data_vector_[0]->RunFor(1);
515   EXPECT_EQ(ERR_FAILED, one_callback.WaitForResult());
516
517   EXPECT_EQ(OK, two_callback.WaitForResult());
518   ExpectResponse("two.html", two_transaction, SYNCHRONOUS);
519 }
520
521 TEST_F(HttpPipelinedNetworkTransactionTest, RedirectDrained) {
522   Initialize(false);
523
524   MockWrite writes[] = {
525     MockWrite(SYNCHRONOUS, 0, "GET /redirect.html HTTP/1.1\r\n"
526               "Host: localhost\r\n"
527               "Connection: keep-alive\r\n\r\n"),
528     MockWrite(SYNCHRONOUS, 3, "GET /two.html HTTP/1.1\r\n"
529               "Host: localhost\r\n"
530               "Connection: keep-alive\r\n\r\n"),
531   };
532   MockRead reads[] = {
533     MockRead(SYNCHRONOUS, 1, "HTTP/1.1 302 OK\r\n"),
534     MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"),
535     MockRead(ASYNC, 4, "redirect"),
536     MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"),
537     MockRead(SYNCHRONOUS, 6, "Content-Length: 8\r\n\r\n"),
538     MockRead(SYNCHRONOUS, 7, "two.html"),
539   };
540   AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
541
542   scoped_ptr<HttpNetworkTransaction> one_transaction(
543       new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
544   TestCompletionCallback one_callback;
545   EXPECT_EQ(ERR_IO_PENDING,
546             one_transaction->Start(GetRequestInfo("redirect.html"),
547                                    one_callback.callback(), BoundNetLog()));
548   EXPECT_EQ(OK, one_callback.WaitForResult());
549
550   HttpNetworkTransaction two_transaction(DEFAULT_PRIORITY, session_.get());
551   TestCompletionCallback two_callback;
552   EXPECT_EQ(ERR_IO_PENDING,
553             two_transaction.Start(GetRequestInfo("two.html"),
554                                   two_callback.callback(), BoundNetLog()));
555
556   one_transaction.reset();
557   data_vector_[0]->RunFor(2);
558   data_vector_[0]->SetStop(10);
559
560   EXPECT_EQ(OK, two_callback.WaitForResult());
561   ExpectResponse("two.html", two_transaction, SYNCHRONOUS);
562 }
563
564 TEST_F(HttpPipelinedNetworkTransactionTest, BasicHttpAuthentication) {
565   Initialize(false);
566
567   MockWrite writes[] = {
568     MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n"
569               "Host: localhost\r\n"
570               "Connection: keep-alive\r\n\r\n"),
571     MockWrite(SYNCHRONOUS, 5, "GET /one.html HTTP/1.1\r\n"
572               "Host: localhost\r\n"
573               "Connection: keep-alive\r\n"
574               "Authorization: auth_token\r\n\r\n"),
575   };
576   MockRead reads[] = {
577     MockRead(SYNCHRONOUS, 1, "HTTP/1.1 401 Authentication Required\r\n"),
578     MockRead(SYNCHRONOUS, 2,
579              "WWW-Authenticate: Basic realm=\"Secure Area\"\r\n"),
580     MockRead(SYNCHRONOUS, 3, "Content-Length: 20\r\n\r\n"),
581     MockRead(SYNCHRONOUS, 4, "needs authentication"),
582     MockRead(SYNCHRONOUS, 6, "HTTP/1.1 200 OK\r\n"),
583     MockRead(SYNCHRONOUS, 7, "Content-Length: 8\r\n\r\n"),
584     MockRead(SYNCHRONOUS, 8, "one.html"),
585   };
586   AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
587
588   HttpAuthHandlerMock* mock_auth = new HttpAuthHandlerMock;
589   std::string challenge_text = "Basic";
590   HttpAuth::ChallengeTokenizer challenge(challenge_text.begin(),
591                                          challenge_text.end());
592   GURL origin("localhost");
593   EXPECT_TRUE(mock_auth->InitFromChallenge(&challenge,
594                                            HttpAuth::AUTH_SERVER,
595                                            origin,
596                                            BoundNetLog()));
597   auth_handler_factory_->AddMockHandler(mock_auth, HttpAuth::AUTH_SERVER);
598
599   HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session_.get());
600   EXPECT_EQ(ERR_IO_PENDING,
601             transaction.Start(GetRequestInfo("one.html"),
602                               callback_.callback(),
603                               BoundNetLog()));
604   EXPECT_EQ(OK, callback_.WaitForResult());
605
606   AuthCredentials credentials(ASCIIToUTF16("user"), ASCIIToUTF16("pass"));
607   EXPECT_EQ(OK, transaction.RestartWithAuth(credentials, callback_.callback()));
608
609   ExpectResponse("one.html", transaction, SYNCHRONOUS);
610 }
611
612 TEST_F(HttpPipelinedNetworkTransactionTest, OldVersionDisablesPipelining) {
613   Initialize(false);
614
615   MockWrite writes[] = {
616     MockWrite(SYNCHRONOUS, 0, "GET /pipelined.html HTTP/1.1\r\n"
617               "Host: localhost\r\n"
618               "Connection: keep-alive\r\n\r\n"),
619   };
620   MockRead reads[] = {
621     MockRead(SYNCHRONOUS, 1, "HTTP/1.0 200 OK\r\n"),
622     MockRead(SYNCHRONOUS, 2, "Content-Length: 14\r\n\r\n"),
623     MockRead(SYNCHRONOUS, 3, "pipelined.html"),
624   };
625   AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
626
627   MockWrite writes2[] = {
628     MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n"
629               "Host: localhost\r\n"
630               "Connection: keep-alive\r\n\r\n"),
631   };
632   MockRead reads2[] = {
633     MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"),
634     MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"),
635     MockRead(ASYNC, 3, "one.html"),
636     MockRead(SYNCHRONOUS, OK, 4),
637   };
638   AddExpectedConnection(reads2, arraysize(reads2), writes2, arraysize(writes2));
639
640   MockWrite writes3[] = {
641     MockWrite(SYNCHRONOUS, 0, "GET /two.html HTTP/1.1\r\n"
642               "Host: localhost\r\n"
643               "Connection: keep-alive\r\n\r\n"),
644   };
645   MockRead reads3[] = {
646     MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"),
647     MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"),
648     MockRead(SYNCHRONOUS, 3, "two.html"),
649     MockRead(SYNCHRONOUS, OK, 4),
650   };
651   AddExpectedConnection(reads3, arraysize(reads3), writes3, arraysize(writes3));
652
653   HttpNetworkTransaction one_transaction(DEFAULT_PRIORITY, session_.get());
654   TestCompletionCallback one_callback;
655   EXPECT_EQ(ERR_IO_PENDING,
656             one_transaction.Start(GetRequestInfo("pipelined.html"),
657                                   one_callback.callback(), BoundNetLog()));
658   EXPECT_EQ(OK, one_callback.WaitForResult());
659   ExpectResponse("pipelined.html", one_transaction, SYNCHRONOUS);
660
661   CompleteTwoRequests(1, 4);
662 }
663
664 TEST_F(HttpPipelinedNetworkTransactionTest, PipelinesImmediatelyIfKnownGood) {
665   // The first request gets us an HTTP/1.1. The next 3 test pipelining. When the
666   // 3rd request completes, we know pipelining is safe. After the first 4
667   // complete, the 5th and 6th should then be immediately sent pipelined on a
668   // new HttpPipelinedConnection.
669   int old_max_sockets = ClientSocketPoolManager::max_sockets_per_group(
670       HttpNetworkSession::NORMAL_SOCKET_POOL);
671   ClientSocketPoolManager::set_max_sockets_per_group(
672       HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
673   Initialize(false);
674
675   MockWrite writes[] = {
676     MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n"
677               "Host: localhost\r\n"
678               "Connection: keep-alive\r\n\r\n"),
679     MockWrite(SYNCHRONOUS, 4, "GET /two.html HTTP/1.1\r\n"
680               "Host: localhost\r\n"
681               "Connection: keep-alive\r\n\r\n"),
682     MockWrite(SYNCHRONOUS, 7, "GET /three.html HTTP/1.1\r\n"
683               "Host: localhost\r\n"
684               "Connection: keep-alive\r\n\r\n"),
685     MockWrite(SYNCHRONOUS, 12, "GET /four.html HTTP/1.1\r\n"
686               "Host: localhost\r\n"
687               "Connection: keep-alive\r\n\r\n"),
688     MockWrite(SYNCHRONOUS, 16, "GET /second-pipeline-one.html HTTP/1.1\r\n"
689               "Host: localhost\r\n"
690               "Connection: keep-alive\r\n\r\n"),
691     MockWrite(SYNCHRONOUS, 17, "GET /second-pipeline-two.html HTTP/1.1\r\n"
692               "Host: localhost\r\n"
693               "Connection: keep-alive\r\n\r\n"),
694   };
695   MockRead reads[] = {
696     MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"),
697     MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"),
698     MockRead(SYNCHRONOUS, 3, "one.html"),
699     MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"),
700     MockRead(SYNCHRONOUS, 6, "Content-Length: 8\r\n\r\n"),
701     MockRead(SYNCHRONOUS, 8, "two.html"),
702     MockRead(SYNCHRONOUS, 9, "HTTP/1.1 200 OK\r\n"),
703     MockRead(SYNCHRONOUS, 10, "Content-Length: 10\r\n\r\n"),
704     MockRead(SYNCHRONOUS, 11, "three.html"),
705     MockRead(SYNCHRONOUS, 13, "HTTP/1.1 200 OK\r\n"),
706     MockRead(SYNCHRONOUS, 14, "Content-Length: 9\r\n\r\n"),
707     MockRead(SYNCHRONOUS, 15, "four.html"),
708     MockRead(ASYNC, 18, "HTTP/1.1 200 OK\r\n"),
709     MockRead(ASYNC, 19, "Content-Length: 24\r\n\r\n"),
710     MockRead(SYNCHRONOUS, 20, "second-pipeline-one.html"),
711     MockRead(SYNCHRONOUS, 21, "HTTP/1.1 200 OK\r\n"),
712     MockRead(SYNCHRONOUS, 22, "Content-Length: 24\r\n\r\n"),
713     MockRead(SYNCHRONOUS, 23, "second-pipeline-two.html"),
714   };
715   AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
716
717   CompleteFourRequests(REQUEST_DEFAULT);
718
719   HttpNetworkTransaction second_one_transaction(
720       DEFAULT_PRIORITY, session_.get());
721   TestCompletionCallback second_one_callback;
722   EXPECT_EQ(ERR_IO_PENDING,
723             second_one_transaction.Start(
724                 GetRequestInfo("second-pipeline-one.html"),
725                 second_one_callback.callback(), BoundNetLog()));
726   base::MessageLoop::current()->RunUntilIdle();
727
728   HttpNetworkTransaction second_two_transaction(
729       DEFAULT_PRIORITY, session_.get());
730   TestCompletionCallback second_two_callback;
731   EXPECT_EQ(ERR_IO_PENDING,
732             second_two_transaction.Start(
733                 GetRequestInfo("second-pipeline-two.html"),
734                 second_two_callback.callback(), BoundNetLog()));
735
736   data_vector_[0]->RunFor(3);
737   EXPECT_EQ(OK, second_one_callback.WaitForResult());
738   data_vector_[0]->StopAfter(100);
739   ExpectResponse("second-pipeline-one.html", second_one_transaction,
740                  SYNCHRONOUS);
741   EXPECT_EQ(OK, second_two_callback.WaitForResult());
742   ExpectResponse("second-pipeline-two.html", second_two_transaction,
743                  SYNCHRONOUS);
744
745   ClientSocketPoolManager::set_max_sockets_per_group(
746       HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_sockets);
747 }
748
749 class DataRunnerObserver : public base::MessageLoop::TaskObserver {
750  public:
751   DataRunnerObserver(DeterministicSocketData* data, int run_before_task)
752       : data_(data),
753         run_before_task_(run_before_task),
754         current_task_(0) { }
755
756   virtual void WillProcessTask(const base::PendingTask& pending_task) OVERRIDE {
757     ++current_task_;
758     if (current_task_ == run_before_task_) {
759       data_->Run();
760       base::MessageLoop::current()->RemoveTaskObserver(this);
761     }
762   }
763
764   virtual void DidProcessTask(const base::PendingTask& pending_task) OVERRIDE {}
765
766  private:
767   DeterministicSocketData* data_;
768   int run_before_task_;
769   int current_task_;
770 };
771
772 TEST_F(HttpPipelinedNetworkTransactionTest, OpenPipelinesWhileBinding) {
773   // There was a racy crash in the pipelining code. This test recreates that
774   // race. The steps are:
775   // 1. The first request starts a pipeline and requests headers.
776   // 2. HttpStreamFactoryImpl::Job tries to bind a pending request to a new
777   // pipeline and queues a task to do so.
778   // 3. Before that task runs, the first request receives its headers and
779   // determines this host is probably capable of pipelining.
780   // 4. All of the hosts' pipelines are notified they have capacity in a loop.
781   // 5. On the first iteration, the first pipeline is opened up to accept new
782   // requests and steals the request from step #2.
783   // 6. The pipeline from #2 is deleted because it has no streams.
784   // 7. On the second iteration, the host tries to notify the pipeline from step
785   // #2 that it has capacity. This is a use-after-free.
786   Initialize(false);
787
788   MockWrite writes[] = {
789     MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n"
790               "Host: localhost\r\n"
791               "Connection: keep-alive\r\n\r\n"),
792     MockWrite(ASYNC, 3, "GET /two.html HTTP/1.1\r\n"
793               "Host: localhost\r\n"
794               "Connection: keep-alive\r\n\r\n"),
795   };
796   MockRead reads[] = {
797     MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"),
798     MockRead(ASYNC, 2, "Content-Length: 8\r\n\r\n"),
799     MockRead(SYNCHRONOUS, 4, "one.html"),
800     MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"),
801     MockRead(SYNCHRONOUS, 6, "Content-Length: 8\r\n\r\n"),
802     MockRead(SYNCHRONOUS, 7, "two.html"),
803   };
804   AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
805
806   AddExpectedConnection(NULL, 0, NULL, 0);
807
808   HttpNetworkTransaction one_transaction(DEFAULT_PRIORITY, session_.get());
809   TestCompletionCallback one_callback;
810   EXPECT_EQ(ERR_IO_PENDING,
811             one_transaction.Start(GetRequestInfo("one.html"),
812                                   one_callback.callback(), BoundNetLog()));
813
814   data_vector_[0]->SetStop(2);
815   data_vector_[0]->Run();
816
817   HttpNetworkTransaction two_transaction(DEFAULT_PRIORITY, session_.get());
818   TestCompletionCallback two_callback;
819   EXPECT_EQ(ERR_IO_PENDING,
820             two_transaction.Start(GetRequestInfo("two.html"),
821                                   two_callback.callback(), BoundNetLog()));
822   // Posted tasks should be:
823   // 1. MockHostResolverBase::ResolveNow
824   // 2. HttpStreamFactoryImpl::Job::OnStreamReadyCallback for job 1
825   // 3. HttpStreamFactoryImpl::Job::OnStreamReadyCallback for job 2
826   //
827   // We need to make sure that the response that triggers OnPipelineFeedback(OK)
828   // is called in between when task #3 is scheduled and when it runs. The
829   // DataRunnerObserver does that.
830   DataRunnerObserver observer(data_vector_[0], 3);
831   base::MessageLoop::current()->AddTaskObserver(&observer);
832   data_vector_[0]->SetStop(4);
833   base::MessageLoop::current()->RunUntilIdle();
834   data_vector_[0]->SetStop(10);
835
836   EXPECT_EQ(OK, one_callback.WaitForResult());
837   ExpectResponse("one.html", one_transaction, SYNCHRONOUS);
838   EXPECT_EQ(OK, two_callback.WaitForResult());
839   ExpectResponse("two.html", two_transaction, SYNCHRONOUS);
840 }
841
842 TEST_F(HttpPipelinedNetworkTransactionTest, ProxyChangesWhileConnecting) {
843   Initialize(false);
844
845   DeterministicSocketData data(NULL, 0, NULL, 0);
846   data.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
847   factory_.AddSocketDataProvider(&data);
848
849   DeterministicSocketData data2(NULL, 0, NULL, 0);
850   data2.set_connect_data(MockConnect(ASYNC, ERR_FAILED));
851   factory_.AddSocketDataProvider(&data2);
852
853   HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session_.get());
854   EXPECT_EQ(ERR_IO_PENDING,
855             transaction.Start(GetRequestInfo("test.html"), callback_.callback(),
856                               BoundNetLog()));
857
858   proxy_config_service_->IncrementConfigId();
859
860   EXPECT_EQ(ERR_FAILED, callback_.WaitForResult());
861 }
862
863 TEST_F(HttpPipelinedNetworkTransactionTest, ForcedPipelineSharesConnection) {
864   Initialize(true);
865
866   MockWrite writes[] = {
867     MockWrite(ASYNC, 0, "GET /one.html HTTP/1.1\r\n"
868               "Host: localhost\r\n"
869               "Connection: keep-alive\r\n\r\n"
870               "GET /two.html HTTP/1.1\r\n"
871               "Host: localhost\r\n"
872               "Connection: keep-alive\r\n\r\n"),
873   };
874   MockRead reads[] = {
875     MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n"),
876     MockRead(ASYNC, 2, "Content-Length: 8\r\n\r\n"),
877     MockRead(ASYNC, 3, "one.html"),
878     MockRead(ASYNC, 4, "HTTP/1.1 200 OK\r\n"),
879     MockRead(ASYNC, 5, "Content-Length: 8\r\n\r\n"),
880     MockRead(ASYNC, 6, "two.html"),
881   };
882   AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
883
884   scoped_ptr<HttpNetworkTransaction> one_transaction(
885       new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
886   TestCompletionCallback one_callback;
887   EXPECT_EQ(ERR_IO_PENDING,
888             one_transaction->Start(GetRequestInfo("one.html"),
889                                    one_callback.callback(), BoundNetLog()));
890
891   HttpNetworkTransaction two_transaction(DEFAULT_PRIORITY, session_.get());
892   TestCompletionCallback two_callback;
893   EXPECT_EQ(ERR_IO_PENDING,
894             two_transaction.Start(GetRequestInfo("two.html"),
895                                   two_callback.callback(), BoundNetLog()));
896
897   data_vector_[0]->RunFor(3);  // Send + 2 lines of headers.
898   EXPECT_EQ(OK, one_callback.WaitForResult());
899   ExpectResponse("one.html", *one_transaction.get(), ASYNC);
900   one_transaction.reset();
901
902   data_vector_[0]->RunFor(2);  // 2 lines of headers.
903   EXPECT_EQ(OK, two_callback.WaitForResult());
904   ExpectResponse("two.html", two_transaction, ASYNC);
905 }
906
907 TEST_F(HttpPipelinedNetworkTransactionTest,
908        ForcedPipelineConnectionErrorFailsBoth) {
909   Initialize(true);
910
911   DeterministicSocketData data(NULL, 0, NULL, 0);
912   data.set_connect_data(MockConnect(ASYNC, ERR_FAILED));
913   factory_.AddSocketDataProvider(&data);
914
915   scoped_ptr<HttpNetworkTransaction> one_transaction(
916       new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
917   TestCompletionCallback one_callback;
918   EXPECT_EQ(ERR_IO_PENDING,
919             one_transaction->Start(GetRequestInfo("one.html"),
920                                    one_callback.callback(), BoundNetLog()));
921
922   HttpNetworkTransaction two_transaction(DEFAULT_PRIORITY, session_.get());
923   TestCompletionCallback two_callback;
924   EXPECT_EQ(ERR_IO_PENDING,
925             two_transaction.Start(GetRequestInfo("two.html"),
926                                   two_callback.callback(), BoundNetLog()));
927
928   data.Run();
929   EXPECT_EQ(ERR_FAILED, one_callback.WaitForResult());
930   EXPECT_EQ(ERR_FAILED, two_callback.WaitForResult());
931 }
932
933 TEST_F(HttpPipelinedNetworkTransactionTest, ForcedPipelineEvictionIsFatal) {
934   Initialize(true);
935
936   MockWrite writes[] = {
937     MockWrite(ASYNC, 0, "GET /one.html HTTP/1.1\r\n"
938               "Host: localhost\r\n"
939               "Connection: keep-alive\r\n\r\n"
940               "GET /two.html HTTP/1.1\r\n"
941               "Host: localhost\r\n"
942               "Connection: keep-alive\r\n\r\n"),
943   };
944   MockRead reads[] = {
945     MockRead(ASYNC, ERR_FAILED, 1),
946   };
947   AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
948
949   scoped_ptr<HttpNetworkTransaction> one_transaction(
950       new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
951   TestCompletionCallback one_callback;
952   EXPECT_EQ(ERR_IO_PENDING,
953             one_transaction->Start(GetRequestInfo("one.html"),
954                                    one_callback.callback(), BoundNetLog()));
955
956   HttpNetworkTransaction two_transaction(DEFAULT_PRIORITY, session_.get());
957   TestCompletionCallback two_callback;
958   EXPECT_EQ(ERR_IO_PENDING,
959             two_transaction.Start(GetRequestInfo("two.html"),
960                                   two_callback.callback(), BoundNetLog()));
961
962   data_vector_[0]->RunFor(2);
963   EXPECT_EQ(ERR_FAILED, one_callback.WaitForResult());
964   one_transaction.reset();
965   EXPECT_EQ(ERR_PIPELINE_EVICTION, two_callback.WaitForResult());
966 }
967
968 TEST_F(HttpPipelinedNetworkTransactionTest, ForcedPipelineOrder) {
969   Initialize(true);
970
971   MockWrite writes[] = {
972     MockWrite(ASYNC, 0,
973               "GET /one.html HTTP/1.1\r\n"
974               "Host: localhost\r\n"
975               "Connection: keep-alive\r\n\r\n"
976               "GET /two.html HTTP/1.1\r\n"
977               "Host: localhost\r\n"
978               "Connection: keep-alive\r\n\r\n"
979               "GET /three.html HTTP/1.1\r\n"
980               "Host: localhost\r\n"
981               "Connection: keep-alive\r\n\r\n"
982               "GET /four.html HTTP/1.1\r\n"
983               "Host: localhost\r\n"
984               "Connection: keep-alive\r\n\r\n"
985               ),
986   };
987   MockRead reads[] = {
988     MockRead(ASYNC, ERR_FAILED, 1),
989   };
990   DeterministicSocketData data(
991       reads, arraysize(reads), writes, arraysize(writes));
992   data.set_connect_data(MockConnect(ASYNC, OK));
993   factory_.AddSocketDataProvider(&data);
994
995   scoped_ptr<HttpNetworkTransaction> one_transaction(
996       new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
997   TestCompletionCallback one_callback;
998   EXPECT_EQ(ERR_IO_PENDING,
999             one_transaction->Start(GetRequestInfo("one.html"),
1000                                    one_callback.callback(), BoundNetLog()));
1001
1002   scoped_ptr<HttpNetworkTransaction> two_transaction(
1003       new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
1004   TestCompletionCallback two_callback;
1005   EXPECT_EQ(ERR_IO_PENDING,
1006             two_transaction->Start(GetRequestInfo("two.html"),
1007                                    two_callback.callback(), BoundNetLog()));
1008
1009   scoped_ptr<HttpNetworkTransaction> three_transaction(
1010       new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
1011   TestCompletionCallback three_callback;
1012   EXPECT_EQ(ERR_IO_PENDING,
1013             three_transaction->Start(GetRequestInfo("three.html"),
1014                                      three_callback.callback(), BoundNetLog()));
1015
1016   scoped_ptr<HttpNetworkTransaction> four_transaction(
1017       new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
1018   TestCompletionCallback four_callback;
1019   EXPECT_EQ(ERR_IO_PENDING,
1020             four_transaction->Start(GetRequestInfo("four.html"),
1021                                     four_callback.callback(), BoundNetLog()));
1022
1023   data.RunFor(3);
1024   EXPECT_EQ(ERR_FAILED, one_callback.WaitForResult());
1025   one_transaction.reset();
1026   EXPECT_EQ(ERR_PIPELINE_EVICTION, two_callback.WaitForResult());
1027   two_transaction.reset();
1028   EXPECT_EQ(ERR_PIPELINE_EVICTION, three_callback.WaitForResult());
1029   three_transaction.reset();
1030   EXPECT_EQ(ERR_PIPELINE_EVICTION, four_callback.WaitForResult());
1031 }
1032
1033 }  // anonymous namespace
1034
1035 }  // namespace net