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

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: Added additional tests 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/host_resolver_impl.h"
14 #include "net/base/host_resolver_proc.h"
15 #include "net/base/io_buffer.h"
16 #include "net/base/net_errors.h"
17 #include "net/base/net_util.h"
18 #include "net/base/request_priority.h"
19 #include "net/base/ssl_config_service_defaults.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.h"
25 #include "net/proxy/proxy_service.h"
26 #include "net/socket/client_socket_handle.h"
27 #include "net/socket/client_socket_pool_histograms.h"
28 #include "net/socket/socket_test_util.h"
29 #include "testing/gmock/include/gmock/gmock.h"
30 #include "testing/gtest/include/gtest/gtest.h"
31
32 using testing::StrEq;
33
34 namespace net {
35
36 class DummySocketParams : public base::RefCounted<DummySocketParams> {
37 private:
38 friend class base::RefCounted<DummySocketParams>;
39 };
40
41 REGISTER_SOCKET_PARAMS_FOR_POOL(MockTransportClientSocketPool,
42 DummySocketParams);
43
44 class DummyHttpServerProperties : public HttpServerProperties {
mmenke 2011/11/07 16:53:46 I don't think this class is necessary. We should
James Simonsen 2011/11/07 20:30:29 Done.
45 public:
46 virtual void Clear() OVERRIDE { }
47 virtual bool SupportsSpdy(const HostPortPair& server) const OVERRIDE {
48 return false;
49 }
50 virtual void SetSupportsSpdy(const HostPortPair& server,
51 bool support_spdy) OVERRIDE { }
52 virtual bool HasAlternateProtocol(const HostPortPair& server) const OVERRIDE {
53 return false;
54 }
55 virtual PortAlternateProtocolPair GetAlternateProtocol(
56 const HostPortPair& server) const OVERRIDE {
57 return PortAlternateProtocolPair();
58 }
59 virtual void SetAlternateProtocol(
60 const HostPortPair& server, uint16 alternate_port,
61 AlternateProtocol alternate_protocol) OVERRIDE { }
62 virtual void SetBrokenAlternateProtocol(
63 const HostPortPair& server) OVERRIDE { }
64 virtual const AlternateProtocolMap& alternate_protocol_map() const OVERRIDE {
65 return alternate_protocol_map_;
66 }
67 private:
68 AlternateProtocolMap alternate_protocol_map_;
69 };
70
71 class DummyHostResolverProc : public HostResolverProc {
mmenke 2011/11/07 16:53:46 I don't think this class is needed, either. We sh
James Simonsen 2011/11/07 20:30:29 Done.
72 public:
73 DummyHostResolverProc() : HostResolverProc(NULL) { }
74 virtual int Resolve(const std::string& host,
75 AddressFamily address_family,
76 HostResolverFlags host_resolver_flags,
77 AddressList* addrlist,
78 int* os_error) OVERRIDE {
79 IPAddressNumber address;
80 address.push_back(0127);
81 address.push_back(00);
82 address.push_back(00);
83 address.push_back(01);
84 *addrlist = AddressList::CreateFromIPAddress(address, 123);
85 return OK;
86 }
87 };
88
89 class HttpPipelinedNetworkTransactionTest : public testing::Test {
90 public:
91 HttpPipelinedNetworkTransactionTest()
92 : histograms_("a"),
93 pool_(1, 1, &histograms_, &factory_) {
94 }
95
96 void SetUp() {
mmenke 2011/11/07 16:53:46 virtual/OVERRIDE for this, and the next one, too.
James Simonsen 2011/11/07 20:30:29 Done.
97 HttpStreamFactory::set_http_pipelining_enabled(true);
98 }
99
100 void TearDown() {
101 MessageLoop::current()->RunAllPending();
102 }
103
104 void Initialize() {
mmenke 2011/11/07 16:53:46 Any reason not to do this in SetUp? It's called o
James Simonsen 2011/11/07 20:30:29 It's the ReusesOnSpaceAvailable test that screws i
mmenke 2011/11/08 18:12:41 You could just have a function to create the sessi
105 HttpNetworkSession::Params session_params;
106 session_params.client_socket_factory = &factory_;
107 session_params.proxy_service = ProxyService::CreateDirect();
108 session_params.host_resolver = new HostResolverImpl(
mmenke 2011/11/07 16:53:46 None of these will be owned by the HttpNetworkSess
James Simonsen 2011/11/07 20:30:29 Bah. I even ran valgrind ahead of time, but leak c
109 new DummyHostResolverProc, HostCache::CreateDefaultCache(), 1, 1, NULL);
110 session_params.ssl_config_service = new SSLConfigServiceDefaults;
111 session_params.http_auth_handler_factory = auth_handler_factory_ =
112 new HttpAuthHandlerMock::Factory();
113 session_params.http_server_properties = new DummyHttpServerProperties;
114 session_ = new HttpNetworkSession(session_params);
115 }
116
117 void AddExpectedConnection(MockRead* reads, size_t reads_count,
118 MockWrite* writes, size_t writes_count) {
119 DeterministicSocketData* data = new DeterministicSocketData(
120 reads, reads_count, writes, writes_count);
121 data->set_connect_data(MockConnect(false, 0));
122 if (reads_count || writes_count) {
123 data->StopAfter(reads_count + writes_count);
124 }
125 factory_.AddSocketDataProvider(data);
126 data_vector_.push_back(data);
127 }
128
129 const HttpRequestInfo* GetRequestInfo(const char* filename) {
130 std::string url = StringPrintf("http://localhost/%s", filename);
131 HttpRequestInfo* request_info = new HttpRequestInfo;
132 request_info->url = GURL(url);
133 request_info->method = "GET";
134 request_info_vector_.push_back(request_info);
135 return request_info;
136 }
137
138 void ExpectResponse(const std::string& expected,
139 HttpNetworkTransaction& transaction) {
140 scoped_refptr<IOBuffer> buffer(new IOBuffer(expected.size()));
141 EXPECT_EQ(static_cast<int>(expected.size()),
142 transaction.Read(buffer.get(), expected.size(), &callback_));
143 std::string actual(buffer->data(), expected.size());
144 EXPECT_THAT(actual, StrEq(expected));
145 EXPECT_EQ(OK, transaction.Read(buffer.get(), expected.size(), &callback_));
146 }
147
148 void PipelineTwoRequests() {
mmenke 2011/11/07 16:53:46 nit: CompleteTwoRequests, maybe? They're not exa
James Simonsen 2011/11/07 20:30:29 Done.
149 HttpNetworkTransaction one_transaction(session_.get());
150 TestOldCompletionCallback one_callback;
151 EXPECT_EQ(ERR_IO_PENDING,
152 one_transaction.Start(GetRequestInfo("one.html"), &one_callback,
153 BoundNetLog()));
154 EXPECT_EQ(OK, one_callback.WaitForResult());
155
156 HttpNetworkTransaction two_transaction(session_.get());
157 TestOldCompletionCallback two_callback;
158 EXPECT_EQ(ERR_IO_PENDING,
159 two_transaction.Start(GetRequestInfo("two.html"), &two_callback,
160 BoundNetLog()));
161
162 ExpectResponse("one.html", one_transaction);
163 EXPECT_EQ(OK, two_callback.WaitForResult());
164 ExpectResponse("two.html", two_transaction);
165 }
166
167 DeterministicMockClientSocketFactory factory_;
168 ClientSocketPoolHistograms histograms_;
169 MockTransportClientSocketPool pool_;
170 std::vector<scoped_refptr<DeterministicSocketData> > data_vector_;
171 HttpAuthHandlerMock::Factory* auth_handler_factory_;
172 scoped_refptr<HttpNetworkSession> session_;
173
174 SSLConfig ssl_config_;
175 ProxyInfo proxy_info_;
176 TestOldCompletionCallback callback_;
177 ScopedVector<HttpRequestInfo> request_info_vector_;
178 };
179
180 TEST_F(HttpPipelinedNetworkTransactionTest, OneRequest) {
181 Initialize();
182
183 MockWrite writes[] = {
184 MockWrite(false, 0, "GET /test.html HTTP/1.1\r\n"
185 "Host: localhost\r\n"
186 "Connection: keep-alive\r\n\r\n"),
187 };
188 MockRead reads[] = {
189 MockRead(false, 1, "HTTP/1.1 200 OK\r\n"),
190 MockRead(false, 2, "Content-Length: 9\r\n\r\n"),
191 MockRead(false, 3, "test.html"),
192 };
193 AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
194
195 HttpNetworkTransaction transaction(session_.get());
196 EXPECT_EQ(ERR_IO_PENDING,
197 transaction.Start(GetRequestInfo("test.html"), &callback_,
198 BoundNetLog()));
199 EXPECT_EQ(OK, callback_.WaitForResult());
200 ExpectResponse("test.html", transaction);
201 }
202
203 TEST_F(HttpPipelinedNetworkTransactionTest, ReusePipeline) {
204 Initialize();
205
206 MockWrite writes[] = {
207 MockWrite(false, 0, "GET /one.html HTTP/1.1\r\n"
208 "Host: localhost\r\n"
209 "Connection: keep-alive\r\n\r\n"),
210 MockWrite(false, 4, "GET /two.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, 7, "two.html"),
221 };
222 AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
223
224 PipelineTwoRequests();
225 }
226
227 TEST_F(HttpPipelinedNetworkTransactionTest, ReusesOnSpaceAvailable) {
228 int old_max_sockets = ClientSocketPoolManager::max_sockets_per_group();
229 ClientSocketPoolManager::set_max_sockets_per_group(1);
230 Initialize();
231
232 MockWrite writes[] = {
233 MockWrite(false, 0, "GET /one.html HTTP/1.1\r\n"
234 "Host: localhost\r\n"
235 "Connection: keep-alive\r\n\r\n"),
236 MockWrite(false, 4, "GET /two.html HTTP/1.1\r\n"
237 "Host: localhost\r\n"
238 "Connection: keep-alive\r\n\r\n"),
239 MockWrite(false, 7, "GET /three.html HTTP/1.1\r\n"
240 "Host: localhost\r\n"
241 "Connection: keep-alive\r\n\r\n"),
242 MockWrite(false, 12, "GET /four.html HTTP/1.1\r\n"
243 "Host: localhost\r\n"
244 "Connection: keep-alive\r\n\r\n"),
245 };
246 MockRead reads[] = {
247 MockRead(false, 1, "HTTP/1.1 200 OK\r\n"),
248 MockRead(false, 2, "Content-Length: 8\r\n\r\n"),
249 MockRead(false, 3, "one.html"),
250 MockRead(false, 5, "HTTP/1.1 200 OK\r\n"),
251 MockRead(false, 6, "Content-Length: 8\r\n\r\n"),
252 MockRead(false, 8, "two.html"),
253 MockRead(false, 9, "HTTP/1.1 200 OK\r\n"),
254 MockRead(false, 10, "Content-Length: 10\r\n\r\n"),
255 MockRead(false, 11, "three.html"),
256 MockRead(false, 13, "HTTP/1.1 200 OK\r\n"),
257 MockRead(false, 14, "Content-Length: 9\r\n\r\n"),
258 MockRead(false, 15, "four.html"),
259 };
260 AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
261
262 scoped_ptr<HttpNetworkTransaction> one_transaction(
263 new HttpNetworkTransaction(session_.get()));
264 TestOldCompletionCallback one_callback;
265 EXPECT_EQ(ERR_IO_PENDING,
266 one_transaction->Start(GetRequestInfo("one.html"), &one_callback,
267 BoundNetLog()));
268 EXPECT_EQ(OK, one_callback.WaitForResult());
269
270 HttpNetworkTransaction two_transaction(session_.get());
271 TestOldCompletionCallback two_callback;
272 EXPECT_EQ(ERR_IO_PENDING,
273 two_transaction.Start(GetRequestInfo("two.html"), &two_callback,
274 BoundNetLog()));
275
276 HttpNetworkTransaction three_transaction(session_.get());
277 TestOldCompletionCallback three_callback;
278 EXPECT_EQ(ERR_IO_PENDING,
279 three_transaction.Start(GetRequestInfo("three.html"),
280 &three_callback, BoundNetLog()));
281
282 HttpNetworkTransaction four_transaction(session_.get());
283 TestOldCompletionCallback four_callback;
284 EXPECT_EQ(ERR_IO_PENDING,
285 four_transaction.Start(GetRequestInfo("four.html"), &four_callback,
286 BoundNetLog()));
287
288 ExpectResponse("one.html", *one_transaction.get());
289 EXPECT_EQ(OK, two_callback.WaitForResult());
290 ExpectResponse("two.html", two_transaction);
291 EXPECT_EQ(OK, three_callback.WaitForResult());
292 ExpectResponse("three.html", three_transaction);
293
294 one_transaction.reset();
295 EXPECT_EQ(OK, four_callback.WaitForResult());
296 ExpectResponse("four.html", four_transaction);
297
298 ClientSocketPoolManager::set_max_sockets_per_group(old_max_sockets);
299 }
300
301 TEST_F(HttpPipelinedNetworkTransactionTest, UnknownSizeEvictsToNewPipeline) {
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, 4, "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\r\n"),
314 MockRead(false, 2, "one.html"),
315 MockRead(false, OK, 3),
316 };
317 AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
318
319 MockWrite writes2[] = {
320 MockWrite(false, 0, "GET /two.html HTTP/1.1\r\n"
321 "Host: localhost\r\n"
322 "Connection: keep-alive\r\n\r\n"),
323 };
324 MockRead reads2[] = {
325 MockRead(false, 1, "HTTP/1.1 200 OK\r\n"),
326 MockRead(false, 2, "Content-Length: 8\r\n\r\n"),
327 MockRead(false, 3, "two.html"),
328 };
329 AddExpectedConnection(reads2, arraysize(reads2), writes2, arraysize(writes2));
330
331 PipelineTwoRequests();
332 }
333
334 TEST_F(HttpPipelinedNetworkTransactionTest, ConnectionCloseEvictToNewPipeline) {
335 Initialize();
336
337 MockWrite writes[] = {
338 MockWrite(false, 0, "GET /one.html HTTP/1.1\r\n"
339 "Host: localhost\r\n"
340 "Connection: keep-alive\r\n\r\n"),
341 MockWrite(false, 4, "GET /two.html HTTP/1.1\r\n"
342 "Host: localhost\r\n"
343 "Connection: keep-alive\r\n\r\n"),
344 };
345 MockRead reads[] = {
346 MockRead(false, 1, "HTTP/1.1 200 OK\r\n"),
347 MockRead(false, 2, "Content-Length: 8\r\n\r\n"),
348 MockRead(false, 3, "one.html"),
349 MockRead(false, ERR_SOCKET_NOT_CONNECTED, 5),
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 PipelineTwoRequests();
366 }
367
368 TEST_F(HttpPipelinedNetworkTransactionTest, ErrorEvictsToNewPipeline) {
369 Initialize();
370
371 MockWrite writes[] = {
372 MockWrite(false, 0, "GET /one.html HTTP/1.1\r\n"
373 "Host: localhost\r\n"
374 "Connection: keep-alive\r\n\r\n"),
375 MockWrite(false, 3, "GET /two.html HTTP/1.1\r\n"
376 "Host: localhost\r\n"
377 "Connection: keep-alive\r\n\r\n"),
378 };
379 MockRead reads[] = {
380 MockRead(false, 1, "HTTP/1.1 200 OK\r\n\r\n"),
381 MockRead(false, ERR_FAILED, 2),
382 };
383 AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
384
385 MockWrite writes2[] = {
386 MockWrite(false, 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(false, 1, "HTTP/1.1 200 OK\r\n"),
392 MockRead(false, 2, "Content-Length: 8\r\n\r\n"),
393 MockRead(false, 3, "two.html"),
394 };
395 AddExpectedConnection(reads2, arraysize(reads2), writes2, arraysize(writes2));
396
397 HttpNetworkTransaction one_transaction(session_.get());
398 TestOldCompletionCallback one_callback;
399 EXPECT_EQ(ERR_IO_PENDING,
400 one_transaction.Start(GetRequestInfo("one.html"), &one_callback,
401 BoundNetLog()));
402 EXPECT_EQ(OK, one_callback.WaitForResult());
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 scoped_refptr<IOBuffer> buffer(new IOBuffer(1));
411 EXPECT_EQ(ERR_FAILED, one_transaction.Read(buffer.get(), 1, &callback_));
412 EXPECT_EQ(OK, two_callback.WaitForResult());
413 ExpectResponse("two.html", two_transaction);
414 }
415
416 TEST_F(HttpPipelinedNetworkTransactionTest, SendErrorEvictsToNewPipeline) {
417 Initialize();
418
419 MockWrite writes[] = {
420 MockWrite(true, ERR_FAILED, 0),
421 };
422 AddExpectedConnection(NULL, 0, writes, arraysize(writes));
423
424 MockWrite writes2[] = {
425 MockWrite(false, 0, "GET /two.html HTTP/1.1\r\n"
426 "Host: localhost\r\n"
427 "Connection: keep-alive\r\n\r\n"),
428 };
429 MockRead reads2[] = {
430 MockRead(false, 1, "HTTP/1.1 200 OK\r\n"),
431 MockRead(false, 2, "Content-Length: 8\r\n\r\n"),
432 MockRead(false, 3, "two.html"),
433 };
434 AddExpectedConnection(reads2, arraysize(reads2), writes2, arraysize(writes2));
435
436 HttpNetworkTransaction one_transaction(session_.get());
437 TestOldCompletionCallback one_callback;
438 EXPECT_EQ(ERR_IO_PENDING,
439 one_transaction.Start(GetRequestInfo("one.html"), &one_callback,
440 BoundNetLog()));
441
442 HttpNetworkTransaction two_transaction(session_.get());
443 TestOldCompletionCallback two_callback;
444 EXPECT_EQ(ERR_IO_PENDING,
445 two_transaction.Start(GetRequestInfo("two.html"), &two_callback,
446 BoundNetLog()));
447
448 data_vector_[0]->RunFor(1);
449 EXPECT_EQ(ERR_FAILED, one_callback.WaitForResult());
450
451 EXPECT_EQ(OK, two_callback.WaitForResult());
452 ExpectResponse("two.html", two_transaction);
453 }
454
455 TEST_F(HttpPipelinedNetworkTransactionTest, BasicHttpAuthentication) {
456 Initialize();
457
458 MockWrite writes[] = {
459 MockWrite(false, 0, "GET /one.html HTTP/1.1\r\n"
460 "Host: localhost\r\n"
461 "Connection: keep-alive\r\n\r\n"),
462 MockWrite(false, 5, "GET /one.html HTTP/1.1\r\n"
463 "Host: localhost\r\n"
464 "Connection: keep-alive\r\n"
465 "Authorization: auth_token\r\n\r\n"),
466 };
467 MockRead reads[] = {
468 MockRead(false, 1, "HTTP/1.1 401 Authentication Required\r\n"),
469 MockRead(false, 2, "WWW-Authenticate: Basic realm=\"Secure Area\"\r\n"),
470 MockRead(false, 3, "Content-Length: 20\r\n\r\n"),
471 MockRead(false, 4, "needs authentication"),
472 MockRead(false, 6, "HTTP/1.1 200 OK\r\n"),
473 MockRead(false, 7, "Content-Length: 8\r\n\r\n"),
474 MockRead(false, 8, "one.html"),
475 };
476 AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
477
478 HttpAuthHandlerMock* mock_auth = new HttpAuthHandlerMock;
479 std::string challenge_text = "Basic";
480 HttpAuth::ChallengeTokenizer challenge(challenge_text.begin(),
481 challenge_text.end());
482 GURL origin("localhost");
483 EXPECT_TRUE(mock_auth->InitFromChallenge(&challenge,
484 HttpAuth::AUTH_SERVER,
485 origin,
486 BoundNetLog()));
487 auth_handler_factory_->AddMockHandler(mock_auth, HttpAuth::AUTH_SERVER);
488
489 HttpNetworkTransaction transaction(session_.get());
490 EXPECT_EQ(
491 ERR_IO_PENDING,
492 transaction.Start(GetRequestInfo("one.html"), &callback_, BoundNetLog()));
493 EXPECT_EQ(OK, callback_.WaitForResult());
494
495 AuthCredentials credentials(ASCIIToUTF16("user"), ASCIIToUTF16("pass"));
496 EXPECT_EQ(OK, transaction.RestartWithAuth(credentials, &callback_));
497
498 ExpectResponse("one.html", transaction);
499 }
500
501 } // 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