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

Side by Side Diff: net/http/http_pipelined_network_transaction_unittest.cc

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

Powered by Google App Engine
This is Rietveld 408576698