OLD | NEW |
---|---|
(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 "net/http/http_pipelined_connection_impl.h" | |
6 | |
7 #include <string> | |
mmenke
2011/08/23 19:05:25
nit: Add blank link.
James Simonsen
2011/08/26 22:19:07
Done.
| |
8 #include "base/memory/ref_counted.h" | |
9 #include "base/memory/scoped_vector.h" | |
10 #include "net/base/io_buffer.h" | |
11 #include "net/base/net_errors.h" | |
12 #include "net/base/request_priority.h" | |
13 #include "net/http/http_pipelined_stream.h" | |
14 #include "net/socket/client_socket_handle.h" | |
15 #include "net/socket/client_socket_pool_histograms.h" | |
16 #include "net/socket/socket_test_util.h" | |
17 #include "testing/gmock/include/gmock/gmock.h" | |
18 #include "testing/gtest/include/gtest/gtest.h" | |
19 | |
20 using testing::NiceMock; | |
21 using testing::Ref; | |
22 using testing::StrEq; | |
23 | |
24 namespace net { | |
25 | |
26 class DummySocketParams : public base::RefCounted<DummySocketParams> { | |
27 private: | |
28 friend class base::RefCounted<DummySocketParams>; | |
29 }; | |
30 | |
31 REGISTER_SOCKET_PARAMS_FOR_POOL(MockTransportClientSocketPool, | |
32 DummySocketParams); | |
33 | |
34 class MockPipelineOwner : public HttpPipelinedConnectionImpl::Owner { | |
35 public: | |
36 MOCK_METHOD1(OnPipelineHasCapacity, void(HttpPipelinedConnection* pipeline)); | |
37 }; | |
38 | |
39 class HttpPipelinedConnectionImplTest : public testing::Test { | |
40 public: | |
41 HttpPipelinedConnectionImplTest() | |
42 : histograms_("a"), | |
43 pool_(1, 1, &histograms_, &factory_) { | |
44 } | |
45 | |
46 void Initialize(MockRead* reads, size_t reads_count, | |
47 MockWrite* writes, size_t writes_count) { | |
48 data_ = new DeterministicSocketData(reads, reads_count, | |
49 writes, writes_count); | |
50 data_->set_connect_data(MockConnect(false, 0)); | |
51 if (reads_count || writes_count) { | |
52 data_->StopAfter(reads_count + writes_count); | |
53 } | |
54 factory_.AddSocketDataProvider(data_.get()); | |
55 scoped_refptr<DummySocketParams> params; | |
56 ClientSocketHandle* connection = new ClientSocketHandle; | |
57 connection->Init("a", params, MEDIUM, NULL, &pool_, BoundNetLog()); | |
58 pipeline_.reset(new HttpPipelinedConnectionImpl(connection, &owner_, | |
59 ssl_config_, proxy_info_, | |
60 BoundNetLog(), false)); | |
61 } | |
62 | |
63 HttpRequestInfo* GetRequestInfo(const std::string& filename) { | |
64 HttpRequestInfo* request_info = new HttpRequestInfo; | |
65 request_info->url = GURL("http://localhost/" + filename); | |
66 request_info->method = "GET"; | |
67 request_info_vector_.push_back(request_info); | |
68 return request_info; | |
69 } | |
70 | |
71 HttpStream* NewTestStream(const std::string& filename) { | |
72 HttpStream* stream = pipeline_->CreateNewStream(); | |
73 HttpRequestInfo* request_info = GetRequestInfo(filename); | |
74 int rv = stream->InitializeStream(request_info, BoundNetLog(), NULL); | |
75 DCHECK_EQ(OK, rv); | |
76 return stream; | |
77 } | |
78 | |
79 void ExpectResponse(const std::string& expected, | |
80 scoped_ptr<HttpStream>& stream, bool async) { | |
81 scoped_refptr<IOBuffer> buffer(new IOBuffer(expected.size())); | |
82 | |
83 if (async) { | |
84 EXPECT_EQ(ERR_IO_PENDING, | |
85 stream->ReadResponseBody(buffer.get(), expected.size(), | |
86 &callback_)); | |
87 data_->RunFor(1); | |
88 EXPECT_EQ(static_cast<int>(expected.size()), callback_.WaitForResult()); | |
89 } else { | |
90 EXPECT_EQ(static_cast<int>(expected.size()), | |
91 stream->ReadResponseBody(buffer.get(), expected.size(), | |
92 &callback_)); | |
93 } | |
94 std::string actual(buffer->data(), expected.size()); | |
95 EXPECT_THAT(actual, StrEq(expected)); | |
96 } | |
97 | |
98 void TestSyncRequest(scoped_ptr<HttpStream>& stream, | |
99 const std::string& filename) { | |
100 HttpRequestHeaders headers; | |
101 HttpResponseInfo response; | |
102 EXPECT_EQ(OK, stream->SendRequest(headers, NULL, &response, &callback_)); | |
103 EXPECT_EQ(OK, stream->ReadResponseHeaders(&callback_)); | |
104 ExpectResponse(filename, stream, false); | |
105 | |
106 stream->Close(false); | |
107 } | |
108 | |
109 DeterministicMockClientSocketFactory factory_; | |
110 ClientSocketPoolHistograms histograms_; | |
111 MockTransportClientSocketPool pool_; | |
112 scoped_refptr<DeterministicSocketData> data_; | |
113 | |
114 SSLConfig ssl_config_; | |
115 ProxyInfo proxy_info_; | |
116 NiceMock<MockPipelineOwner> owner_; | |
117 TestCompletionCallback callback_; | |
118 scoped_ptr<HttpPipelinedConnectionImpl> pipeline_; | |
119 ScopedVector<HttpRequestInfo> request_info_vector_; | |
120 }; | |
121 | |
122 TEST_F(HttpPipelinedConnectionImplTest, SyncSingleRequest) { | |
123 MockWrite writes[] = { | |
124 MockWrite(false, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
125 }; | |
126 MockRead reads[] = { | |
127 MockRead(false, 1, "HTTP/1.1 200 OK\r\n"), | |
128 MockRead(false, 2, "Content-Length: 7\r\n\r\n"), | |
129 MockRead(false, 3, "ok.html"), | |
130 }; | |
131 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
132 | |
133 scoped_ptr<HttpStream> stream(NewTestStream("ok.html")); | |
134 TestSyncRequest(stream, "ok.html"); | |
135 } | |
136 | |
137 TEST_F(HttpPipelinedConnectionImplTest, AsyncSingleRequest) { | |
138 MockWrite writes[] = { | |
139 MockWrite(true, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
140 }; | |
141 MockRead reads[] = { | |
142 MockRead(true, 1, "HTTP/1.1 200 OK\r\n"), | |
143 MockRead(true, 2, "Content-Length: 7\r\n\r\n"), | |
144 MockRead(true, 3, "ok.html"), | |
145 }; | |
146 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
147 | |
148 scoped_ptr<HttpStream> stream(NewTestStream("ok.html")); | |
149 | |
150 HttpRequestHeaders headers; | |
151 HttpResponseInfo response; | |
152 EXPECT_EQ(ERR_IO_PENDING, | |
153 stream->SendRequest(headers, NULL, &response, &callback_)); | |
154 data_->RunFor(1); | |
155 EXPECT_LE(OK, callback_.WaitForResult()); | |
156 | |
157 EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(&callback_)); | |
158 data_->RunFor(2); | |
159 EXPECT_LE(OK, callback_.WaitForResult()); | |
160 | |
161 ExpectResponse("ok.html", stream, true); | |
162 | |
163 stream->Close(false); | |
164 } | |
165 | |
166 TEST_F(HttpPipelinedConnectionImplTest, LockStepAsyncRequests) { | |
167 MockWrite writes[] = { | |
168 MockWrite(true, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
169 MockWrite(true, 1, "GET /ko.html HTTP/1.1\r\n\r\n"), | |
170 }; | |
171 MockRead reads[] = { | |
172 MockRead(true, 2, "HTTP/1.1 200 OK\r\n"), | |
173 MockRead(true, 3, "Content-Length: 7\r\n\r\n"), | |
174 MockRead(true, 4, "ok.html"), | |
175 MockRead(true, 5, "HTTP/1.1 200 OK\r\n"), | |
176 MockRead(true, 6, "Content-Length: 7\r\n\r\n"), | |
177 MockRead(true, 7, "ko.html"), | |
178 }; | |
179 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
180 | |
181 scoped_ptr<HttpStream> stream1(NewTestStream("ok.html")); | |
182 scoped_ptr<HttpStream> stream2(NewTestStream("ko.html")); | |
183 | |
184 HttpRequestHeaders headers1; | |
185 HttpResponseInfo response1; | |
186 EXPECT_EQ(ERR_IO_PENDING, | |
187 stream1->SendRequest(headers1, NULL, &response1, &callback_)); | |
188 | |
189 HttpRequestHeaders headers2; | |
190 HttpResponseInfo response2; | |
191 EXPECT_EQ(ERR_IO_PENDING, | |
192 stream2->SendRequest(headers2, NULL, &response2, &callback_)); | |
193 | |
194 data_->RunFor(1); | |
195 EXPECT_LE(OK, callback_.WaitForResult()); | |
196 data_->RunFor(1); | |
197 EXPECT_LE(OK, callback_.WaitForResult()); | |
198 | |
199 EXPECT_EQ(ERR_IO_PENDING, stream1->ReadResponseHeaders(&callback_)); | |
200 EXPECT_EQ(ERR_IO_PENDING, stream2->ReadResponseHeaders(&callback_)); | |
201 | |
202 data_->RunFor(2); | |
203 EXPECT_LE(OK, callback_.WaitForResult()); | |
204 | |
205 ExpectResponse("ok.html", stream1, true); | |
206 | |
207 stream1->Close(false); | |
208 | |
209 data_->RunFor(2); | |
210 EXPECT_LE(OK, callback_.WaitForResult()); | |
211 | |
212 ExpectResponse("ko.html", stream2, true); | |
213 | |
214 stream2->Close(false); | |
215 } | |
216 | |
217 TEST_F(HttpPipelinedConnectionImplTest, TwoResponsesInOnePacket) { | |
218 MockWrite writes[] = { | |
219 MockWrite(false, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
220 MockWrite(false, 1, "GET /ko.html HTTP/1.1\r\n\r\n"), | |
221 }; | |
222 MockRead reads[] = { | |
223 MockRead(false, 2, | |
224 "HTTP/1.1 200 OK\r\n" | |
225 "Content-Length: 7\r\n\r\n" | |
226 "ok.html" | |
227 "HTTP/1.1 200 OK\r\n" | |
228 "Content-Length: 7\r\n\r\n" | |
229 "ko.html"), | |
230 }; | |
231 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
232 | |
233 scoped_ptr<HttpStream> stream1(NewTestStream("ok.html")); | |
234 scoped_ptr<HttpStream> stream2(NewTestStream("ko.html")); | |
235 | |
236 HttpRequestHeaders headers1; | |
237 HttpResponseInfo response1; | |
238 EXPECT_EQ(OK, stream1->SendRequest(headers1, NULL, &response1, &callback_)); | |
239 HttpRequestHeaders headers2; | |
240 HttpResponseInfo response2; | |
241 EXPECT_EQ(OK, stream2->SendRequest(headers2, NULL, &response2, &callback_)); | |
242 | |
243 EXPECT_EQ(OK, stream1->ReadResponseHeaders(&callback_)); | |
244 ExpectResponse("ok.html", stream1, false); | |
245 stream1->Close(false); | |
246 | |
247 EXPECT_EQ(OK, stream2->ReadResponseHeaders(&callback_)); | |
248 ExpectResponse("ko.html", stream2, false); | |
249 stream2->Close(false); | |
250 } | |
251 | |
252 TEST_F(HttpPipelinedConnectionImplTest, InitializeOrderSwapped) { | |
253 MockWrite writes[] = { | |
254 MockWrite(false, 0, "GET /ko.html HTTP/1.1\r\n\r\n"), | |
255 MockWrite(false, 4, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
256 }; | |
257 MockRead reads[] = { | |
258 MockRead(false, 1, "HTTP/1.1 200 OK\r\n"), | |
259 MockRead(false, 2, "Content-Length: 7\r\n\r\n"), | |
260 MockRead(false, 3, "ko.html"), | |
261 MockRead(false, 5, "HTTP/1.1 200 OK\r\n"), | |
262 MockRead(false, 6, "Content-Length: 7\r\n\r\n"), | |
263 MockRead(false, 7, "ok.html"), | |
264 }; | |
265 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
266 | |
267 scoped_ptr<HttpStream> stream1(NewTestStream("ok.html")); | |
268 scoped_ptr<HttpStream> stream2(NewTestStream("ko.html")); | |
269 | |
270 TestSyncRequest(stream2, "ko.html"); | |
271 TestSyncRequest(stream1, "ok.html"); | |
272 } | |
273 | |
274 TEST_F(HttpPipelinedConnectionImplTest, SendOrderSwapped) { | |
mmenke
2011/08/23 19:05:25
How is this different from the previous test?
James Simonsen
2011/08/26 22:19:07
Hmm. It was different at one point, but I oversimp
| |
275 MockWrite writes[] = { | |
276 MockWrite(false, 0, "GET /ko.html HTTP/1.1\r\n\r\n"), | |
277 MockWrite(false, 4, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
278 }; | |
279 MockRead reads[] = { | |
280 MockRead(false, 1, "HTTP/1.1 200 OK\r\n"), | |
281 MockRead(false, 2, "Content-Length: 7\r\n\r\n"), | |
282 MockRead(false, 3, "ko.html"), | |
283 MockRead(false, 5, "HTTP/1.1 200 OK\r\n"), | |
284 MockRead(false, 6, "Content-Length: 7\r\n\r\n"), | |
285 MockRead(false, 7, "ok.html"), | |
286 }; | |
287 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
288 | |
289 scoped_ptr<HttpStream> stream1(NewTestStream("ok.html")); | |
290 scoped_ptr<HttpStream> stream2(NewTestStream("ko.html")); | |
291 | |
292 HttpRequestHeaders headers2; | |
293 HttpResponseInfo response2; | |
294 EXPECT_EQ(OK, stream2->SendRequest(headers2, NULL, &response2, &callback_)); | |
295 EXPECT_EQ(OK, stream2->ReadResponseHeaders(&callback_)); | |
296 ExpectResponse("ko.html", stream2, false); | |
297 | |
298 stream2->Close(false); | |
299 | |
300 HttpRequestHeaders headers1; | |
301 HttpResponseInfo response1; | |
302 EXPECT_EQ(OK, stream1->SendRequest(headers1, NULL, &response1, &callback_)); | |
303 EXPECT_EQ(OK, stream1->ReadResponseHeaders(&callback_)); | |
304 ExpectResponse("ok.html", stream1, false); | |
305 | |
306 stream1->Close(false); | |
307 } | |
308 | |
309 TEST_F(HttpPipelinedConnectionImplTest, ReadOrderSwapped) { | |
310 MockWrite writes[] = { | |
311 MockWrite(false, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
312 MockWrite(false, 1, "GET /ko.html HTTP/1.1\r\n\r\n"), | |
313 }; | |
314 MockRead reads[] = { | |
315 MockRead(false, 2, "HTTP/1.1 200 OK\r\n"), | |
316 MockRead(false, 3, "Content-Length: 7\r\n\r\n"), | |
317 MockRead(false, 4, "ok.html"), | |
318 MockRead(false, 5, "HTTP/1.1 200 OK\r\n"), | |
319 MockRead(false, 6, "Content-Length: 7\r\n\r\n"), | |
320 MockRead(false, 7, "ko.html"), | |
321 }; | |
322 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
323 | |
324 scoped_ptr<HttpStream> stream1(NewTestStream("ok.html")); | |
325 scoped_ptr<HttpStream> stream2(NewTestStream("ko.html")); | |
326 | |
327 HttpRequestHeaders headers1; | |
328 HttpResponseInfo response1; | |
329 EXPECT_EQ(OK, stream1->SendRequest(headers1, NULL, &response1, &callback_)); | |
330 | |
331 HttpRequestHeaders headers2; | |
332 HttpResponseInfo response2; | |
333 EXPECT_EQ(OK, stream2->SendRequest(headers2, NULL, &response2, &callback_)); | |
334 | |
335 EXPECT_EQ(ERR_IO_PENDING, stream2->ReadResponseHeaders(&callback_)); | |
336 | |
337 EXPECT_EQ(OK, stream1->ReadResponseHeaders(&callback_)); | |
338 ExpectResponse("ok.html", stream1, false); | |
339 | |
340 stream1->Close(false); | |
341 | |
342 EXPECT_LE(OK, callback_.WaitForResult()); | |
343 ExpectResponse("ko.html", stream2, false); | |
344 | |
345 stream2->Close(false); | |
346 } | |
347 | |
348 TEST_F(HttpPipelinedConnectionImplTest, SendWhileReading) { | |
349 MockWrite writes[] = { | |
350 MockWrite(false, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
351 MockWrite(false, 3, "GET /ko.html HTTP/1.1\r\n\r\n"), | |
352 }; | |
353 MockRead reads[] = { | |
354 MockRead(false, 1, "HTTP/1.1 200 OK\r\n"), | |
355 MockRead(false, 2, "Content-Length: 7\r\n\r\n"), | |
356 MockRead(false, 4, "ok.html"), | |
357 MockRead(false, 5, "HTTP/1.1 200 OK\r\n"), | |
358 MockRead(false, 6, "Content-Length: 7\r\n\r\n"), | |
359 MockRead(false, 7, "ko.html"), | |
360 }; | |
361 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
362 | |
363 scoped_ptr<HttpStream> stream1(NewTestStream("ok.html")); | |
364 scoped_ptr<HttpStream> stream2(NewTestStream("ko.html")); | |
365 | |
366 HttpRequestHeaders headers1; | |
367 HttpResponseInfo response1; | |
368 EXPECT_EQ(OK, stream1->SendRequest(headers1, NULL, &response1, &callback_)); | |
369 EXPECT_EQ(OK, stream1->ReadResponseHeaders(&callback_)); | |
370 | |
371 HttpRequestHeaders headers2; | |
372 HttpResponseInfo response2; | |
373 EXPECT_EQ(OK, stream2->SendRequest(headers2, NULL, &response2, &callback_)); | |
374 | |
375 ExpectResponse("ok.html", stream1, false); | |
376 stream1->Close(false); | |
377 | |
378 EXPECT_EQ(OK, stream2->ReadResponseHeaders(&callback_)); | |
379 ExpectResponse("ko.html", stream2, false); | |
380 stream2->Close(false); | |
381 } | |
382 | |
383 TEST_F(HttpPipelinedConnectionImplTest, AsyncSendWhileAsyncReadBlocked) { | |
384 MockWrite writes[] = { | |
385 MockWrite(false, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
386 MockWrite(true, 3, "GET /ko.html HTTP/1.1\r\n\r\n"), | |
387 }; | |
388 MockRead reads[] = { | |
389 MockRead(false, 1, "HTTP/1.1 200 OK\r\n"), | |
390 MockRead(false, 2, "Content-Length: 7\r\n\r\n"), | |
391 MockRead(true, 4, "ok.html"), | |
392 MockRead(false, 5, "HTTP/1.1 200 OK\r\n"), | |
393 MockRead(false, 6, "Content-Length: 7\r\n\r\n"), | |
394 MockRead(false, 7, "ko.html"), | |
395 }; | |
396 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
397 | |
398 scoped_ptr<HttpStream> stream1(NewTestStream("ok.html")); | |
399 scoped_ptr<HttpStream> stream2(NewTestStream("ko.html")); | |
400 | |
401 HttpRequestHeaders headers1; | |
402 HttpResponseInfo response1; | |
403 EXPECT_EQ(OK, stream1->SendRequest(headers1, NULL, &response1, &callback_)); | |
404 EXPECT_EQ(OK, stream1->ReadResponseHeaders(&callback_)); | |
405 TestCompletionCallback callback1; | |
406 std::string expected = "ok.html"; | |
407 scoped_refptr<IOBuffer> buffer(new IOBuffer(expected.size())); | |
408 EXPECT_EQ(ERR_IO_PENDING, | |
409 stream1->ReadResponseBody(buffer.get(), expected.size(), | |
410 &callback1)); | |
411 | |
412 HttpRequestHeaders headers2; | |
413 HttpResponseInfo response2; | |
414 TestCompletionCallback callback2; | |
415 EXPECT_EQ(ERR_IO_PENDING, | |
416 stream2->SendRequest(headers2, NULL, &response2, &callback2)); | |
417 | |
418 data_->RunFor(1); | |
419 EXPECT_LE(OK, callback2.WaitForResult()); | |
420 EXPECT_EQ(ERR_IO_PENDING, stream2->ReadResponseHeaders(&callback2)); | |
421 | |
422 data_->RunFor(1); | |
423 EXPECT_EQ(static_cast<int>(expected.size()), callback1.WaitForResult()); | |
424 std::string actual(buffer->data(), expected.size()); | |
425 EXPECT_THAT(actual, StrEq(expected)); | |
426 stream1->Close(false); | |
427 | |
428 data_->StopAfter(8); | |
429 EXPECT_LE(OK, callback2.WaitForResult()); | |
430 ExpectResponse("ko.html", stream2, false); | |
431 stream2->Close(false); | |
432 } | |
433 | |
434 TEST_F(HttpPipelinedConnectionImplTest, PipelineNotUsed) { | |
mmenke
2011/08/23 19:05:25
nit: Might want to put this test as well as the n
James Simonsen
2011/08/26 22:19:07
Done.
| |
435 MockWrite writes[] = {}; | |
mmenke
2011/08/23 19:05:25
MSVC doesn't like 0-length arrays like this.
James Simonsen
2011/08/26 22:19:07
Lame. Fixed.
| |
436 MockRead reads[] = {}; | |
437 Initialize(reads, 0, writes, 0); | |
438 } | |
439 | |
440 TEST_F(HttpPipelinedConnectionImplTest, StreamNotUsed) { | |
441 MockWrite writes[] = {}; | |
442 MockRead reads[] = {}; | |
443 Initialize(reads, 0, writes, 0); | |
444 | |
445 scoped_ptr<HttpStream> stream(pipeline_->CreateNewStream()); | |
446 | |
447 stream->Close(false); | |
448 } | |
449 | |
450 TEST_F(HttpPipelinedConnectionImplTest, StreamBoundButNotUsed) { | |
451 MockWrite writes[] = {}; | |
452 MockRead reads[] = {}; | |
453 Initialize(reads, 0, writes, 0); | |
454 | |
455 scoped_ptr<HttpStream> stream(NewTestStream("ok.html")); | |
456 | |
457 stream->Close(false); | |
458 } | |
459 | |
460 TEST_F(HttpPipelinedConnectionImplTest, UnusedStreamAllowsLaterUse) { | |
461 MockWrite writes[] = { | |
462 MockWrite(false, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
463 }; | |
464 MockRead reads[] = { | |
465 MockRead(false, 1, "HTTP/1.1 200 OK\r\n"), | |
466 MockRead(false, 2, "Content-Length: 7\r\n\r\n"), | |
467 MockRead(false, 3, "ok.html"), | |
468 }; | |
469 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
470 | |
471 scoped_ptr<HttpStream> unused_stream(NewTestStream("unused.html")); | |
472 unused_stream->Close(false); | |
473 | |
474 scoped_ptr<HttpStream> later_stream(NewTestStream("ok.html")); | |
475 TestSyncRequest(later_stream, "ok.html"); | |
476 } | |
477 | |
478 TEST_F(HttpPipelinedConnectionImplTest, UnsentStreamAllowsLaterUse) { | |
479 MockWrite writes[] = { | |
480 MockWrite(true, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
481 MockWrite(false, 4, "GET /ko.html HTTP/1.1\r\n\r\n"), | |
482 }; | |
483 MockRead reads[] = { | |
484 MockRead(true, 1, "HTTP/1.1 200 OK\r\n"), | |
485 MockRead(true, 2, "Content-Length: 7\r\n\r\n"), | |
486 MockRead(true, 3, "ok.html"), | |
487 MockRead(false, 5, "HTTP/1.1 200 OK\r\n"), | |
488 MockRead(false, 6, "Content-Length: 7\r\n\r\n"), | |
489 MockRead(false, 7, "ko.html"), | |
490 }; | |
491 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
492 | |
493 scoped_ptr<HttpStream> stream(NewTestStream("ok.html")); | |
494 | |
495 HttpRequestHeaders headers; | |
496 HttpResponseInfo response; | |
497 EXPECT_EQ(ERR_IO_PENDING, | |
498 stream->SendRequest(headers, NULL, &response, &callback_)); | |
499 | |
500 scoped_ptr<HttpStream> unsent_stream(NewTestStream("unsent.html")); | |
501 HttpRequestHeaders unsent_headers; | |
502 HttpResponseInfo unsent_response; | |
503 EXPECT_EQ(ERR_IO_PENDING, | |
504 unsent_stream->SendRequest(unsent_headers, NULL, &unsent_response, | |
505 &callback_)); | |
506 unsent_stream->Close(false); | |
507 | |
508 data_->RunFor(1); | |
509 EXPECT_LE(OK, callback_.WaitForResult()); | |
510 | |
511 EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(&callback_)); | |
512 data_->RunFor(2); | |
513 EXPECT_LE(OK, callback_.WaitForResult()); | |
514 | |
515 ExpectResponse("ok.html", stream, true); | |
516 | |
517 stream->Close(false); | |
518 | |
519 data_->StopAfter(8); | |
520 scoped_ptr<HttpStream> later_stream(NewTestStream("ko.html")); | |
521 TestSyncRequest(later_stream, "ko.html"); | |
522 } | |
523 | |
524 TEST_F(HttpPipelinedConnectionImplTest, FailedSend) { | |
525 MockWrite writes[] = { | |
526 MockWrite(true, ERR_FAILED), | |
527 }; | |
528 MockRead reads[] = {}; | |
529 Initialize(reads, 0, writes, arraysize(writes)); | |
530 | |
531 scoped_ptr<HttpStream> failed_stream(NewTestStream("ok.html")); | |
532 scoped_ptr<HttpStream> evicted_stream(NewTestStream("evicted.html")); | |
533 scoped_ptr<HttpStream> closed_stream(NewTestStream("closed.html")); | |
534 scoped_ptr<HttpStream> rejected_stream(NewTestStream("rejected.html")); | |
535 | |
536 HttpRequestHeaders headers; | |
537 HttpResponseInfo response; | |
538 TestCompletionCallback failed_callback; | |
539 EXPECT_EQ(ERR_IO_PENDING, | |
540 failed_stream->SendRequest(headers, NULL, &response, | |
541 &failed_callback)); | |
542 TestCompletionCallback evicted_callback; | |
543 EXPECT_EQ(ERR_IO_PENDING, | |
544 evicted_stream->SendRequest(headers, NULL, &response, | |
545 &evicted_callback)); | |
546 EXPECT_EQ(ERR_IO_PENDING, | |
547 closed_stream->SendRequest(headers, NULL, &response, | |
548 &callback_)); | |
549 closed_stream->Close(false); | |
550 | |
551 data_->RunFor(1); | |
552 EXPECT_EQ(ERR_FAILED, failed_callback.WaitForResult()); | |
553 EXPECT_EQ(ERR_PIPELINE_EVICTION, evicted_callback.WaitForResult()); | |
554 EXPECT_EQ(ERR_PIPELINE_EVICTION, | |
555 rejected_stream->SendRequest(headers, NULL, &response, | |
556 &callback_)); | |
557 | |
558 failed_stream->Close(true); | |
559 evicted_stream->Close(true); | |
560 rejected_stream->Close(true); | |
561 } | |
562 | |
563 TEST_F(HttpPipelinedConnectionImplTest, ConnectionSuddenlyClosedAfterResponse) { | |
564 MockWrite writes[] = { | |
565 MockWrite(false, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
566 MockWrite(false, 1, "GET /read_evicted.html HTTP/1.1\r\n\r\n"), | |
567 MockWrite(false, 2, "GET /read_rejected.html HTTP/1.1\r\n\r\n"), | |
568 MockWrite(true, ERR_SOCKET_NOT_CONNECTED, 5), | |
569 }; | |
570 MockRead reads[] = { | |
571 MockRead(false, 3, "HTTP/1.1 200 OK\r\n\r\n"), | |
572 MockRead(false, 4, "ok.html"), | |
573 }; | |
574 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
575 | |
576 scoped_ptr<HttpStream> closed_stream(NewTestStream("ok.html")); | |
577 scoped_ptr<HttpStream> read_evicted_stream( | |
578 NewTestStream("read_evicted.html")); | |
579 scoped_ptr<HttpStream> read_rejected_stream( | |
580 NewTestStream("read_rejected.html")); | |
581 scoped_ptr<HttpStream> send_closed_stream( | |
582 NewTestStream("send_closed.html")); | |
583 scoped_ptr<HttpStream> send_evicted_stream( | |
584 NewTestStream("send_evicted.html")); | |
585 scoped_ptr<HttpStream> send_rejected_stream( | |
586 NewTestStream("send_rejected.html")); | |
587 | |
588 HttpRequestHeaders headers; | |
589 HttpResponseInfo response; | |
590 EXPECT_EQ(OK, closed_stream->SendRequest(headers, NULL, &response, | |
591 &callback_)); | |
592 EXPECT_EQ(OK, read_evicted_stream->SendRequest(headers, NULL, &response, | |
593 &callback_)); | |
594 EXPECT_EQ(OK, read_rejected_stream->SendRequest(headers, NULL, &response, | |
595 &callback_)); | |
596 TestCompletionCallback send_closed_callback; | |
597 EXPECT_EQ(ERR_IO_PENDING, | |
598 send_closed_stream->SendRequest(headers, NULL, &response, | |
599 &send_closed_callback)); | |
600 TestCompletionCallback send_evicted_callback; | |
601 EXPECT_EQ(ERR_IO_PENDING, | |
602 send_evicted_stream->SendRequest(headers, NULL, &response, | |
603 &send_evicted_callback)); | |
604 | |
605 TestCompletionCallback read_evicted_callback; | |
606 EXPECT_EQ(ERR_IO_PENDING, | |
607 read_evicted_stream->ReadResponseHeaders(&read_evicted_callback)); | |
608 | |
609 EXPECT_EQ(OK, closed_stream->ReadResponseHeaders(&callback_)); | |
610 std::string expected = "ok.html"; | |
611 scoped_refptr<IOBuffer> buffer(new IOBuffer(expected.size() + 10)); | |
612 EXPECT_EQ(static_cast<int>(expected.size()), | |
613 closed_stream->ReadResponseBody(buffer.get(), expected.size() + 10, | |
614 &callback_)); | |
615 std::string actual(buffer->data(), expected.size()); | |
616 EXPECT_THAT(actual, StrEq(expected)); | |
mmenke
2011/08/23 19:05:25
nit: Instead of the above lines, could just use:
James Simonsen
2011/08/26 22:19:07
Good eye. Fixed.
| |
617 closed_stream->Close(true); | |
618 | |
619 EXPECT_EQ(ERR_PIPELINE_EVICTION, read_evicted_callback.WaitForResult()); | |
620 read_evicted_stream->Close(true); | |
621 | |
622 EXPECT_EQ(ERR_PIPELINE_EVICTION, | |
623 read_rejected_stream->ReadResponseHeaders(&callback_)); | |
624 read_rejected_stream->Close(true); | |
625 | |
626 data_->RunFor(1); | |
627 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, send_closed_callback.WaitForResult()); | |
628 send_closed_stream->Close(true); | |
629 | |
630 EXPECT_EQ(ERR_PIPELINE_EVICTION, send_evicted_callback.WaitForResult()); | |
631 send_evicted_stream->Close(true); | |
632 | |
633 EXPECT_EQ(ERR_PIPELINE_EVICTION, | |
634 send_rejected_stream->SendRequest(headers, NULL, &response, | |
635 &callback_)); | |
636 send_rejected_stream->Close(true); | |
637 } | |
638 | |
639 TEST_F(HttpPipelinedConnectionImplTest, AbortWhileReadingHeaders) { | |
640 MockWrite writes[] = { | |
641 MockWrite(false, 0, "GET /aborts.html HTTP/1.1\r\n\r\n"), | |
642 MockWrite(false, 1, "GET /evicted.html HTTP/1.1\r\n\r\n"), | |
643 }; | |
644 MockRead reads[] = { | |
645 MockRead(true, ERR_FAILED, 2), | |
646 }; | |
647 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
648 | |
649 scoped_ptr<HttpStream> aborted_stream(NewTestStream("aborts.html")); | |
650 scoped_ptr<HttpStream> evicted_stream(NewTestStream("evicted.html")); | |
651 scoped_ptr<HttpStream> rejected_stream(NewTestStream( | |
652 "rejected.html")); | |
653 | |
654 HttpRequestHeaders headers; | |
655 HttpResponseInfo response; | |
656 EXPECT_EQ(OK, aborted_stream->SendRequest(headers, NULL, &response, | |
657 &callback_)); | |
658 EXPECT_EQ(OK, evicted_stream->SendRequest(headers, NULL, &response, | |
659 &callback_)); | |
660 | |
661 EXPECT_EQ(ERR_IO_PENDING, aborted_stream->ReadResponseHeaders(&callback_)); | |
662 TestCompletionCallback evicted_callback; | |
663 EXPECT_EQ(ERR_IO_PENDING, | |
664 evicted_stream->ReadResponseHeaders(&evicted_callback)); | |
665 | |
666 aborted_stream->Close(true); | |
667 EXPECT_EQ(ERR_PIPELINE_EVICTION, evicted_callback.WaitForResult()); | |
668 evicted_stream->Close(true); | |
669 | |
670 EXPECT_EQ(ERR_PIPELINE_EVICTION, | |
671 rejected_stream->SendRequest(headers, NULL, &response, &callback_)); | |
672 rejected_stream->Close(true); | |
673 } | |
674 | |
675 TEST_F(HttpPipelinedConnectionImplTest, PendingResponseAbandoned) { | |
mmenke
2011/08/23 19:05:25
Out of general paranoia, should also have tests wh
James Simonsen
2011/08/26 22:19:07
Nice. Caught a bug too.
| |
676 MockWrite writes[] = { | |
677 MockWrite(false, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
678 MockWrite(false, 1, "GET /abandoned.html HTTP/1.1\r\n\r\n"), | |
679 MockWrite(false, 2, "GET /evicted.html HTTP/1.1\r\n\r\n"), | |
680 }; | |
681 MockRead reads[] = { | |
682 MockRead(false, 3, "HTTP/1.1 200 OK\r\n"), | |
683 MockRead(false, 4, "Content-Length: 7\r\n\r\n"), | |
684 MockRead(false, 5, "ok.html"), | |
685 }; | |
686 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
687 | |
688 scoped_ptr<HttpStream> ok_stream(NewTestStream("ok.html")); | |
689 scoped_ptr<HttpStream> abandoned_stream( | |
690 NewTestStream("abandoned.html")); | |
691 scoped_ptr<HttpStream> evicted_stream(NewTestStream("evicted.html")); | |
692 | |
693 HttpRequestHeaders headers; | |
694 HttpResponseInfo response; | |
695 EXPECT_EQ(OK, ok_stream->SendRequest(headers, NULL, &response, &callback_)); | |
696 EXPECT_EQ(OK, abandoned_stream->SendRequest(headers, NULL, &response, | |
697 &callback_)); | |
698 EXPECT_EQ(OK, evicted_stream->SendRequest(headers, NULL, &response, | |
699 &callback_)); | |
700 | |
701 EXPECT_EQ(OK, ok_stream->ReadResponseHeaders(&callback_)); | |
702 TestCompletionCallback abandoned_callback; | |
703 EXPECT_EQ(ERR_IO_PENDING, | |
704 abandoned_stream->ReadResponseHeaders(&abandoned_callback)); | |
705 TestCompletionCallback evicted_callback; | |
706 EXPECT_EQ(ERR_IO_PENDING, | |
707 evicted_stream->ReadResponseHeaders(&evicted_callback)); | |
708 | |
709 abandoned_stream->Close(false); | |
710 | |
711 ExpectResponse("ok.html", ok_stream, false); | |
712 ok_stream->Close(false); | |
713 | |
714 EXPECT_EQ(ERR_PIPELINE_EVICTION, evicted_callback.WaitForResult()); | |
715 evicted_stream->Close(true); | |
716 EXPECT_FALSE(evicted_stream->IsConnectionReusable()); | |
717 } | |
718 | |
719 TEST_F(HttpPipelinedConnectionImplTest, OnPipelineHasCapacity) { | |
720 MockWrite writes[] = { | |
721 MockWrite(false, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
722 }; | |
723 MockRead reads[] = {}; | |
724 Initialize(reads, 0, writes, arraysize(writes)); | |
725 | |
726 scoped_ptr<HttpStream> stream(NewTestStream("ok.html")); | |
727 | |
728 EXPECT_CALL(owner_, OnPipelineHasCapacity(pipeline_.get())).Times(1); | |
729 HttpRequestHeaders headers; | |
730 HttpResponseInfo response; | |
731 EXPECT_EQ(OK, stream->SendRequest(headers, NULL, &response, &callback_)); | |
732 MessageLoop::current()->RunAllPending(); | |
733 | |
734 stream->Close(false); | |
735 EXPECT_CALL(owner_, OnPipelineHasCapacity(pipeline_.get())).Times(1); | |
736 stream.reset(NULL); | |
737 MessageLoop::current()->RunAllPending(); | |
738 } | |
739 | |
740 } // namespace net | |
OLD | NEW |