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

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

Issue 8457002: Integration tests for HTTP pipelining. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Restore second read Created 9 years, 1 month 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
« no previous file with comments | « net/http/http_pipelined_connection_impl.cc ('k') | net/net.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 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_vector.h"
9 #include "base/stringprintf.h"
10 #include "base/utf_string_conversions.h"
11 #include "net/base/address_list.h"
12 #include "net/base/host_cache.h"
13 #include "net/base/io_buffer.h"
14 #include "net/base/mock_host_resolver.h"
15 #include "net/base/net_errors.h"
16 #include "net/base/net_util.h"
17 #include "net/base/request_priority.h"
18 #include "net/base/ssl_config_service_defaults.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_service.h"
25 #include "net/socket/client_socket_handle.h"
26 #include "net/socket/client_socket_pool_histograms.h"
27 #include "net/socket/socket_test_util.h"
28 #include "testing/gmock/include/gmock/gmock.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30
31 using testing::StrEq;
32
33 namespace net {
34
35 namespace {
36
37 class HttpPipelinedNetworkTransactionTest : public testing::Test {
38 public:
39 HttpPipelinedNetworkTransactionTest()
40 : histograms_("a"),
41 pool_(1, 1, &histograms_, &factory_) {
42 }
43
44 virtual void SetUp() OVERRIDE {
45 default_pipelining_enabled_ = HttpStreamFactory::http_pipelining_enabled();
46 HttpStreamFactory::set_http_pipelining_enabled(true);
47 }
48
49 virtual void TearDown() OVERRIDE {
50 MessageLoop::current()->RunAllPending();
51 HttpStreamFactory::set_http_pipelining_enabled(default_pipelining_enabled_);
52 }
53
54 void Initialize() {
55 proxy_service_.reset(ProxyService::CreateDirect());
56 ssl_config_ = new SSLConfigServiceDefaults;
57 auth_handler_factory_.reset(new HttpAuthHandlerMock::Factory());
58
59 HttpNetworkSession::Params session_params;
60 session_params.client_socket_factory = &factory_;
61 session_params.proxy_service = proxy_service_.get();
62 session_params.host_resolver = &mock_resolver_;
63 session_params.ssl_config_service = ssl_config_.get();
64 session_params.http_auth_handler_factory = auth_handler_factory_.get();
65 session_params.http_server_properties = &http_server_properties_;
66 session_ = new HttpNetworkSession(session_params);
67 }
68
69 void AddExpectedConnection(MockRead* reads, size_t reads_count,
70 MockWrite* writes, size_t writes_count) {
71 DeterministicSocketData* data = new DeterministicSocketData(
72 reads, reads_count, writes, writes_count);
73 data->set_connect_data(MockConnect(false, 0));
74 if (reads_count || writes_count) {
75 data->StopAfter(reads_count + writes_count);
76 }
77 factory_.AddSocketDataProvider(data);
78 data_vector_.push_back(data);
79 }
80
81 const HttpRequestInfo* GetRequestInfo(const char* filename) {
82 std::string url = StringPrintf("http://localhost/%s", filename);
83 HttpRequestInfo* request_info = new HttpRequestInfo;
84 request_info->url = GURL(url);
85 request_info->method = "GET";
86 request_info_vector_.push_back(request_info);
87 return request_info;
88 }
89
90 void ExpectResponse(const std::string& expected,
91 HttpNetworkTransaction& transaction) {
92 scoped_refptr<IOBuffer> buffer(new IOBuffer(expected.size()));
93 EXPECT_EQ(static_cast<int>(expected.size()),
94 transaction.Read(buffer.get(), expected.size(), &callback_));
95 std::string actual(buffer->data(), expected.size());
96 EXPECT_THAT(actual, StrEq(expected));
97 EXPECT_EQ(OK, transaction.Read(buffer.get(), expected.size(), &callback_));
98 }
99
100 void CompleteTwoRequests() {
101 scoped_ptr<HttpNetworkTransaction> one_transaction(
102 new HttpNetworkTransaction(session_.get()));
103 TestOldCompletionCallback one_callback;
104 EXPECT_EQ(ERR_IO_PENDING,
105 one_transaction->Start(GetRequestInfo("one.html"), &one_callback,
106 BoundNetLog()));
107 EXPECT_EQ(OK, one_callback.WaitForResult());
108
109 HttpNetworkTransaction two_transaction(session_.get());
110 TestOldCompletionCallback two_callback;
111 EXPECT_EQ(ERR_IO_PENDING,
112 two_transaction.Start(GetRequestInfo("two.html"), &two_callback,
113 BoundNetLog()));
114
115 TestOldCompletionCallback one_read_callback;
116 scoped_refptr<IOBuffer> buffer(new IOBuffer(8));
117 EXPECT_EQ(ERR_IO_PENDING,
118 one_transaction->Read(buffer.get(), 8, &one_read_callback));
119
120 data_vector_[0]->RunFor(2);
121 EXPECT_EQ(8, one_read_callback.WaitForResult());
122 data_vector_[0]->SetStop(10);
123 std::string actual(buffer->data(), 8);
124 EXPECT_THAT(actual, StrEq("one.html"));
125 EXPECT_EQ(OK, one_transaction->Read(buffer.get(), 8, &one_read_callback));
126
127 EXPECT_EQ(OK, two_callback.WaitForResult());
128 ExpectResponse("two.html", two_transaction);
129 }
130
131 DeterministicMockClientSocketFactory factory_;
132 ClientSocketPoolHistograms histograms_;
133 MockTransportClientSocketPool pool_;
134 std::vector<scoped_refptr<DeterministicSocketData> > data_vector_;
135 TestOldCompletionCallback callback_;
136 ScopedVector<HttpRequestInfo> request_info_vector_;
137 bool default_pipelining_enabled_;
138
139 scoped_ptr<ProxyService> proxy_service_;
140 MockHostResolver mock_resolver_;
141 scoped_refptr<SSLConfigService> ssl_config_;
142 scoped_ptr<HttpAuthHandlerMock::Factory> auth_handler_factory_;
143 HttpServerPropertiesImpl http_server_properties_;
144 scoped_refptr<HttpNetworkSession> session_;
145 };
146
147 TEST_F(HttpPipelinedNetworkTransactionTest, OneRequest) {
148 Initialize();
149
150 MockWrite writes[] = {
151 MockWrite(false, 0, "GET /test.html HTTP/1.1\r\n"
152 "Host: localhost\r\n"
153 "Connection: keep-alive\r\n\r\n"),
154 };
155 MockRead reads[] = {
156 MockRead(false, 1, "HTTP/1.1 200 OK\r\n"),
157 MockRead(false, 2, "Content-Length: 9\r\n\r\n"),
158 MockRead(false, 3, "test.html"),
159 };
160 AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
161
162 HttpNetworkTransaction transaction(session_.get());
163 EXPECT_EQ(ERR_IO_PENDING,
164 transaction.Start(GetRequestInfo("test.html"), &callback_,
165 BoundNetLog()));
166 EXPECT_EQ(OK, callback_.WaitForResult());
167 ExpectResponse("test.html", transaction);
168 }
169
170 TEST_F(HttpPipelinedNetworkTransactionTest, ReusePipeline) {
171 Initialize();
172
173 MockWrite writes[] = {
174 MockWrite(false, 0, "GET /one.html HTTP/1.1\r\n"
175 "Host: localhost\r\n"
176 "Connection: keep-alive\r\n\r\n"),
177 MockWrite(false, 3, "GET /two.html HTTP/1.1\r\n"
178 "Host: localhost\r\n"
179 "Connection: keep-alive\r\n\r\n"),
180 };
181 MockRead reads[] = {
182 MockRead(false, 1, "HTTP/1.1 200 OK\r\n"),
183 MockRead(false, 2, "Content-Length: 8\r\n\r\n"),
184 MockRead(true, 4, "one.html"),
185 MockRead(false, 5, "HTTP/1.1 200 OK\r\n"),
186 MockRead(false, 6, "Content-Length: 8\r\n\r\n"),
187 MockRead(false, 7, "two.html"),
188 };
189 AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
190
191 CompleteTwoRequests();
192 }
193
194 TEST_F(HttpPipelinedNetworkTransactionTest, ReusesOnSpaceAvailable) {
195 int old_max_sockets = ClientSocketPoolManager::max_sockets_per_group();
196 ClientSocketPoolManager::set_max_sockets_per_group(1);
197 Initialize();
198
199 MockWrite writes[] = {
200 MockWrite(false, 0, "GET /one.html HTTP/1.1\r\n"
201 "Host: localhost\r\n"
202 "Connection: keep-alive\r\n\r\n"),
203 MockWrite(false, 4, "GET /two.html HTTP/1.1\r\n"
204 "Host: localhost\r\n"
205 "Connection: keep-alive\r\n\r\n"),
206 MockWrite(false, 7, "GET /three.html HTTP/1.1\r\n"
207 "Host: localhost\r\n"
208 "Connection: keep-alive\r\n\r\n"),
209 MockWrite(false, 12, "GET /four.html HTTP/1.1\r\n"
210 "Host: localhost\r\n"
211 "Connection: keep-alive\r\n\r\n"),
212 };
213 MockRead reads[] = {
214 MockRead(false, 1, "HTTP/1.1 200 OK\r\n"),
215 MockRead(false, 2, "Content-Length: 8\r\n\r\n"),
216 MockRead(false, 3, "one.html"),
217 MockRead(false, 5, "HTTP/1.1 200 OK\r\n"),
218 MockRead(false, 6, "Content-Length: 8\r\n\r\n"),
219 MockRead(false, 8, "two.html"),
220 MockRead(false, 9, "HTTP/1.1 200 OK\r\n"),
221 MockRead(false, 10, "Content-Length: 10\r\n\r\n"),
222 MockRead(false, 11, "three.html"),
223 MockRead(false, 13, "HTTP/1.1 200 OK\r\n"),
224 MockRead(false, 14, "Content-Length: 9\r\n\r\n"),
225 MockRead(false, 15, "four.html"),
226 };
227 AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
228
229 scoped_ptr<HttpNetworkTransaction> one_transaction(
230 new HttpNetworkTransaction(session_.get()));
231 TestOldCompletionCallback one_callback;
232 EXPECT_EQ(ERR_IO_PENDING,
233 one_transaction->Start(GetRequestInfo("one.html"), &one_callback,
234 BoundNetLog()));
235 EXPECT_EQ(OK, one_callback.WaitForResult());
236
237 HttpNetworkTransaction two_transaction(session_.get());
238 TestOldCompletionCallback two_callback;
239 EXPECT_EQ(ERR_IO_PENDING,
240 two_transaction.Start(GetRequestInfo("two.html"), &two_callback,
241 BoundNetLog()));
242
243 HttpNetworkTransaction three_transaction(session_.get());
244 TestOldCompletionCallback three_callback;
245 EXPECT_EQ(ERR_IO_PENDING,
246 three_transaction.Start(GetRequestInfo("three.html"),
247 &three_callback, BoundNetLog()));
248
249 HttpNetworkTransaction four_transaction(session_.get());
250 TestOldCompletionCallback four_callback;
251 EXPECT_EQ(ERR_IO_PENDING,
252 four_transaction.Start(GetRequestInfo("four.html"), &four_callback,
253 BoundNetLog()));
254
255 ExpectResponse("one.html", *one_transaction.get());
256 EXPECT_EQ(OK, two_callback.WaitForResult());
257 ExpectResponse("two.html", two_transaction);
258 EXPECT_EQ(OK, three_callback.WaitForResult());
259 ExpectResponse("three.html", three_transaction);
260
261 one_transaction.reset();
262 EXPECT_EQ(OK, four_callback.WaitForResult());
263 ExpectResponse("four.html", four_transaction);
264
265 ClientSocketPoolManager::set_max_sockets_per_group(old_max_sockets);
266 }
267
268 TEST_F(HttpPipelinedNetworkTransactionTest, UnknownSizeEvictsToNewPipeline) {
269 Initialize();
270
271 MockWrite writes[] = {
272 MockWrite(false, 0, "GET /one.html HTTP/1.1\r\n"
273 "Host: localhost\r\n"
274 "Connection: keep-alive\r\n\r\n"),
275 MockWrite(false, 2, "GET /two.html HTTP/1.1\r\n"
276 "Host: localhost\r\n"
277 "Connection: keep-alive\r\n\r\n"),
278 };
279 MockRead reads[] = {
280 MockRead(false, 1, "HTTP/1.1 200 OK\r\n\r\n"),
281 MockRead(true, 3, "one.html"),
282 MockRead(false, OK, 4),
283 };
284 AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
285
286 MockWrite writes2[] = {
287 MockWrite(false, 0, "GET /two.html HTTP/1.1\r\n"
288 "Host: localhost\r\n"
289 "Connection: keep-alive\r\n\r\n"),
290 };
291 MockRead reads2[] = {
292 MockRead(false, 1, "HTTP/1.1 200 OK\r\n"),
293 MockRead(false, 2, "Content-Length: 8\r\n\r\n"),
294 MockRead(false, 3, "two.html"),
295 };
296 AddExpectedConnection(reads2, arraysize(reads2), writes2, arraysize(writes2));
297
298 CompleteTwoRequests();
299 }
300
301 TEST_F(HttpPipelinedNetworkTransactionTest, ConnectionCloseEvictToNewPipeline) {
302 Initialize();
303
304 MockWrite writes[] = {
305 MockWrite(false, 0, "GET /one.html HTTP/1.1\r\n"
306 "Host: localhost\r\n"
307 "Connection: keep-alive\r\n\r\n"),
308 MockWrite(false, 3, "GET /two.html HTTP/1.1\r\n"
309 "Host: localhost\r\n"
310 "Connection: keep-alive\r\n\r\n"),
311 };
312 MockRead reads[] = {
313 MockRead(false, 1, "HTTP/1.1 200 OK\r\n"),
314 MockRead(false, 2, "Content-Length: 8\r\n\r\n"),
315 MockRead(true, 4, "one.html"),
316 MockRead(false, ERR_SOCKET_NOT_CONNECTED, 5),
317 };
318 AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
319
320 MockWrite writes2[] = {
321 MockWrite(false, 0, "GET /two.html HTTP/1.1\r\n"
322 "Host: localhost\r\n"
323 "Connection: keep-alive\r\n\r\n"),
324 };
325 MockRead reads2[] = {
326 MockRead(false, 1, "HTTP/1.1 200 OK\r\n"),
327 MockRead(false, 2, "Content-Length: 8\r\n\r\n"),
328 MockRead(false, 3, "two.html"),
329 };
330 AddExpectedConnection(reads2, arraysize(reads2), writes2, arraysize(writes2));
331
332 CompleteTwoRequests();
333 }
334
335 TEST_F(HttpPipelinedNetworkTransactionTest, ErrorEvictsToNewPipeline) {
336 Initialize();
337
338 MockWrite writes[] = {
339 MockWrite(false, 0, "GET /one.html HTTP/1.1\r\n"
340 "Host: localhost\r\n"
341 "Connection: keep-alive\r\n\r\n"),
342 MockWrite(false, 3, "GET /two.html HTTP/1.1\r\n"
343 "Host: localhost\r\n"
344 "Connection: keep-alive\r\n\r\n"),
345 };
346 MockRead reads[] = {
347 MockRead(false, 1, "HTTP/1.1 200 OK\r\n\r\n"),
348 MockRead(false, ERR_FAILED, 2),
349 };
350 AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
351
352 MockWrite writes2[] = {
353 MockWrite(false, 0, "GET /two.html HTTP/1.1\r\n"
354 "Host: localhost\r\n"
355 "Connection: keep-alive\r\n\r\n"),
356 };
357 MockRead reads2[] = {
358 MockRead(false, 1, "HTTP/1.1 200 OK\r\n"),
359 MockRead(false, 2, "Content-Length: 8\r\n\r\n"),
360 MockRead(false, 3, "two.html"),
361 };
362 AddExpectedConnection(reads2, arraysize(reads2), writes2, arraysize(writes2));
363
364 HttpNetworkTransaction one_transaction(session_.get());
365 TestOldCompletionCallback one_callback;
366 EXPECT_EQ(ERR_IO_PENDING,
367 one_transaction.Start(GetRequestInfo("one.html"), &one_callback,
368 BoundNetLog()));
369 EXPECT_EQ(OK, one_callback.WaitForResult());
370
371 HttpNetworkTransaction two_transaction(session_.get());
372 TestOldCompletionCallback two_callback;
373 EXPECT_EQ(ERR_IO_PENDING,
374 two_transaction.Start(GetRequestInfo("two.html"), &two_callback,
375 BoundNetLog()));
376
377 scoped_refptr<IOBuffer> buffer(new IOBuffer(1));
378 EXPECT_EQ(ERR_FAILED, one_transaction.Read(buffer.get(), 1, &callback_));
379 EXPECT_EQ(OK, two_callback.WaitForResult());
380 ExpectResponse("two.html", two_transaction);
381 }
382
383 TEST_F(HttpPipelinedNetworkTransactionTest, SendErrorEvictsToNewPipeline) {
384 Initialize();
385
386 MockWrite writes[] = {
387 MockWrite(true, ERR_FAILED, 0),
388 };
389 AddExpectedConnection(NULL, 0, writes, arraysize(writes));
390
391 MockWrite writes2[] = {
392 MockWrite(false, 0, "GET /two.html HTTP/1.1\r\n"
393 "Host: localhost\r\n"
394 "Connection: keep-alive\r\n\r\n"),
395 };
396 MockRead reads2[] = {
397 MockRead(false, 1, "HTTP/1.1 200 OK\r\n"),
398 MockRead(false, 2, "Content-Length: 8\r\n\r\n"),
399 MockRead(false, 3, "two.html"),
400 };
401 AddExpectedConnection(reads2, arraysize(reads2), writes2, arraysize(writes2));
402
403 HttpNetworkTransaction one_transaction(session_.get());
404 TestOldCompletionCallback one_callback;
405 EXPECT_EQ(ERR_IO_PENDING,
406 one_transaction.Start(GetRequestInfo("one.html"), &one_callback,
407 BoundNetLog()));
408
409 HttpNetworkTransaction two_transaction(session_.get());
410 TestOldCompletionCallback two_callback;
411 EXPECT_EQ(ERR_IO_PENDING,
412 two_transaction.Start(GetRequestInfo("two.html"), &two_callback,
413 BoundNetLog()));
414
415 data_vector_[0]->RunFor(1);
416 EXPECT_EQ(ERR_FAILED, one_callback.WaitForResult());
417
418 EXPECT_EQ(OK, two_callback.WaitForResult());
419 ExpectResponse("two.html", two_transaction);
420 }
421
422 TEST_F(HttpPipelinedNetworkTransactionTest, BasicHttpAuthentication) {
423 Initialize();
424
425 MockWrite writes[] = {
426 MockWrite(false, 0, "GET /one.html HTTP/1.1\r\n"
427 "Host: localhost\r\n"
428 "Connection: keep-alive\r\n\r\n"),
429 MockWrite(false, 5, "GET /one.html HTTP/1.1\r\n"
430 "Host: localhost\r\n"
431 "Connection: keep-alive\r\n"
432 "Authorization: auth_token\r\n\r\n"),
433 };
434 MockRead reads[] = {
435 MockRead(false, 1, "HTTP/1.1 401 Authentication Required\r\n"),
436 MockRead(false, 2, "WWW-Authenticate: Basic realm=\"Secure Area\"\r\n"),
437 MockRead(false, 3, "Content-Length: 20\r\n\r\n"),
438 MockRead(false, 4, "needs authentication"),
439 MockRead(false, 6, "HTTP/1.1 200 OK\r\n"),
440 MockRead(false, 7, "Content-Length: 8\r\n\r\n"),
441 MockRead(false, 8, "one.html"),
442 };
443 AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
444
445 HttpAuthHandlerMock* mock_auth = new HttpAuthHandlerMock;
446 std::string challenge_text = "Basic";
447 HttpAuth::ChallengeTokenizer challenge(challenge_text.begin(),
448 challenge_text.end());
449 GURL origin("localhost");
450 EXPECT_TRUE(mock_auth->InitFromChallenge(&challenge,
451 HttpAuth::AUTH_SERVER,
452 origin,
453 BoundNetLog()));
454 auth_handler_factory_->AddMockHandler(mock_auth, HttpAuth::AUTH_SERVER);
455
456 HttpNetworkTransaction transaction(session_.get());
457 EXPECT_EQ(
458 ERR_IO_PENDING,
459 transaction.Start(GetRequestInfo("one.html"), &callback_, BoundNetLog()));
460 EXPECT_EQ(OK, callback_.WaitForResult());
461
462 AuthCredentials credentials(ASCIIToUTF16("user"), ASCIIToUTF16("pass"));
463 EXPECT_EQ(OK, transaction.RestartWithAuth(credentials, &callback_));
464
465 ExpectResponse("one.html", transaction);
466 }
467
468 } // anonymous namespace
469
470 } // namespace net
OLDNEW
« no previous file with comments | « net/http/http_pipelined_connection_impl.cc ('k') | net/net.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698