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

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