OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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> | |
8 | |
9 #include "base/memory/ref_counted.h" | |
10 #include "base/memory/scoped_ptr.h" | |
11 #include "base/memory/scoped_vector.h" | |
12 #include "net/base/capturing_net_log.h" | |
13 #include "net/base/io_buffer.h" | |
14 #include "net/base/load_timing_info.h" | |
15 #include "net/base/load_timing_info_test_util.h" | |
16 #include "net/base/net_errors.h" | |
17 #include "net/base/request_priority.h" | |
18 #include "net/http/http_pipelined_stream.h" | |
19 #include "net/socket/client_socket_handle.h" | |
20 #include "net/socket/client_socket_pool_histograms.h" | |
21 #include "net/socket/socket_test_util.h" | |
22 #include "testing/gmock/include/gmock/gmock.h" | |
23 #include "testing/gtest/include/gtest/gtest.h" | |
24 | |
25 using testing::_; | |
26 using testing::NiceMock; | |
27 using testing::StrEq; | |
28 | |
29 namespace net { | |
30 | |
31 namespace { | |
32 | |
33 // Tests the load timing of a stream that's connected and is not the first | |
34 // request sent on a connection. | |
35 void TestLoadTimingReused(const HttpStream& stream) { | |
36 LoadTimingInfo load_timing_info; | |
37 EXPECT_TRUE(stream.GetLoadTimingInfo(&load_timing_info)); | |
38 | |
39 EXPECT_TRUE(load_timing_info.socket_reused); | |
40 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id); | |
41 | |
42 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing); | |
43 ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info); | |
44 } | |
45 | |
46 // Tests the load timing of a stream that's connected and using a fresh | |
47 // connection. | |
48 void TestLoadTimingNotReused(const HttpStream& stream) { | |
49 LoadTimingInfo load_timing_info; | |
50 EXPECT_TRUE(stream.GetLoadTimingInfo(&load_timing_info)); | |
51 | |
52 EXPECT_FALSE(load_timing_info.socket_reused); | |
53 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id); | |
54 | |
55 ExpectConnectTimingHasTimes(load_timing_info.connect_timing, | |
56 CONNECT_TIMING_HAS_DNS_TIMES); | |
57 ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info); | |
58 } | |
59 | |
60 class MockPipelineDelegate : public HttpPipelinedConnection::Delegate { | |
61 public: | |
62 MOCK_METHOD1(OnPipelineHasCapacity, void(HttpPipelinedConnection* pipeline)); | |
63 MOCK_METHOD2(OnPipelineFeedback, void( | |
64 HttpPipelinedConnection* pipeline, | |
65 HttpPipelinedConnection::Feedback feedback)); | |
66 }; | |
67 | |
68 class SuddenCloseObserver : public base::MessageLoop::TaskObserver { | |
69 public: | |
70 SuddenCloseObserver(HttpStream* stream, int close_before_task) | |
71 : stream_(stream), | |
72 close_before_task_(close_before_task), | |
73 current_task_(0) { } | |
74 | |
75 virtual void WillProcessTask(const base::PendingTask& pending_task) OVERRIDE { | |
76 ++current_task_; | |
77 if (current_task_ == close_before_task_) { | |
78 stream_->Close(false); | |
79 base::MessageLoop::current()->RemoveTaskObserver(this); | |
80 } | |
81 } | |
82 | |
83 virtual void DidProcessTask(const base::PendingTask& pending_task) OVERRIDE {} | |
84 | |
85 private: | |
86 HttpStream* stream_; | |
87 int close_before_task_; | |
88 int current_task_; | |
89 }; | |
90 | |
91 class HttpPipelinedConnectionImplTest : public testing::Test { | |
92 public: | |
93 HttpPipelinedConnectionImplTest() | |
94 : histograms_("a"), | |
95 pool_(1, 1, &histograms_, &factory_), | |
96 origin_("host", 123) { | |
97 } | |
98 | |
99 void TearDown() { | |
100 base::MessageLoop::current()->RunUntilIdle(); | |
101 } | |
102 | |
103 void Initialize(MockRead* reads, size_t reads_count, | |
104 MockWrite* writes, size_t writes_count) { | |
105 data_.reset(new DeterministicSocketData(reads, reads_count, | |
106 writes, writes_count)); | |
107 data_->set_connect_data(MockConnect(SYNCHRONOUS, OK)); | |
108 if (reads_count || writes_count) { | |
109 data_->StopAfter(reads_count + writes_count); | |
110 } | |
111 factory_.AddSocketDataProvider(data_.get()); | |
112 scoped_refptr<MockTransportSocketParams> params; | |
113 ClientSocketHandle* connection = new ClientSocketHandle; | |
114 // Only give the connection a real NetLog to make sure that LoadTiming uses | |
115 // the connection's ID, rather than the pipeline's. Since pipelines are | |
116 // destroyed when they've responded to all requests, but the connection | |
117 // lives on, this is an important behavior. | |
118 connection->Init("a", params, MEDIUM, CompletionCallback(), &pool_, | |
119 net_log_.bound()); | |
120 pipeline_.reset(new HttpPipelinedConnectionImpl( | |
121 connection, &delegate_, origin_, ssl_config_, proxy_info_, | |
122 BoundNetLog(), false, kProtoUnknown)); | |
123 } | |
124 | |
125 HttpRequestInfo* GetRequestInfo(const std::string& filename) { | |
126 HttpRequestInfo* request_info = new HttpRequestInfo; | |
127 request_info->url = GURL("http://localhost/" + filename); | |
128 request_info->method = "GET"; | |
129 request_info_vector_.push_back(request_info); | |
130 return request_info; | |
131 } | |
132 | |
133 HttpStream* NewTestStream(const std::string& filename) { | |
134 HttpStream* stream = pipeline_->CreateNewStream(); | |
135 HttpRequestInfo* request_info = GetRequestInfo(filename); | |
136 int rv = stream->InitializeStream( | |
137 request_info, DEFAULT_PRIORITY, BoundNetLog(), CompletionCallback()); | |
138 DCHECK_EQ(OK, rv); | |
139 return stream; | |
140 } | |
141 | |
142 void ExpectResponse(const std::string& expected, | |
143 scoped_ptr<HttpStream>& stream, bool async) { | |
144 scoped_refptr<IOBuffer> buffer(new IOBuffer(expected.size())); | |
145 | |
146 if (async) { | |
147 EXPECT_EQ(ERR_IO_PENDING, | |
148 stream->ReadResponseBody(buffer.get(), expected.size(), | |
149 callback_.callback())); | |
150 data_->RunFor(1); | |
151 EXPECT_EQ(static_cast<int>(expected.size()), callback_.WaitForResult()); | |
152 } else { | |
153 EXPECT_EQ(static_cast<int>(expected.size()), | |
154 stream->ReadResponseBody(buffer.get(), expected.size(), | |
155 callback_.callback())); | |
156 } | |
157 std::string actual(buffer->data(), expected.size()); | |
158 EXPECT_THAT(actual, StrEq(expected)); | |
159 } | |
160 | |
161 void TestSyncRequest(scoped_ptr<HttpStream>& stream, | |
162 const std::string& filename) { | |
163 HttpRequestHeaders headers; | |
164 HttpResponseInfo response; | |
165 EXPECT_EQ(OK, stream->SendRequest(headers, &response, | |
166 callback_.callback())); | |
167 EXPECT_EQ(OK, stream->ReadResponseHeaders(callback_.callback())); | |
168 ExpectResponse(filename, stream, false); | |
169 | |
170 stream->Close(false); | |
171 } | |
172 | |
173 CapturingBoundNetLog net_log_; | |
174 DeterministicMockClientSocketFactory factory_; | |
175 ClientSocketPoolHistograms histograms_; | |
176 MockTransportClientSocketPool pool_; | |
177 scoped_ptr<DeterministicSocketData> data_; | |
178 | |
179 HostPortPair origin_; | |
180 SSLConfig ssl_config_; | |
181 ProxyInfo proxy_info_; | |
182 NiceMock<MockPipelineDelegate> delegate_; | |
183 TestCompletionCallback callback_; | |
184 scoped_ptr<HttpPipelinedConnectionImpl> pipeline_; | |
185 ScopedVector<HttpRequestInfo> request_info_vector_; | |
186 }; | |
187 | |
188 TEST_F(HttpPipelinedConnectionImplTest, PipelineNotUsed) { | |
189 Initialize(NULL, 0, NULL, 0); | |
190 } | |
191 | |
192 TEST_F(HttpPipelinedConnectionImplTest, StreamNotUsed) { | |
193 Initialize(NULL, 0, NULL, 0); | |
194 | |
195 scoped_ptr<HttpStream> stream(pipeline_->CreateNewStream()); | |
196 | |
197 stream->Close(false); | |
198 } | |
199 | |
200 TEST_F(HttpPipelinedConnectionImplTest, StreamBoundButNotUsed) { | |
201 Initialize(NULL, 0, NULL, 0); | |
202 | |
203 scoped_ptr<HttpStream> stream(NewTestStream("ok.html")); | |
204 | |
205 TestLoadTimingNotReused(*stream); | |
206 stream->Close(false); | |
207 TestLoadTimingNotReused(*stream); | |
208 } | |
209 | |
210 TEST_F(HttpPipelinedConnectionImplTest, SyncSingleRequest) { | |
211 MockWrite writes[] = { | |
212 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
213 }; | |
214 MockRead reads[] = { | |
215 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), | |
216 MockRead(SYNCHRONOUS, 2, "Content-Length: 7\r\n\r\n"), | |
217 MockRead(SYNCHRONOUS, 3, "ok.html"), | |
218 }; | |
219 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
220 | |
221 scoped_ptr<HttpStream> stream(NewTestStream("ok.html")); | |
222 TestLoadTimingNotReused(*stream); | |
223 TestSyncRequest(stream, "ok.html"); | |
224 TestLoadTimingNotReused(*stream); | |
225 } | |
226 | |
227 TEST_F(HttpPipelinedConnectionImplTest, AsyncSingleRequest) { | |
228 MockWrite writes[] = { | |
229 MockWrite(ASYNC, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
230 }; | |
231 MockRead reads[] = { | |
232 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n"), | |
233 MockRead(ASYNC, 2, "Content-Length: 7\r\n\r\n"), | |
234 MockRead(ASYNC, 3, "ok.html"), | |
235 }; | |
236 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
237 | |
238 scoped_ptr<HttpStream> stream(NewTestStream("ok.html")); | |
239 | |
240 HttpRequestHeaders headers; | |
241 HttpResponseInfo response; | |
242 EXPECT_EQ(ERR_IO_PENDING, stream->SendRequest(headers, &response, | |
243 callback_.callback())); | |
244 data_->RunFor(1); | |
245 EXPECT_LE(OK, callback_.WaitForResult()); | |
246 TestLoadTimingNotReused(*stream); | |
247 | |
248 EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback())); | |
249 data_->RunFor(2); | |
250 EXPECT_LE(OK, callback_.WaitForResult()); | |
251 TestLoadTimingNotReused(*stream); | |
252 | |
253 ExpectResponse("ok.html", stream, true); | |
254 TestLoadTimingNotReused(*stream); | |
255 | |
256 stream->Close(false); | |
257 } | |
258 | |
259 TEST_F(HttpPipelinedConnectionImplTest, LockStepAsyncRequests) { | |
260 MockWrite writes[] = { | |
261 MockWrite(ASYNC, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
262 MockWrite(ASYNC, 1, "GET /ko.html HTTP/1.1\r\n\r\n"), | |
263 }; | |
264 MockRead reads[] = { | |
265 MockRead(ASYNC, 2, "HTTP/1.1 200 OK\r\n"), | |
266 MockRead(ASYNC, 3, "Content-Length: 7\r\n\r\n"), | |
267 MockRead(ASYNC, 4, "ok.html"), | |
268 MockRead(ASYNC, 5, "HTTP/1.1 200 OK\r\n"), | |
269 MockRead(ASYNC, 6, "Content-Length: 7\r\n\r\n"), | |
270 MockRead(ASYNC, 7, "ko.html"), | |
271 }; | |
272 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
273 | |
274 scoped_ptr<HttpStream> stream1(NewTestStream("ok.html")); | |
275 scoped_ptr<HttpStream> stream2(NewTestStream("ko.html")); | |
276 | |
277 HttpRequestHeaders headers1; | |
278 HttpResponseInfo response1; | |
279 EXPECT_EQ(ERR_IO_PENDING, stream1->SendRequest(headers1, &response1, | |
280 callback_.callback())); | |
281 TestLoadTimingNotReused(*stream1); | |
282 | |
283 HttpRequestHeaders headers2; | |
284 HttpResponseInfo response2; | |
285 EXPECT_EQ(ERR_IO_PENDING, stream2->SendRequest(headers2, &response2, | |
286 callback_.callback())); | |
287 TestLoadTimingReused(*stream2); | |
288 | |
289 data_->RunFor(1); | |
290 EXPECT_LE(OK, callback_.WaitForResult()); | |
291 data_->RunFor(1); | |
292 EXPECT_LE(OK, callback_.WaitForResult()); | |
293 | |
294 EXPECT_EQ(ERR_IO_PENDING, stream1->ReadResponseHeaders(callback_.callback())); | |
295 EXPECT_EQ(ERR_IO_PENDING, stream2->ReadResponseHeaders(callback_.callback())); | |
296 | |
297 data_->RunFor(2); | |
298 EXPECT_LE(OK, callback_.WaitForResult()); | |
299 | |
300 ExpectResponse("ok.html", stream1, true); | |
301 | |
302 TestLoadTimingNotReused(*stream1); | |
303 LoadTimingInfo load_timing_info1; | |
304 EXPECT_TRUE(stream1->GetLoadTimingInfo(&load_timing_info1)); | |
305 stream1->Close(false); | |
306 | |
307 data_->RunFor(2); | |
308 EXPECT_LE(OK, callback_.WaitForResult()); | |
309 | |
310 ExpectResponse("ko.html", stream2, true); | |
311 | |
312 TestLoadTimingReused(*stream2); | |
313 LoadTimingInfo load_timing_info2; | |
314 EXPECT_TRUE(stream2->GetLoadTimingInfo(&load_timing_info2)); | |
315 EXPECT_EQ(load_timing_info1.socket_log_id, | |
316 load_timing_info2.socket_log_id); | |
317 stream2->Close(false); | |
318 } | |
319 | |
320 TEST_F(HttpPipelinedConnectionImplTest, TwoResponsesInOnePacket) { | |
321 MockWrite writes[] = { | |
322 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
323 MockWrite(SYNCHRONOUS, 1, "GET /ko.html HTTP/1.1\r\n\r\n"), | |
324 }; | |
325 MockRead reads[] = { | |
326 MockRead(SYNCHRONOUS, 2, | |
327 "HTTP/1.1 200 OK\r\n" | |
328 "Content-Length: 7\r\n\r\n" | |
329 "ok.html" | |
330 "HTTP/1.1 200 OK\r\n" | |
331 "Content-Length: 7\r\n\r\n" | |
332 "ko.html"), | |
333 }; | |
334 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
335 | |
336 scoped_ptr<HttpStream> stream1(NewTestStream("ok.html")); | |
337 scoped_ptr<HttpStream> stream2(NewTestStream("ko.html")); | |
338 | |
339 HttpRequestHeaders headers1; | |
340 HttpResponseInfo response1; | |
341 EXPECT_EQ(OK, stream1->SendRequest(headers1, | |
342 &response1, callback_.callback())); | |
343 HttpRequestHeaders headers2; | |
344 HttpResponseInfo response2; | |
345 EXPECT_EQ(OK, stream2->SendRequest(headers2, | |
346 &response2, callback_.callback())); | |
347 | |
348 EXPECT_EQ(OK, stream1->ReadResponseHeaders(callback_.callback())); | |
349 ExpectResponse("ok.html", stream1, false); | |
350 stream1->Close(false); | |
351 | |
352 EXPECT_EQ(OK, stream2->ReadResponseHeaders(callback_.callback())); | |
353 ExpectResponse("ko.html", stream2, false); | |
354 stream2->Close(false); | |
355 } | |
356 | |
357 TEST_F(HttpPipelinedConnectionImplTest, SendOrderSwapped) { | |
358 MockWrite writes[] = { | |
359 MockWrite(SYNCHRONOUS, 0, "GET /ko.html HTTP/1.1\r\n\r\n"), | |
360 MockWrite(SYNCHRONOUS, 4, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
361 }; | |
362 MockRead reads[] = { | |
363 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), | |
364 MockRead(SYNCHRONOUS, 2, "Content-Length: 7\r\n\r\n"), | |
365 MockRead(SYNCHRONOUS, 3, "ko.html"), | |
366 MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"), | |
367 MockRead(SYNCHRONOUS, 6, "Content-Length: 7\r\n\r\n"), | |
368 MockRead(SYNCHRONOUS, 7, "ok.html"), | |
369 }; | |
370 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
371 | |
372 scoped_ptr<HttpStream> stream1(NewTestStream("ok.html")); | |
373 scoped_ptr<HttpStream> stream2(NewTestStream("ko.html")); | |
374 | |
375 TestSyncRequest(stream2, "ko.html"); | |
376 TestSyncRequest(stream1, "ok.html"); | |
377 TestLoadTimingNotReused(*stream1); | |
378 TestLoadTimingReused(*stream2); | |
379 } | |
380 | |
381 TEST_F(HttpPipelinedConnectionImplTest, ReadOrderSwapped) { | |
382 MockWrite writes[] = { | |
383 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
384 MockWrite(SYNCHRONOUS, 1, "GET /ko.html HTTP/1.1\r\n\r\n"), | |
385 }; | |
386 MockRead reads[] = { | |
387 MockRead(SYNCHRONOUS, 2, "HTTP/1.1 200 OK\r\n"), | |
388 MockRead(SYNCHRONOUS, 3, "Content-Length: 7\r\n\r\n"), | |
389 MockRead(SYNCHRONOUS, 4, "ok.html"), | |
390 MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"), | |
391 MockRead(SYNCHRONOUS, 6, "Content-Length: 7\r\n\r\n"), | |
392 MockRead(SYNCHRONOUS, 7, "ko.html"), | |
393 }; | |
394 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
395 | |
396 scoped_ptr<HttpStream> stream1(NewTestStream("ok.html")); | |
397 scoped_ptr<HttpStream> stream2(NewTestStream("ko.html")); | |
398 | |
399 HttpRequestHeaders headers1; | |
400 HttpResponseInfo response1; | |
401 EXPECT_EQ(OK, stream1->SendRequest(headers1, | |
402 &response1, callback_.callback())); | |
403 | |
404 HttpRequestHeaders headers2; | |
405 HttpResponseInfo response2; | |
406 EXPECT_EQ(OK, stream2->SendRequest(headers2, | |
407 &response2, callback_.callback())); | |
408 | |
409 EXPECT_EQ(ERR_IO_PENDING, stream2->ReadResponseHeaders(callback_.callback())); | |
410 | |
411 EXPECT_EQ(OK, stream1->ReadResponseHeaders(callback_.callback())); | |
412 ExpectResponse("ok.html", stream1, false); | |
413 | |
414 stream1->Close(false); | |
415 | |
416 EXPECT_LE(OK, callback_.WaitForResult()); | |
417 ExpectResponse("ko.html", stream2, false); | |
418 | |
419 stream2->Close(false); | |
420 } | |
421 | |
422 TEST_F(HttpPipelinedConnectionImplTest, SendWhileReading) { | |
423 MockWrite writes[] = { | |
424 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
425 MockWrite(SYNCHRONOUS, 3, "GET /ko.html HTTP/1.1\r\n\r\n"), | |
426 }; | |
427 MockRead reads[] = { | |
428 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), | |
429 MockRead(SYNCHRONOUS, 2, "Content-Length: 7\r\n\r\n"), | |
430 MockRead(SYNCHRONOUS, 4, "ok.html"), | |
431 MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"), | |
432 MockRead(SYNCHRONOUS, 6, "Content-Length: 7\r\n\r\n"), | |
433 MockRead(SYNCHRONOUS, 7, "ko.html"), | |
434 }; | |
435 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
436 | |
437 scoped_ptr<HttpStream> stream1(NewTestStream("ok.html")); | |
438 scoped_ptr<HttpStream> stream2(NewTestStream("ko.html")); | |
439 | |
440 HttpRequestHeaders headers1; | |
441 HttpResponseInfo response1; | |
442 EXPECT_EQ(OK, stream1->SendRequest(headers1, | |
443 &response1, callback_.callback())); | |
444 EXPECT_EQ(OK, stream1->ReadResponseHeaders(callback_.callback())); | |
445 | |
446 HttpRequestHeaders headers2; | |
447 HttpResponseInfo response2; | |
448 EXPECT_EQ(OK, stream2->SendRequest(headers2, | |
449 &response2, callback_.callback())); | |
450 | |
451 ExpectResponse("ok.html", stream1, false); | |
452 stream1->Close(false); | |
453 | |
454 EXPECT_EQ(OK, stream2->ReadResponseHeaders(callback_.callback())); | |
455 ExpectResponse("ko.html", stream2, false); | |
456 stream2->Close(false); | |
457 } | |
458 | |
459 TEST_F(HttpPipelinedConnectionImplTest, AsyncSendWhileAsyncReadBlocked) { | |
460 MockWrite writes[] = { | |
461 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
462 MockWrite(ASYNC, 3, "GET /ko.html HTTP/1.1\r\n\r\n"), | |
463 }; | |
464 MockRead reads[] = { | |
465 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), | |
466 MockRead(SYNCHRONOUS, 2, "Content-Length: 7\r\n\r\n"), | |
467 MockRead(ASYNC, 4, "ok.html"), | |
468 MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"), | |
469 MockRead(SYNCHRONOUS, 6, "Content-Length: 7\r\n\r\n"), | |
470 MockRead(SYNCHRONOUS, 7, "ko.html"), | |
471 }; | |
472 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
473 | |
474 scoped_ptr<HttpStream> stream1(NewTestStream("ok.html")); | |
475 scoped_ptr<HttpStream> stream2(NewTestStream("ko.html")); | |
476 | |
477 HttpRequestHeaders headers1; | |
478 HttpResponseInfo response1; | |
479 EXPECT_EQ(OK, stream1->SendRequest(headers1, | |
480 &response1, callback_.callback())); | |
481 EXPECT_EQ(OK, stream1->ReadResponseHeaders(callback_.callback())); | |
482 TestCompletionCallback callback1; | |
483 std::string expected = "ok.html"; | |
484 scoped_refptr<IOBuffer> buffer(new IOBuffer(expected.size())); | |
485 EXPECT_EQ(ERR_IO_PENDING, | |
486 stream1->ReadResponseBody(buffer.get(), expected.size(), | |
487 callback1.callback())); | |
488 | |
489 HttpRequestHeaders headers2; | |
490 HttpResponseInfo response2; | |
491 TestCompletionCallback callback2; | |
492 EXPECT_EQ(ERR_IO_PENDING, stream2->SendRequest(headers2, &response2, | |
493 callback2.callback())); | |
494 | |
495 data_->RunFor(1); | |
496 EXPECT_LE(OK, callback2.WaitForResult()); | |
497 EXPECT_EQ(ERR_IO_PENDING, stream2->ReadResponseHeaders(callback2.callback())); | |
498 | |
499 data_->RunFor(1); | |
500 EXPECT_EQ(static_cast<int>(expected.size()), callback1.WaitForResult()); | |
501 std::string actual(buffer->data(), expected.size()); | |
502 EXPECT_THAT(actual, StrEq(expected)); | |
503 stream1->Close(false); | |
504 | |
505 data_->StopAfter(8); | |
506 EXPECT_LE(OK, callback2.WaitForResult()); | |
507 ExpectResponse("ko.html", stream2, false); | |
508 stream2->Close(false); | |
509 } | |
510 | |
511 TEST_F(HttpPipelinedConnectionImplTest, UnusedStreamAllowsLaterUse) { | |
512 MockWrite writes[] = { | |
513 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
514 }; | |
515 MockRead reads[] = { | |
516 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), | |
517 MockRead(SYNCHRONOUS, 2, "Content-Length: 7\r\n\r\n"), | |
518 MockRead(SYNCHRONOUS, 3, "ok.html"), | |
519 }; | |
520 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
521 | |
522 scoped_ptr<HttpStream> unused_stream(NewTestStream("unused.html")); | |
523 unused_stream->Close(false); | |
524 | |
525 scoped_ptr<HttpStream> later_stream(NewTestStream("ok.html")); | |
526 TestSyncRequest(later_stream, "ok.html"); | |
527 } | |
528 | |
529 TEST_F(HttpPipelinedConnectionImplTest, UnsentStreamAllowsLaterUse) { | |
530 MockWrite writes[] = { | |
531 MockWrite(ASYNC, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
532 MockWrite(SYNCHRONOUS, 4, "GET /ko.html HTTP/1.1\r\n\r\n"), | |
533 }; | |
534 MockRead reads[] = { | |
535 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n"), | |
536 MockRead(ASYNC, 2, "Content-Length: 7\r\n\r\n"), | |
537 MockRead(ASYNC, 3, "ok.html"), | |
538 MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"), | |
539 MockRead(SYNCHRONOUS, 6, "Content-Length: 7\r\n\r\n"), | |
540 MockRead(SYNCHRONOUS, 7, "ko.html"), | |
541 }; | |
542 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
543 | |
544 scoped_ptr<HttpStream> stream(NewTestStream("ok.html")); | |
545 | |
546 HttpRequestHeaders headers; | |
547 HttpResponseInfo response; | |
548 EXPECT_EQ(ERR_IO_PENDING, stream->SendRequest(headers, &response, | |
549 callback_.callback())); | |
550 | |
551 scoped_ptr<HttpStream> unsent_stream(NewTestStream("unsent.html")); | |
552 HttpRequestHeaders unsent_headers; | |
553 HttpResponseInfo unsent_response; | |
554 EXPECT_EQ(ERR_IO_PENDING, unsent_stream->SendRequest(unsent_headers, | |
555 &unsent_response, | |
556 callback_.callback())); | |
557 unsent_stream->Close(false); | |
558 | |
559 data_->RunFor(1); | |
560 EXPECT_LE(OK, callback_.WaitForResult()); | |
561 | |
562 EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback())); | |
563 data_->RunFor(2); | |
564 EXPECT_LE(OK, callback_.WaitForResult()); | |
565 | |
566 ExpectResponse("ok.html", stream, true); | |
567 | |
568 stream->Close(false); | |
569 | |
570 data_->StopAfter(8); | |
571 scoped_ptr<HttpStream> later_stream(NewTestStream("ko.html")); | |
572 TestSyncRequest(later_stream, "ko.html"); | |
573 } | |
574 | |
575 TEST_F(HttpPipelinedConnectionImplTest, FailedSend) { | |
576 MockWrite writes[] = { | |
577 MockWrite(ASYNC, ERR_FAILED), | |
578 }; | |
579 Initialize(NULL, 0, writes, arraysize(writes)); | |
580 | |
581 scoped_ptr<HttpStream> failed_stream(NewTestStream("ok.html")); | |
582 scoped_ptr<HttpStream> evicted_stream(NewTestStream("evicted.html")); | |
583 scoped_ptr<HttpStream> closed_stream(NewTestStream("closed.html")); | |
584 scoped_ptr<HttpStream> rejected_stream(NewTestStream("rejected.html")); | |
585 | |
586 HttpRequestHeaders headers; | |
587 HttpResponseInfo response; | |
588 TestCompletionCallback failed_callback; | |
589 EXPECT_EQ(ERR_IO_PENDING, | |
590 failed_stream->SendRequest(headers, &response, | |
591 failed_callback.callback())); | |
592 TestCompletionCallback evicted_callback; | |
593 EXPECT_EQ(ERR_IO_PENDING, | |
594 evicted_stream->SendRequest(headers, &response, | |
595 evicted_callback.callback())); | |
596 EXPECT_EQ(ERR_IO_PENDING, closed_stream->SendRequest(headers, &response, | |
597 callback_.callback())); | |
598 closed_stream->Close(false); | |
599 | |
600 data_->RunFor(1); | |
601 EXPECT_EQ(ERR_FAILED, failed_callback.WaitForResult()); | |
602 EXPECT_EQ(ERR_PIPELINE_EVICTION, evicted_callback.WaitForResult()); | |
603 EXPECT_EQ(ERR_PIPELINE_EVICTION, | |
604 rejected_stream->SendRequest(headers, &response, | |
605 callback_.callback())); | |
606 | |
607 failed_stream->Close(true); | |
608 evicted_stream->Close(true); | |
609 rejected_stream->Close(true); | |
610 } | |
611 | |
612 TEST_F(HttpPipelinedConnectionImplTest, ConnectionSuddenlyClosedAfterResponse) { | |
613 MockWrite writes[] = { | |
614 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
615 MockWrite(SYNCHRONOUS, 1, "GET /read_evicted.html HTTP/1.1\r\n\r\n"), | |
616 MockWrite(SYNCHRONOUS, 2, "GET /read_rejected.html HTTP/1.1\r\n\r\n"), | |
617 MockWrite(ASYNC, ERR_SOCKET_NOT_CONNECTED, 5), | |
618 }; | |
619 MockRead reads[] = { | |
620 MockRead(SYNCHRONOUS, 3, "HTTP/1.1 200 OK\r\n\r\n"), | |
621 MockRead(SYNCHRONOUS, 4, "ok.html"), | |
622 MockRead(ASYNC, OK, 6), // Connection closed message. Not read before the | |
623 // ERR_SOCKET_NOT_CONNECTED. | |
624 }; | |
625 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
626 | |
627 scoped_ptr<HttpStream> closed_stream(NewTestStream("ok.html")); | |
628 scoped_ptr<HttpStream> read_evicted_stream( | |
629 NewTestStream("read_evicted.html")); | |
630 scoped_ptr<HttpStream> read_rejected_stream( | |
631 NewTestStream("read_rejected.html")); | |
632 scoped_ptr<HttpStream> send_closed_stream( | |
633 NewTestStream("send_closed.html")); | |
634 scoped_ptr<HttpStream> send_evicted_stream( | |
635 NewTestStream("send_evicted.html")); | |
636 scoped_ptr<HttpStream> send_rejected_stream( | |
637 NewTestStream("send_rejected.html")); | |
638 | |
639 HttpRequestHeaders headers; | |
640 HttpResponseInfo response; | |
641 EXPECT_EQ(OK, closed_stream->SendRequest(headers, | |
642 &response, callback_.callback())); | |
643 EXPECT_EQ(OK, read_evicted_stream->SendRequest(headers, &response, | |
644 callback_.callback())); | |
645 EXPECT_EQ(OK, read_rejected_stream->SendRequest(headers, &response, | |
646 callback_.callback())); | |
647 TestCompletionCallback send_closed_callback; | |
648 EXPECT_EQ(ERR_IO_PENDING, | |
649 send_closed_stream->SendRequest(headers, &response, | |
650 send_closed_callback.callback())); | |
651 TestCompletionCallback send_evicted_callback; | |
652 EXPECT_EQ(ERR_IO_PENDING, | |
653 send_evicted_stream->SendRequest(headers, &response, | |
654 send_evicted_callback.callback())); | |
655 | |
656 TestCompletionCallback read_evicted_callback; | |
657 EXPECT_EQ(ERR_IO_PENDING, | |
658 read_evicted_stream->ReadResponseHeaders( | |
659 read_evicted_callback.callback())); | |
660 | |
661 EXPECT_EQ(OK, closed_stream->ReadResponseHeaders(callback_.callback())); | |
662 ExpectResponse("ok.html", closed_stream, false); | |
663 closed_stream->Close(true); | |
664 | |
665 EXPECT_EQ(ERR_PIPELINE_EVICTION, read_evicted_callback.WaitForResult()); | |
666 read_evicted_stream->Close(true); | |
667 | |
668 EXPECT_EQ(ERR_PIPELINE_EVICTION, | |
669 read_rejected_stream->ReadResponseHeaders(callback_.callback())); | |
670 read_rejected_stream->Close(true); | |
671 | |
672 data_->RunFor(1); | |
673 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, send_closed_callback.WaitForResult()); | |
674 send_closed_stream->Close(true); | |
675 | |
676 EXPECT_EQ(ERR_PIPELINE_EVICTION, send_evicted_callback.WaitForResult()); | |
677 send_evicted_stream->Close(true); | |
678 | |
679 EXPECT_EQ(ERR_PIPELINE_EVICTION, | |
680 send_rejected_stream->SendRequest(headers, &response, | |
681 callback_.callback())); | |
682 send_rejected_stream->Close(true); | |
683 } | |
684 | |
685 TEST_F(HttpPipelinedConnectionImplTest, AbortWhileSending) { | |
686 MockWrite writes[] = { | |
687 MockWrite(ASYNC, 0, "GET /aborts.html HTTP/1.1\r\n\r\n"), | |
688 }; | |
689 Initialize(NULL, 0, writes, arraysize(writes)); | |
690 | |
691 scoped_ptr<HttpStream> aborted_stream(NewTestStream("aborts.html")); | |
692 scoped_ptr<HttpStream> evicted_stream(NewTestStream("evicted.html")); | |
693 | |
694 HttpRequestHeaders headers; | |
695 HttpResponseInfo response; | |
696 TestCompletionCallback aborted_callback; | |
697 EXPECT_EQ(ERR_IO_PENDING, | |
698 aborted_stream->SendRequest(headers, &response, | |
699 aborted_callback.callback())); | |
700 TestCompletionCallback evicted_callback; | |
701 EXPECT_EQ(ERR_IO_PENDING, | |
702 evicted_stream->SendRequest(headers, &response, | |
703 evicted_callback.callback())); | |
704 | |
705 aborted_stream->Close(true); | |
706 EXPECT_EQ(ERR_PIPELINE_EVICTION, evicted_callback.WaitForResult()); | |
707 evicted_stream->Close(true); | |
708 EXPECT_FALSE(aborted_callback.have_result()); | |
709 } | |
710 | |
711 TEST_F(HttpPipelinedConnectionImplTest, AbortWhileSendingSecondRequest) { | |
712 MockWrite writes[] = { | |
713 MockWrite(ASYNC, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
714 MockWrite(ASYNC, 1, "GET /aborts.html HTTP/1.1\r\n\r\n"), | |
715 }; | |
716 Initialize(NULL, 0, writes, arraysize(writes)); | |
717 | |
718 scoped_ptr<HttpStream> ok_stream(NewTestStream("ok.html")); | |
719 scoped_ptr<HttpStream> aborted_stream(NewTestStream("aborts.html")); | |
720 scoped_ptr<HttpStream> evicted_stream(NewTestStream("evicted.html")); | |
721 | |
722 HttpRequestHeaders headers; | |
723 HttpResponseInfo response; | |
724 TestCompletionCallback ok_callback; | |
725 EXPECT_EQ(ERR_IO_PENDING, ok_stream->SendRequest(headers, &response, | |
726 ok_callback.callback())); | |
727 TestCompletionCallback aborted_callback; | |
728 EXPECT_EQ(ERR_IO_PENDING, | |
729 aborted_stream->SendRequest(headers, &response, | |
730 aborted_callback.callback())); | |
731 TestCompletionCallback evicted_callback; | |
732 EXPECT_EQ(ERR_IO_PENDING, | |
733 evicted_stream->SendRequest(headers, &response, | |
734 evicted_callback.callback())); | |
735 | |
736 data_->RunFor(1); | |
737 EXPECT_LE(OK, ok_callback.WaitForResult()); | |
738 base::MessageLoop::current()->RunUntilIdle(); | |
739 aborted_stream->Close(true); | |
740 EXPECT_EQ(ERR_PIPELINE_EVICTION, evicted_callback.WaitForResult()); | |
741 evicted_stream->Close(true); | |
742 EXPECT_FALSE(aborted_callback.have_result()); | |
743 ok_stream->Close(true); | |
744 } | |
745 | |
746 TEST_F(HttpPipelinedConnectionImplTest, AbortWhileReadingHeaders) { | |
747 MockWrite writes[] = { | |
748 MockWrite(SYNCHRONOUS, 0, "GET /aborts.html HTTP/1.1\r\n\r\n"), | |
749 MockWrite(SYNCHRONOUS, 1, "GET /evicted.html HTTP/1.1\r\n\r\n"), | |
750 }; | |
751 MockRead reads[] = { | |
752 MockRead(ASYNC, ERR_FAILED, 2), | |
753 }; | |
754 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
755 | |
756 scoped_ptr<HttpStream> aborted_stream(NewTestStream("aborts.html")); | |
757 scoped_ptr<HttpStream> evicted_stream(NewTestStream("evicted.html")); | |
758 scoped_ptr<HttpStream> rejected_stream(NewTestStream("rejected.html")); | |
759 | |
760 HttpRequestHeaders headers; | |
761 HttpResponseInfo response; | |
762 EXPECT_EQ(OK, | |
763 aborted_stream->SendRequest(headers, &response, | |
764 callback_.callback())); | |
765 EXPECT_EQ(OK, | |
766 evicted_stream->SendRequest(headers, &response, | |
767 callback_.callback())); | |
768 | |
769 EXPECT_EQ(ERR_IO_PENDING, | |
770 aborted_stream->ReadResponseHeaders(callback_.callback())); | |
771 TestCompletionCallback evicted_callback; | |
772 EXPECT_EQ(ERR_IO_PENDING, | |
773 evicted_stream->ReadResponseHeaders(evicted_callback.callback())); | |
774 | |
775 aborted_stream->Close(true); | |
776 EXPECT_EQ(ERR_PIPELINE_EVICTION, evicted_callback.WaitForResult()); | |
777 evicted_stream->Close(true); | |
778 | |
779 EXPECT_EQ(ERR_PIPELINE_EVICTION, | |
780 rejected_stream->SendRequest(headers, &response, | |
781 callback_.callback())); | |
782 rejected_stream->Close(true); | |
783 } | |
784 | |
785 TEST_F(HttpPipelinedConnectionImplTest, PendingResponseAbandoned) { | |
786 MockWrite writes[] = { | |
787 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
788 MockWrite(SYNCHRONOUS, 1, "GET /abandoned.html HTTP/1.1\r\n\r\n"), | |
789 MockWrite(SYNCHRONOUS, 2, "GET /evicted.html HTTP/1.1\r\n\r\n"), | |
790 }; | |
791 MockRead reads[] = { | |
792 MockRead(SYNCHRONOUS, 3, "HTTP/1.1 200 OK\r\n"), | |
793 MockRead(SYNCHRONOUS, 4, "Content-Length: 7\r\n\r\n"), | |
794 MockRead(SYNCHRONOUS, 5, "ok.html"), | |
795 }; | |
796 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
797 | |
798 scoped_ptr<HttpStream> ok_stream(NewTestStream("ok.html")); | |
799 scoped_ptr<HttpStream> abandoned_stream(NewTestStream("abandoned.html")); | |
800 scoped_ptr<HttpStream> evicted_stream(NewTestStream("evicted.html")); | |
801 | |
802 HttpRequestHeaders headers; | |
803 HttpResponseInfo response; | |
804 EXPECT_EQ(OK, ok_stream->SendRequest(headers, &response, | |
805 callback_.callback())); | |
806 EXPECT_EQ(OK, abandoned_stream->SendRequest(headers, &response, | |
807 callback_.callback())); | |
808 EXPECT_EQ(OK, evicted_stream->SendRequest(headers, &response, | |
809 callback_.callback())); | |
810 | |
811 EXPECT_EQ(OK, ok_stream->ReadResponseHeaders(callback_.callback())); | |
812 TestCompletionCallback abandoned_callback; | |
813 EXPECT_EQ(ERR_IO_PENDING, abandoned_stream->ReadResponseHeaders( | |
814 abandoned_callback.callback())); | |
815 TestCompletionCallback evicted_callback; | |
816 EXPECT_EQ(ERR_IO_PENDING, | |
817 evicted_stream->ReadResponseHeaders(evicted_callback.callback())); | |
818 | |
819 abandoned_stream->Close(false); | |
820 | |
821 ExpectResponse("ok.html", ok_stream, false); | |
822 ok_stream->Close(false); | |
823 | |
824 EXPECT_EQ(ERR_PIPELINE_EVICTION, evicted_callback.WaitForResult()); | |
825 evicted_stream->Close(true); | |
826 EXPECT_FALSE(evicted_stream->IsConnectionReusable()); | |
827 } | |
828 | |
829 TEST_F(HttpPipelinedConnectionImplTest, DisconnectedAfterOneRequestRecovery) { | |
830 MockWrite writes[] = { | |
831 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
832 MockWrite(SYNCHRONOUS, 1, "GET /rejected.html HTTP/1.1\r\n\r\n"), | |
833 MockWrite(ASYNC, ERR_SOCKET_NOT_CONNECTED, 5), | |
834 MockWrite(SYNCHRONOUS, ERR_SOCKET_NOT_CONNECTED, 7), | |
835 }; | |
836 MockRead reads[] = { | |
837 MockRead(SYNCHRONOUS, 2, "HTTP/1.1 200 OK\r\n"), | |
838 MockRead(SYNCHRONOUS, 3, "Content-Length: 7\r\n\r\n"), | |
839 MockRead(SYNCHRONOUS, 4, "ok.html"), | |
840 MockRead(SYNCHRONOUS, ERR_SOCKET_NOT_CONNECTED, 6), | |
841 }; | |
842 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
843 | |
844 scoped_ptr<HttpStream> ok_stream(NewTestStream("ok.html")); | |
845 scoped_ptr<HttpStream> rejected_read_stream(NewTestStream("rejected.html")); | |
846 scoped_ptr<HttpStream> evicted_send_stream(NewTestStream("evicted.html")); | |
847 scoped_ptr<HttpStream> rejected_send_stream(NewTestStream("rejected.html")); | |
848 | |
849 HttpRequestHeaders headers; | |
850 HttpResponseInfo response; | |
851 EXPECT_EQ(OK, ok_stream->SendRequest(headers, | |
852 &response, callback_.callback())); | |
853 EXPECT_EQ(OK, rejected_read_stream->SendRequest(headers, &response, | |
854 callback_.callback())); | |
855 | |
856 EXPECT_EQ(OK, ok_stream->ReadResponseHeaders(callback_.callback())); | |
857 ExpectResponse("ok.html", ok_stream, false); | |
858 ok_stream->Close(false); | |
859 | |
860 TestCompletionCallback read_callback; | |
861 EXPECT_EQ(ERR_IO_PENDING, | |
862 evicted_send_stream->SendRequest(headers, &response, | |
863 read_callback.callback())); | |
864 data_->RunFor(1); | |
865 EXPECT_EQ(ERR_PIPELINE_EVICTION, read_callback.WaitForResult()); | |
866 | |
867 EXPECT_EQ(ERR_PIPELINE_EVICTION, | |
868 rejected_read_stream->ReadResponseHeaders(callback_.callback())); | |
869 EXPECT_EQ(ERR_PIPELINE_EVICTION, | |
870 rejected_send_stream->SendRequest(headers, &response, | |
871 callback_.callback())); | |
872 | |
873 rejected_read_stream->Close(true); | |
874 rejected_send_stream->Close(true); | |
875 } | |
876 | |
877 TEST_F(HttpPipelinedConnectionImplTest, DisconnectedPendingReadRecovery) { | |
878 MockWrite writes[] = { | |
879 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
880 MockWrite(SYNCHRONOUS, 1, "GET /evicted.html HTTP/1.1\r\n\r\n"), | |
881 }; | |
882 MockRead reads[] = { | |
883 MockRead(SYNCHRONOUS, 2, "HTTP/1.1 200 OK\r\n"), | |
884 MockRead(SYNCHRONOUS, 3, "Content-Length: 7\r\n\r\n"), | |
885 MockRead(SYNCHRONOUS, 4, "ok.html"), | |
886 MockRead(SYNCHRONOUS, ERR_SOCKET_NOT_CONNECTED, 5), | |
887 }; | |
888 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
889 | |
890 scoped_ptr<HttpStream> ok_stream(NewTestStream("ok.html")); | |
891 scoped_ptr<HttpStream> evicted_stream(NewTestStream("evicted.html")); | |
892 | |
893 HttpRequestHeaders headers; | |
894 HttpResponseInfo response; | |
895 EXPECT_EQ(OK, ok_stream->SendRequest(headers, | |
896 &response, callback_.callback())); | |
897 EXPECT_EQ(OK, evicted_stream->SendRequest(headers, &response, | |
898 callback_.callback())); | |
899 | |
900 EXPECT_EQ(OK, ok_stream->ReadResponseHeaders(callback_.callback())); | |
901 ExpectResponse("ok.html", ok_stream, false); | |
902 | |
903 TestCompletionCallback evicted_callback; | |
904 EXPECT_EQ(ERR_IO_PENDING, | |
905 evicted_stream->ReadResponseHeaders(evicted_callback.callback())); | |
906 | |
907 ok_stream->Close(false); | |
908 | |
909 EXPECT_EQ(ERR_PIPELINE_EVICTION, evicted_callback.WaitForResult()); | |
910 evicted_stream->Close(false); | |
911 } | |
912 | |
913 TEST_F(HttpPipelinedConnectionImplTest, CloseCalledBeforeNextReadLoop) { | |
914 MockWrite writes[] = { | |
915 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
916 MockWrite(SYNCHRONOUS, 1, "GET /evicted.html HTTP/1.1\r\n\r\n"), | |
917 }; | |
918 MockRead reads[] = { | |
919 MockRead(SYNCHRONOUS, 2, "HTTP/1.1 200 OK\r\n"), | |
920 MockRead(SYNCHRONOUS, 3, "Content-Length: 7\r\n\r\n"), | |
921 MockRead(SYNCHRONOUS, 4, "ok.html"), | |
922 MockRead(SYNCHRONOUS, ERR_SOCKET_NOT_CONNECTED, 5), | |
923 }; | |
924 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
925 | |
926 scoped_ptr<HttpStream> ok_stream(NewTestStream("ok.html")); | |
927 scoped_ptr<HttpStream> evicted_stream(NewTestStream("evicted.html")); | |
928 | |
929 HttpRequestHeaders headers; | |
930 HttpResponseInfo response; | |
931 EXPECT_EQ(OK, ok_stream->SendRequest(headers, | |
932 &response, callback_.callback())); | |
933 EXPECT_EQ(OK, evicted_stream->SendRequest(headers, &response, | |
934 callback_.callback())); | |
935 | |
936 EXPECT_EQ(OK, ok_stream->ReadResponseHeaders(callback_.callback())); | |
937 ExpectResponse("ok.html", ok_stream, false); | |
938 | |
939 TestCompletionCallback evicted_callback; | |
940 EXPECT_EQ(ERR_IO_PENDING, | |
941 evicted_stream->ReadResponseHeaders(evicted_callback.callback())); | |
942 | |
943 ok_stream->Close(false); | |
944 evicted_stream->Close(false); | |
945 } | |
946 | |
947 TEST_F(HttpPipelinedConnectionImplTest, CloseCalledBeforeReadCallback) { | |
948 MockWrite writes[] = { | |
949 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
950 MockWrite(SYNCHRONOUS, 1, "GET /evicted.html HTTP/1.1\r\n\r\n"), | |
951 }; | |
952 MockRead reads[] = { | |
953 MockRead(SYNCHRONOUS, 2, "HTTP/1.1 200 OK\r\n"), | |
954 MockRead(SYNCHRONOUS, 3, "Content-Length: 7\r\n\r\n"), | |
955 MockRead(SYNCHRONOUS, 4, "ok.html"), | |
956 MockRead(SYNCHRONOUS, ERR_SOCKET_NOT_CONNECTED, 5), | |
957 }; | |
958 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
959 | |
960 scoped_ptr<HttpStream> ok_stream(NewTestStream("ok.html")); | |
961 scoped_ptr<HttpStream> evicted_stream(NewTestStream("evicted.html")); | |
962 | |
963 HttpRequestHeaders headers; | |
964 HttpResponseInfo response; | |
965 EXPECT_EQ(OK, ok_stream->SendRequest(headers, | |
966 &response, callback_.callback())); | |
967 EXPECT_EQ(OK, evicted_stream->SendRequest(headers, &response, | |
968 callback_.callback())); | |
969 | |
970 EXPECT_EQ(OK, ok_stream->ReadResponseHeaders(callback_.callback())); | |
971 ExpectResponse("ok.html", ok_stream, false); | |
972 | |
973 TestCompletionCallback evicted_callback; | |
974 EXPECT_EQ(ERR_IO_PENDING, | |
975 evicted_stream->ReadResponseHeaders(evicted_callback.callback())); | |
976 | |
977 ok_stream->Close(false); | |
978 | |
979 // The posted tasks should be: | |
980 // 1. DoReadHeadersLoop, which will post: | |
981 // 2. InvokeUserCallback | |
982 SuddenCloseObserver observer(evicted_stream.get(), 2); | |
983 base::MessageLoop::current()->AddTaskObserver(&observer); | |
984 base::MessageLoop::current()->RunUntilIdle(); | |
985 EXPECT_FALSE(evicted_callback.have_result()); | |
986 } | |
987 | |
988 class StreamDeleter { | |
989 public: | |
990 StreamDeleter(HttpStream* stream) | |
991 : stream_(stream), | |
992 callback_(base::Bind(&StreamDeleter::OnIOComplete, | |
993 base::Unretained(this))) { | |
994 } | |
995 | |
996 ~StreamDeleter() { | |
997 EXPECT_FALSE(stream_); | |
998 } | |
999 | |
1000 const CompletionCallback& callback() { return callback_; } | |
1001 | |
1002 private: | |
1003 void OnIOComplete(int result) { | |
1004 stream_->Close(true); | |
1005 stream_.reset(); | |
1006 } | |
1007 | |
1008 scoped_ptr<HttpStream> stream_; | |
1009 CompletionCallback callback_; | |
1010 }; | |
1011 | |
1012 TEST_F(HttpPipelinedConnectionImplTest, CloseCalledDuringSendCallback) { | |
1013 MockWrite writes[] = { | |
1014 MockWrite(ASYNC, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
1015 }; | |
1016 Initialize(NULL, 0, writes, arraysize(writes)); | |
1017 | |
1018 HttpStream* stream(NewTestStream("ok.html")); | |
1019 | |
1020 StreamDeleter deleter(stream); | |
1021 HttpRequestHeaders headers; | |
1022 HttpResponseInfo response; | |
1023 EXPECT_EQ(ERR_IO_PENDING, stream->SendRequest(headers, &response, | |
1024 deleter.callback())); | |
1025 data_->RunFor(1); | |
1026 } | |
1027 | |
1028 TEST_F(HttpPipelinedConnectionImplTest, CloseCalledDuringReadCallback) { | |
1029 MockWrite writes[] = { | |
1030 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
1031 }; | |
1032 MockRead reads[] = { | |
1033 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), | |
1034 MockRead(ASYNC, 2, "Content-Length: 7\r\n\r\n"), | |
1035 }; | |
1036 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
1037 | |
1038 HttpStream* stream(NewTestStream("ok.html")); | |
1039 | |
1040 HttpRequestHeaders headers; | |
1041 HttpResponseInfo response; | |
1042 EXPECT_EQ(OK, stream->SendRequest(headers, | |
1043 &response, callback_.callback())); | |
1044 | |
1045 StreamDeleter deleter(stream); | |
1046 EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(deleter.callback())); | |
1047 data_->RunFor(1); | |
1048 } | |
1049 | |
1050 TEST_F(HttpPipelinedConnectionImplTest, | |
1051 CloseCalledDuringReadCallbackWithPendingRead) { | |
1052 MockWrite writes[] = { | |
1053 MockWrite(SYNCHRONOUS, 0, "GET /failed.html HTTP/1.1\r\n\r\n"), | |
1054 MockWrite(SYNCHRONOUS, 1, "GET /evicted.html HTTP/1.1\r\n\r\n"), | |
1055 }; | |
1056 MockRead reads[] = { | |
1057 MockRead(SYNCHRONOUS, 2, "HTTP/1.1 200 OK\r\n"), | |
1058 MockRead(ASYNC, 3, "Content-Length: 7\r\n\r\n"), | |
1059 }; | |
1060 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
1061 | |
1062 HttpStream* failed_stream(NewTestStream("failed.html")); | |
1063 HttpStream* evicted_stream(NewTestStream("evicted.html")); | |
1064 | |
1065 HttpRequestHeaders headers; | |
1066 HttpResponseInfo response; | |
1067 EXPECT_EQ(OK, failed_stream->SendRequest(headers, &response, | |
1068 callback_.callback())); | |
1069 EXPECT_EQ(OK, evicted_stream->SendRequest(headers, &response, | |
1070 callback_.callback())); | |
1071 | |
1072 StreamDeleter failed_deleter(failed_stream); | |
1073 EXPECT_EQ(ERR_IO_PENDING, | |
1074 failed_stream->ReadResponseHeaders(failed_deleter.callback())); | |
1075 StreamDeleter evicted_deleter(evicted_stream); | |
1076 EXPECT_EQ(ERR_IO_PENDING, | |
1077 evicted_stream->ReadResponseHeaders(evicted_deleter.callback())); | |
1078 data_->RunFor(1); | |
1079 } | |
1080 | |
1081 TEST_F(HttpPipelinedConnectionImplTest, CloseOtherDuringReadCallback) { | |
1082 MockWrite writes[] = { | |
1083 MockWrite(SYNCHRONOUS, 0, "GET /deleter.html HTTP/1.1\r\n\r\n"), | |
1084 MockWrite(SYNCHRONOUS, 1, "GET /deleted.html HTTP/1.1\r\n\r\n"), | |
1085 }; | |
1086 MockRead reads[] = { | |
1087 MockRead(SYNCHRONOUS, 2, "HTTP/1.1 200 OK\r\n"), | |
1088 MockRead(ASYNC, 3, "Content-Length: 7\r\n\r\n"), | |
1089 }; | |
1090 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
1091 | |
1092 scoped_ptr<HttpStream> deleter_stream(NewTestStream("deleter.html")); | |
1093 HttpStream* deleted_stream(NewTestStream("deleted.html")); | |
1094 | |
1095 HttpRequestHeaders headers; | |
1096 HttpResponseInfo response; | |
1097 EXPECT_EQ(OK, deleter_stream->SendRequest(headers, | |
1098 &response, callback_.callback())); | |
1099 EXPECT_EQ(OK, deleted_stream->SendRequest(headers, | |
1100 &response, callback_.callback())); | |
1101 | |
1102 StreamDeleter deleter(deleted_stream); | |
1103 EXPECT_EQ(ERR_IO_PENDING, | |
1104 deleter_stream->ReadResponseHeaders(deleter.callback())); | |
1105 EXPECT_EQ(ERR_IO_PENDING, | |
1106 deleted_stream->ReadResponseHeaders(callback_.callback())); | |
1107 data_->RunFor(1); | |
1108 } | |
1109 | |
1110 TEST_F(HttpPipelinedConnectionImplTest, CloseBeforeSendCallbackRuns) { | |
1111 MockWrite writes[] = { | |
1112 MockWrite(ASYNC, 0, "GET /close.html HTTP/1.1\r\n\r\n"), | |
1113 MockWrite(ASYNC, 1, "GET /dummy.html HTTP/1.1\r\n\r\n"), | |
1114 }; | |
1115 Initialize(NULL, 0, writes, arraysize(writes)); | |
1116 | |
1117 scoped_ptr<HttpStream> close_stream(NewTestStream("close.html")); | |
1118 scoped_ptr<HttpStream> dummy_stream(NewTestStream("dummy.html")); | |
1119 | |
1120 scoped_ptr<TestCompletionCallback> close_callback( | |
1121 new TestCompletionCallback); | |
1122 HttpRequestHeaders headers; | |
1123 HttpResponseInfo response; | |
1124 EXPECT_EQ(ERR_IO_PENDING, | |
1125 close_stream->SendRequest(headers, | |
1126 &response, close_callback->callback())); | |
1127 | |
1128 data_->RunFor(1); | |
1129 EXPECT_FALSE(close_callback->have_result()); | |
1130 | |
1131 close_stream->Close(false); | |
1132 close_stream.reset(); | |
1133 close_callback.reset(); | |
1134 | |
1135 base::MessageLoop::current()->RunUntilIdle(); | |
1136 } | |
1137 | |
1138 TEST_F(HttpPipelinedConnectionImplTest, CloseBeforeReadCallbackRuns) { | |
1139 MockWrite writes[] = { | |
1140 MockWrite(SYNCHRONOUS, 0, "GET /close.html HTTP/1.1\r\n\r\n"), | |
1141 MockWrite(SYNCHRONOUS, 3, "GET /dummy.html HTTP/1.1\r\n\r\n"), | |
1142 }; | |
1143 MockRead reads[] = { | |
1144 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), | |
1145 MockRead(ASYNC, 2, "Content-Length: 7\r\n\r\n"), | |
1146 }; | |
1147 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
1148 | |
1149 scoped_ptr<HttpStream> close_stream(NewTestStream("close.html")); | |
1150 scoped_ptr<HttpStream> dummy_stream(NewTestStream("dummy.html")); | |
1151 | |
1152 HttpRequestHeaders headers; | |
1153 HttpResponseInfo response; | |
1154 EXPECT_EQ(OK, close_stream->SendRequest(headers, | |
1155 &response, callback_.callback())); | |
1156 | |
1157 scoped_ptr<TestCompletionCallback> close_callback( | |
1158 new TestCompletionCallback); | |
1159 EXPECT_EQ(ERR_IO_PENDING, | |
1160 close_stream->ReadResponseHeaders(close_callback->callback())); | |
1161 | |
1162 data_->RunFor(1); | |
1163 EXPECT_FALSE(close_callback->have_result()); | |
1164 | |
1165 close_stream->Close(false); | |
1166 close_stream.reset(); | |
1167 close_callback.reset(); | |
1168 | |
1169 base::MessageLoop::current()->RunUntilIdle(); | |
1170 } | |
1171 | |
1172 TEST_F(HttpPipelinedConnectionImplTest, AbortWhileSendQueued) { | |
1173 MockWrite writes[] = { | |
1174 MockWrite(ASYNC, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
1175 MockWrite(ASYNC, 1, "GET /ko.html HTTP/1.1\r\n\r\n"), | |
1176 }; | |
1177 Initialize(NULL, 0, writes, arraysize(writes)); | |
1178 | |
1179 scoped_ptr<HttpStream> stream1(NewTestStream("ok.html")); | |
1180 scoped_ptr<HttpStream> stream2(NewTestStream("ko.html")); | |
1181 | |
1182 HttpRequestHeaders headers1; | |
1183 HttpResponseInfo response1; | |
1184 TestCompletionCallback callback1; | |
1185 EXPECT_EQ(ERR_IO_PENDING, stream1->SendRequest(headers1, &response1, | |
1186 callback1.callback())); | |
1187 | |
1188 HttpRequestHeaders headers2; | |
1189 HttpResponseInfo response2; | |
1190 TestCompletionCallback callback2; | |
1191 EXPECT_EQ(ERR_IO_PENDING, stream2->SendRequest(headers2, &response2, | |
1192 callback2.callback())); | |
1193 | |
1194 stream2.reset(); | |
1195 stream1->Close(true); | |
1196 | |
1197 EXPECT_FALSE(callback2.have_result()); | |
1198 } | |
1199 | |
1200 TEST_F(HttpPipelinedConnectionImplTest, NoGapBetweenCloseAndEviction) { | |
1201 MockWrite writes[] = { | |
1202 MockWrite(SYNCHRONOUS, 0, "GET /close.html HTTP/1.1\r\n\r\n"), | |
1203 MockWrite(SYNCHRONOUS, 2, "GET /dummy.html HTTP/1.1\r\n\r\n"), | |
1204 }; | |
1205 MockRead reads[] = { | |
1206 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), | |
1207 MockRead(ASYNC, 3, "Content-Length: 7\r\n\r\n"), | |
1208 }; | |
1209 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
1210 | |
1211 scoped_ptr<HttpStream> close_stream(NewTestStream("close.html")); | |
1212 scoped_ptr<HttpStream> dummy_stream(NewTestStream("dummy.html")); | |
1213 | |
1214 HttpRequestHeaders headers; | |
1215 HttpResponseInfo response; | |
1216 EXPECT_EQ(OK, close_stream->SendRequest(headers, &response, | |
1217 callback_.callback())); | |
1218 | |
1219 TestCompletionCallback close_callback; | |
1220 EXPECT_EQ(ERR_IO_PENDING, | |
1221 close_stream->ReadResponseHeaders(close_callback.callback())); | |
1222 | |
1223 EXPECT_EQ(OK, dummy_stream->SendRequest(headers, &response, | |
1224 callback_.callback())); | |
1225 | |
1226 TestCompletionCallback dummy_callback; | |
1227 EXPECT_EQ(ERR_IO_PENDING, | |
1228 dummy_stream->ReadResponseHeaders(dummy_callback.callback())); | |
1229 | |
1230 close_stream->Close(true); | |
1231 close_stream.reset(); | |
1232 | |
1233 EXPECT_TRUE(dummy_callback.have_result()); | |
1234 EXPECT_EQ(ERR_PIPELINE_EVICTION, dummy_callback.WaitForResult()); | |
1235 dummy_stream->Close(true); | |
1236 dummy_stream.reset(); | |
1237 pipeline_.reset(); | |
1238 } | |
1239 | |
1240 TEST_F(HttpPipelinedConnectionImplTest, RecoverFromDrainOnRedirect) { | |
1241 MockWrite writes[] = { | |
1242 MockWrite(SYNCHRONOUS, 0, "GET /redirect.html HTTP/1.1\r\n\r\n"), | |
1243 MockWrite(SYNCHRONOUS, 1, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
1244 }; | |
1245 MockRead reads[] = { | |
1246 MockRead(SYNCHRONOUS, 2, | |
1247 "HTTP/1.1 302 OK\r\n" | |
1248 "Content-Length: 8\r\n\r\n" | |
1249 "redirect"), | |
1250 MockRead(SYNCHRONOUS, 3, | |
1251 "HTTP/1.1 200 OK\r\n" | |
1252 "Content-Length: 7\r\n\r\n" | |
1253 "ok.html"), | |
1254 }; | |
1255 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
1256 | |
1257 scoped_ptr<HttpStream> stream1(NewTestStream("redirect.html")); | |
1258 scoped_ptr<HttpStream> stream2(NewTestStream("ok.html")); | |
1259 | |
1260 HttpRequestHeaders headers1; | |
1261 HttpResponseInfo response1; | |
1262 EXPECT_EQ(OK, stream1->SendRequest(headers1, | |
1263 &response1, callback_.callback())); | |
1264 HttpRequestHeaders headers2; | |
1265 HttpResponseInfo response2; | |
1266 EXPECT_EQ(OK, stream2->SendRequest(headers2, | |
1267 &response2, callback_.callback())); | |
1268 | |
1269 EXPECT_EQ(OK, stream1->ReadResponseHeaders(callback_.callback())); | |
1270 stream1.release()->Drain(NULL); | |
1271 | |
1272 EXPECT_EQ(OK, stream2->ReadResponseHeaders(callback_.callback())); | |
1273 ExpectResponse("ok.html", stream2, false); | |
1274 stream2->Close(false); | |
1275 } | |
1276 | |
1277 TEST_F(HttpPipelinedConnectionImplTest, EvictAfterDrainOfUnknownSize) { | |
1278 MockWrite writes[] = { | |
1279 MockWrite(SYNCHRONOUS, 0, "GET /redirect.html HTTP/1.1\r\n\r\n"), | |
1280 MockWrite(SYNCHRONOUS, 1, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
1281 }; | |
1282 MockRead reads[] = { | |
1283 MockRead(SYNCHRONOUS, 2, | |
1284 "HTTP/1.1 302 OK\r\n\r\n" | |
1285 "redirect"), | |
1286 }; | |
1287 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
1288 | |
1289 scoped_ptr<HttpStream> stream1(NewTestStream("redirect.html")); | |
1290 scoped_ptr<HttpStream> stream2(NewTestStream("ok.html")); | |
1291 | |
1292 HttpRequestHeaders headers1; | |
1293 HttpResponseInfo response1; | |
1294 EXPECT_EQ(OK, stream1->SendRequest(headers1, | |
1295 &response1, callback_.callback())); | |
1296 HttpRequestHeaders headers2; | |
1297 HttpResponseInfo response2; | |
1298 EXPECT_EQ(OK, stream2->SendRequest(headers2, | |
1299 &response2, callback_.callback())); | |
1300 | |
1301 EXPECT_EQ(OK, stream1->ReadResponseHeaders(callback_.callback())); | |
1302 stream1.release()->Drain(NULL); | |
1303 | |
1304 EXPECT_EQ(ERR_PIPELINE_EVICTION, | |
1305 stream2->ReadResponseHeaders(callback_.callback())); | |
1306 stream2->Close(false); | |
1307 } | |
1308 | |
1309 TEST_F(HttpPipelinedConnectionImplTest, EvictAfterFailedDrain) { | |
1310 MockWrite writes[] = { | |
1311 MockWrite(SYNCHRONOUS, 0, "GET /redirect.html HTTP/1.1\r\n\r\n"), | |
1312 MockWrite(SYNCHRONOUS, 1, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
1313 }; | |
1314 MockRead reads[] = { | |
1315 MockRead(SYNCHRONOUS, 2, | |
1316 "HTTP/1.1 302 OK\r\n" | |
1317 "Content-Length: 8\r\n\r\n"), | |
1318 MockRead(SYNCHRONOUS, ERR_SOCKET_NOT_CONNECTED, 3), | |
1319 }; | |
1320 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
1321 | |
1322 scoped_ptr<HttpStream> stream1(NewTestStream("redirect.html")); | |
1323 scoped_ptr<HttpStream> stream2(NewTestStream("ok.html")); | |
1324 | |
1325 HttpRequestHeaders headers1; | |
1326 HttpResponseInfo response1; | |
1327 EXPECT_EQ(OK, stream1->SendRequest(headers1, | |
1328 &response1, callback_.callback())); | |
1329 HttpRequestHeaders headers2; | |
1330 HttpResponseInfo response2; | |
1331 EXPECT_EQ(OK, stream2->SendRequest(headers2, | |
1332 &response2, callback_.callback())); | |
1333 | |
1334 | |
1335 EXPECT_EQ(OK, stream1->ReadResponseHeaders(callback_.callback())); | |
1336 stream1.release()->Drain(NULL); | |
1337 | |
1338 EXPECT_EQ(ERR_PIPELINE_EVICTION, | |
1339 stream2->ReadResponseHeaders(callback_.callback())); | |
1340 stream2->Close(false); | |
1341 } | |
1342 | |
1343 TEST_F(HttpPipelinedConnectionImplTest, EvictIfDrainingChunkedEncoding) { | |
1344 MockWrite writes[] = { | |
1345 MockWrite(SYNCHRONOUS, 0, "GET /redirect.html HTTP/1.1\r\n\r\n"), | |
1346 MockWrite(SYNCHRONOUS, 1, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
1347 }; | |
1348 MockRead reads[] = { | |
1349 MockRead(SYNCHRONOUS, 2, | |
1350 "HTTP/1.1 302 OK\r\n" | |
1351 "Transfer-Encoding: chunked\r\n\r\n"), | |
1352 MockRead(SYNCHRONOUS, 3, | |
1353 "jibberish"), | |
1354 }; | |
1355 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
1356 | |
1357 scoped_ptr<HttpStream> stream1(NewTestStream("redirect.html")); | |
1358 scoped_ptr<HttpStream> stream2(NewTestStream("ok.html")); | |
1359 | |
1360 HttpRequestHeaders headers1; | |
1361 HttpResponseInfo response1; | |
1362 EXPECT_EQ(OK, stream1->SendRequest(headers1, | |
1363 &response1, callback_.callback())); | |
1364 HttpRequestHeaders headers2; | |
1365 HttpResponseInfo response2; | |
1366 EXPECT_EQ(OK, stream2->SendRequest(headers2, | |
1367 &response2, callback_.callback())); | |
1368 | |
1369 | |
1370 EXPECT_EQ(OK, stream1->ReadResponseHeaders(callback_.callback())); | |
1371 stream1.release()->Drain(NULL); | |
1372 | |
1373 EXPECT_EQ(ERR_PIPELINE_EVICTION, | |
1374 stream2->ReadResponseHeaders(callback_.callback())); | |
1375 stream2->Close(false); | |
1376 } | |
1377 | |
1378 TEST_F(HttpPipelinedConnectionImplTest, EvictionDueToMissingContentLength) { | |
1379 MockWrite writes[] = { | |
1380 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
1381 MockWrite(SYNCHRONOUS, 1, "GET /evicted.html HTTP/1.1\r\n\r\n"), | |
1382 MockWrite(SYNCHRONOUS, 2, "GET /rejected.html HTTP/1.1\r\n\r\n"), | |
1383 }; | |
1384 MockRead reads[] = { | |
1385 MockRead(ASYNC, 3, "HTTP/1.1 200 OK\r\n\r\n"), | |
1386 MockRead(SYNCHRONOUS, 4, "ok.html"), | |
1387 MockRead(SYNCHRONOUS, OK, 5), | |
1388 }; | |
1389 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
1390 | |
1391 scoped_ptr<HttpStream> ok_stream(NewTestStream("ok.html")); | |
1392 scoped_ptr<HttpStream> evicted_stream(NewTestStream("evicted.html")); | |
1393 scoped_ptr<HttpStream> rejected_stream(NewTestStream("rejected.html")); | |
1394 | |
1395 HttpRequestHeaders headers; | |
1396 HttpResponseInfo response; | |
1397 EXPECT_EQ(OK, ok_stream->SendRequest(headers, | |
1398 &response, callback_.callback())); | |
1399 EXPECT_EQ(OK, evicted_stream->SendRequest(headers, | |
1400 &response, callback_.callback())); | |
1401 EXPECT_EQ(OK, rejected_stream->SendRequest(headers, | |
1402 &response, callback_.callback())); | |
1403 | |
1404 TestCompletionCallback ok_callback; | |
1405 EXPECT_EQ(ERR_IO_PENDING, | |
1406 ok_stream->ReadResponseHeaders(ok_callback.callback())); | |
1407 | |
1408 TestCompletionCallback evicted_callback; | |
1409 EXPECT_EQ(ERR_IO_PENDING, | |
1410 evicted_stream->ReadResponseHeaders(evicted_callback.callback())); | |
1411 | |
1412 data_->RunFor(1); | |
1413 EXPECT_LE(OK, ok_callback.WaitForResult()); | |
1414 data_->StopAfter(10); | |
1415 | |
1416 ExpectResponse("ok.html", ok_stream, false); | |
1417 ok_stream->Close(false); | |
1418 | |
1419 EXPECT_EQ(ERR_PIPELINE_EVICTION, | |
1420 rejected_stream->ReadResponseHeaders(callback_.callback())); | |
1421 rejected_stream->Close(true); | |
1422 EXPECT_EQ(ERR_PIPELINE_EVICTION, evicted_callback.WaitForResult()); | |
1423 evicted_stream->Close(true); | |
1424 } | |
1425 | |
1426 TEST_F(HttpPipelinedConnectionImplTest, FeedbackOnSocketError) { | |
1427 MockWrite writes[] = { | |
1428 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
1429 }; | |
1430 MockRead reads[] = { | |
1431 MockRead(SYNCHRONOUS, ERR_FAILED, 1), | |
1432 }; | |
1433 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
1434 | |
1435 EXPECT_CALL(delegate_, | |
1436 OnPipelineFeedback( | |
1437 pipeline_.get(), | |
1438 HttpPipelinedConnection::PIPELINE_SOCKET_ERROR)) | |
1439 .Times(1); | |
1440 | |
1441 scoped_ptr<HttpStream> stream(NewTestStream("ok.html")); | |
1442 HttpRequestHeaders headers; | |
1443 HttpResponseInfo response; | |
1444 EXPECT_EQ(OK, stream->SendRequest(headers, | |
1445 &response, callback_.callback())); | |
1446 EXPECT_EQ(ERR_FAILED, stream->ReadResponseHeaders(callback_.callback())); | |
1447 } | |
1448 | |
1449 TEST_F(HttpPipelinedConnectionImplTest, FeedbackOnNoInternetConnection) { | |
1450 MockWrite writes[] = { | |
1451 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
1452 }; | |
1453 MockRead reads[] = { | |
1454 MockRead(SYNCHRONOUS, ERR_INTERNET_DISCONNECTED, 1), | |
1455 }; | |
1456 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
1457 | |
1458 EXPECT_CALL(delegate_, OnPipelineFeedback(_, _)) | |
1459 .Times(0); | |
1460 | |
1461 scoped_ptr<HttpStream> stream(NewTestStream("ok.html")); | |
1462 HttpRequestHeaders headers; | |
1463 HttpResponseInfo response; | |
1464 EXPECT_EQ(OK, stream->SendRequest(headers, | |
1465 &response, callback_.callback())); | |
1466 EXPECT_EQ(ERR_INTERNET_DISCONNECTED, | |
1467 stream->ReadResponseHeaders(callback_.callback())); | |
1468 } | |
1469 | |
1470 TEST_F(HttpPipelinedConnectionImplTest, FeedbackOnHttp10) { | |
1471 MockWrite writes[] = { | |
1472 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
1473 }; | |
1474 MockRead reads[] = { | |
1475 MockRead(SYNCHRONOUS, 1, "HTTP/1.0 200 OK\r\n"), | |
1476 MockRead(SYNCHRONOUS, 2, "Content-Length: 7\r\n"), | |
1477 MockRead(SYNCHRONOUS, 3, "Connection: keep-alive\r\n\r\n"), | |
1478 MockRead(SYNCHRONOUS, 4, "ok.html"), | |
1479 }; | |
1480 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
1481 | |
1482 EXPECT_CALL(delegate_, | |
1483 OnPipelineFeedback(pipeline_.get(), | |
1484 HttpPipelinedConnection::OLD_HTTP_VERSION)) | |
1485 .Times(1); | |
1486 | |
1487 scoped_ptr<HttpStream> stream(NewTestStream("ok.html")); | |
1488 TestSyncRequest(stream, "ok.html"); | |
1489 } | |
1490 | |
1491 TEST_F(HttpPipelinedConnectionImplTest, FeedbackOnMustClose) { | |
1492 MockWrite writes[] = { | |
1493 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
1494 }; | |
1495 MockRead reads[] = { | |
1496 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), | |
1497 MockRead(SYNCHRONOUS, 2, "Content-Length: 7\r\n"), | |
1498 MockRead(SYNCHRONOUS, 3, "Connection: close\r\n\r\n"), | |
1499 MockRead(SYNCHRONOUS, 4, "ok.html"), | |
1500 }; | |
1501 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
1502 | |
1503 EXPECT_CALL(delegate_, | |
1504 OnPipelineFeedback( | |
1505 pipeline_.get(), | |
1506 HttpPipelinedConnection::MUST_CLOSE_CONNECTION)) | |
1507 .Times(1); | |
1508 | |
1509 scoped_ptr<HttpStream> stream(NewTestStream("ok.html")); | |
1510 TestSyncRequest(stream, "ok.html"); | |
1511 } | |
1512 | |
1513 TEST_F(HttpPipelinedConnectionImplTest, FeedbackOnNoContentLength) { | |
1514 MockWrite writes[] = { | |
1515 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
1516 }; | |
1517 MockRead reads[] = { | |
1518 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n\r\n"), | |
1519 MockRead(SYNCHRONOUS, 2, "ok.html"), | |
1520 }; | |
1521 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
1522 | |
1523 EXPECT_CALL(delegate_, | |
1524 OnPipelineFeedback( | |
1525 pipeline_.get(), | |
1526 HttpPipelinedConnection::MUST_CLOSE_CONNECTION)) | |
1527 .Times(1); | |
1528 | |
1529 scoped_ptr<HttpStream> stream(NewTestStream("ok.html")); | |
1530 TestSyncRequest(stream, "ok.html"); | |
1531 } | |
1532 | |
1533 TEST_F(HttpPipelinedConnectionImplTest, FeedbackOnAuthenticationRequired) { | |
1534 MockWrite writes[] = { | |
1535 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
1536 }; | |
1537 MockRead reads[] = { | |
1538 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 401 Unauthorized\r\n"), | |
1539 MockRead(SYNCHRONOUS, 2, "WWW-Authenticate: NTLM\r\n"), | |
1540 MockRead(SYNCHRONOUS, 3, "Content-Length: 7\r\n\r\n"), | |
1541 MockRead(SYNCHRONOUS, 4, "ok.html"), | |
1542 }; | |
1543 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
1544 | |
1545 EXPECT_CALL(delegate_, | |
1546 OnPipelineFeedback( | |
1547 pipeline_.get(), | |
1548 HttpPipelinedConnection::AUTHENTICATION_REQUIRED)) | |
1549 .Times(1); | |
1550 | |
1551 scoped_ptr<HttpStream> stream(NewTestStream("ok.html")); | |
1552 TestSyncRequest(stream, "ok.html"); | |
1553 } | |
1554 | |
1555 TEST_F(HttpPipelinedConnectionImplTest, OnPipelineHasCapacity) { | |
1556 MockWrite writes[] = { | |
1557 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
1558 }; | |
1559 Initialize(NULL, 0, writes, arraysize(writes)); | |
1560 | |
1561 EXPECT_CALL(delegate_, OnPipelineHasCapacity(pipeline_.get())).Times(0); | |
1562 scoped_ptr<HttpStream> stream(NewTestStream("ok.html")); | |
1563 | |
1564 EXPECT_CALL(delegate_, OnPipelineHasCapacity(pipeline_.get())).Times(1); | |
1565 HttpRequestHeaders headers; | |
1566 HttpResponseInfo response; | |
1567 EXPECT_EQ(OK, stream->SendRequest(headers, | |
1568 &response, callback_.callback())); | |
1569 | |
1570 EXPECT_CALL(delegate_, OnPipelineHasCapacity(pipeline_.get())).Times(0); | |
1571 base::MessageLoop::current()->RunUntilIdle(); | |
1572 | |
1573 stream->Close(false); | |
1574 EXPECT_CALL(delegate_, OnPipelineHasCapacity(pipeline_.get())).Times(1); | |
1575 stream.reset(NULL); | |
1576 } | |
1577 | |
1578 TEST_F(HttpPipelinedConnectionImplTest, OnPipelineHasCapacityWithoutSend) { | |
1579 MockWrite writes[] = { | |
1580 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), | |
1581 }; | |
1582 Initialize(NULL, 0, writes, arraysize(writes)); | |
1583 | |
1584 EXPECT_CALL(delegate_, OnPipelineHasCapacity(pipeline_.get())).Times(0); | |
1585 scoped_ptr<HttpStream> stream(NewTestStream("ok.html")); | |
1586 | |
1587 EXPECT_CALL(delegate_, OnPipelineHasCapacity(pipeline_.get())).Times(1); | |
1588 base::MessageLoop::current()->RunUntilIdle(); | |
1589 | |
1590 stream->Close(false); | |
1591 EXPECT_CALL(delegate_, OnPipelineHasCapacity(pipeline_.get())).Times(1); | |
1592 stream.reset(NULL); | |
1593 } | |
1594 | |
1595 } // anonymous namespace | |
1596 | |
1597 } // namespace net | |
OLD | NEW |