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

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