blob: 641a3062c1ea71e45b8e95481a3a3914286c623b [file] [log] [blame]
[email protected]f702d572012-12-04 15:56:201// 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/quic/quic_http_stream.h"
6
7#include <vector>
8
9#include "net/base/net_errors.h"
10#include "net/base/test_completion_callback.h"
[email protected]b2d26cfd2012-12-11 10:36:0611#include "net/base/upload_bytes_element_reader.h"
[email protected]f702d572012-12-04 15:56:2012#include "net/base/upload_data_stream.h"
13#include "net/http/http_response_headers.h"
[email protected]fee17f72013-02-03 07:47:4114#include "net/quic/congestion_control/receive_algorithm_interface.h"
15#include "net/quic/congestion_control/send_algorithm_interface.h"
[email protected]f702d572012-12-04 15:56:2016#include "net/quic/quic_client_session.h"
17#include "net/quic/quic_connection.h"
18#include "net/quic/quic_connection_helper.h"
19#include "net/quic/test_tools/mock_clock.h"
[email protected]b1f287d2012-12-22 17:25:3920#include "net/quic/test_tools/quic_connection_peer.h"
[email protected]f702d572012-12-04 15:56:2021#include "net/quic/test_tools/quic_test_utils.h"
22#include "net/quic/test_tools/test_task_runner.h"
23#include "net/socket/socket_test_util.h"
[email protected]6cca996b2013-01-25 07:43:3624#include "net/spdy/spdy_frame_builder.h"
25#include "net/spdy/spdy_framer.h"
26#include "net/spdy/spdy_http_utils.h"
27#include "net/spdy/spdy_protocol.h"
[email protected]f702d572012-12-04 15:56:2028#include "testing/gmock/include/gmock/gmock.h"
29#include "testing/gtest/include/gtest/gtest.h"
30
31using testing::_;
32
33namespace net {
[email protected]f702d572012-12-04 15:56:2034namespace test {
[email protected]f702d572012-12-04 15:56:2035namespace {
36
37const char kUploadData[] = "hello world!";
38
39class TestQuicConnection : public QuicConnection {
40 public:
41 TestQuicConnection(QuicGuid guid,
42 IPEndPoint address,
43 QuicConnectionHelper* helper)
44 : QuicConnection(guid, address, helper) {
45 }
46
[email protected]fee17f72013-02-03 07:47:4147 void SetSendAlgorithm(SendAlgorithmInterface* send_algorithm) {
48 QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
[email protected]f702d572012-12-04 15:56:2049 }
[email protected]26f3f8e2012-12-13 21:07:1950
[email protected]fee17f72013-02-03 07:47:4151 void SetReceiveAlgorithm(ReceiveAlgorithmInterface* receive_algorithm) {
52 QuicConnectionPeer::SetReceiveAlgorithm(this, receive_algorithm);
[email protected]26f3f8e2012-12-13 21:07:1953 }
54};
55
[email protected]fee17f72013-02-03 07:47:4156class TestReceiveAlgorithm : public ReceiveAlgorithmInterface {
[email protected]26f3f8e2012-12-13 21:07:1957 public:
[email protected]fee17f72013-02-03 07:47:4158 explicit TestReceiveAlgorithm(QuicCongestionFeedbackFrame* feedback)
59 : feedback_(feedback) {
[email protected]26f3f8e2012-12-13 21:07:1960 }
61
62 bool GenerateCongestionFeedback(
63 QuicCongestionFeedbackFrame* congestion_feedback) {
64 if (feedback_ == NULL) {
65 return false;
66 }
67 *congestion_feedback = *feedback_;
68 return true;
69 }
70
71 MOCK_METHOD4(RecordIncomingPacket,
[email protected]fee17f72013-02-03 07:47:4172 void(QuicByteCount, QuicPacketSequenceNumber, QuicTime, bool));
[email protected]26f3f8e2012-12-13 21:07:1973
74 private:
75 MockClock clock_;
76 QuicCongestionFeedbackFrame* feedback_;
77
[email protected]fee17f72013-02-03 07:47:4178 DISALLOW_COPY_AND_ASSIGN(TestReceiveAlgorithm);
[email protected]f702d572012-12-04 15:56:2079};
80
[email protected]63534512012-12-23 18:49:0081// Subclass of QuicHttpStream that closes itself when the first piece of data
82// is received.
83class AutoClosingStream : public QuicHttpStream {
84 public:
[email protected]6cca996b2013-01-25 07:43:3685 AutoClosingStream(QuicReliableClientStream* stream, bool use_spdy)
86 : QuicHttpStream(stream, use_spdy) {
[email protected]63534512012-12-23 18:49:0087 }
88
[email protected]46fadfd2013-02-06 09:40:1689 virtual int OnDataReceived(const char* data, int length) OVERRIDE {
[email protected]63534512012-12-23 18:49:0090 Close(false);
91 return OK;
92 }
93};
94
[email protected]f702d572012-12-04 15:56:2095} // namespace
96
[email protected]6cca996b2013-01-25 07:43:3697class QuicHttpStreamTest : public ::testing::TestWithParam<bool> {
[email protected]f702d572012-12-04 15:56:2098 protected:
99 const static bool kFin = true;
[email protected]f702d572012-12-04 15:56:20100 // Holds a packet to be written to the wire, and the IO mode that should
101 // be used by the mock socket when performing the write.
102 struct PacketToWrite {
103 PacketToWrite(IoMode mode, QuicEncryptedPacket* packet)
104 : mode(mode),
105 packet(packet) {
106 }
107 IoMode mode;
108 QuicEncryptedPacket* packet;
109 };
110
111 QuicHttpStreamTest()
112 : net_log_(BoundNetLog()),
[email protected]63534512012-12-23 18:49:00113 use_closing_stream_(false),
[email protected]f702d572012-12-04 15:56:20114 read_buffer_(new IOBufferWithSize(4096)),
115 guid_(2),
116 framer_(QuicDecrypter::Create(kNULL), QuicEncrypter::Create(kNULL)),
117 creator_(guid_, &framer_) {
118 IPAddressNumber ip;
119 CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip));
120 peer_addr_ = IPEndPoint(ip, 443);
121 self_addr_ = IPEndPoint(ip, 8435);
122 // Do null initialization for simple tests.
123 Initialize();
124 }
125
126 ~QuicHttpStreamTest() {
127 for (size_t i = 0; i < writes_.size(); i++) {
128 delete writes_[i].packet;
129 }
130 }
131
132 // Adds a packet to the list of expected writes.
133 void AddWrite(IoMode mode, QuicEncryptedPacket* packet) {
134 writes_.push_back(PacketToWrite(mode, packet));
135 }
136
137 // Returns the packet to be written at position |pos|.
138 QuicEncryptedPacket* GetWrite(size_t pos) {
139 return writes_[pos].packet;
140 }
141
142 bool AtEof() {
143 return socket_data_->at_read_eof() && socket_data_->at_write_eof();
144 }
145
146 void ProcessPacket(const QuicEncryptedPacket& packet) {
147 connection_->ProcessUdpPacket(self_addr_, peer_addr_, packet);
148 }
149
150 // Configures the test fixture to use the list of expected writes.
151 void Initialize() {
152 mock_writes_.reset(new MockWrite[writes_.size()]);
153 for (size_t i = 0; i < writes_.size(); i++) {
154 mock_writes_[i] = MockWrite(writes_[i].mode,
155 writes_[i].packet->data(),
156 writes_[i].packet->length());
157 };
158
159 socket_data_.reset(new StaticSocketDataProvider(NULL, 0, mock_writes_.get(),
160 writes_.size()));
161
[email protected]e13201d82012-12-12 05:00:32162 MockUDPClientSocket* socket = new MockUDPClientSocket(socket_data_.get(),
163 net_log_.net_log());
164 socket->Connect(peer_addr_);
[email protected]f702d572012-12-04 15:56:20165 runner_ = new TestTaskRunner(&clock_);
[email protected]fee17f72013-02-03 07:47:41166 send_algorithm_ = new MockSendAlgorithm();
167 receive_algorithm_ = new TestReceiveAlgorithm(NULL);
168 EXPECT_CALL(*send_algorithm_, TimeUntilSend(_)).
[email protected]c995c572013-01-18 05:43:20169 WillRepeatedly(testing::Return(QuicTime::Delta::Zero()));
[email protected]9558c5d32012-12-22 00:08:14170 helper_ = new QuicConnectionHelper(runner_.get(), &clock_,
171 &random_generator_, socket);
[email protected]e13201d82012-12-12 05:00:32172 connection_ = new TestQuicConnection(guid_, peer_addr_, helper_);
[email protected]f702d572012-12-04 15:56:20173 connection_->set_visitor(&visitor_);
[email protected]fee17f72013-02-03 07:47:41174 connection_->SetSendAlgorithm(send_algorithm_);
175 connection_->SetReceiveAlgorithm(receive_algorithm_);
[email protected]41d6b172013-01-29 16:10:57176 session_.reset(new QuicClientSession(connection_, helper_, NULL,
177 "www.google.com"));
[email protected]f702d572012-12-04 15:56:20178 CryptoHandshakeMessage message;
179 message.tag = kSHLO;
180 session_->GetCryptoStream()->OnHandshakeMessage(message);
181 EXPECT_TRUE(session_->IsCryptoHandshakeComplete());
[email protected]63534512012-12-23 18:49:00182 QuicReliableClientStream* stream =
183 session_->CreateOutgoingReliableStream();
[email protected]6cca996b2013-01-25 07:43:36184 stream_.reset(use_closing_stream_ ?
185 new AutoClosingStream(stream, GetParam()) :
186 new QuicHttpStream(stream, GetParam()));
187 }
188
189 void SetRequestString(const std::string& method, const std::string& path) {
190 if (GetParam() == true) {
191 SpdyHeaderBlock headers;
192 headers[":method"] = method;
193 headers[":host"] = "www.google.com";
194 headers[":path"] = path;
195 headers[":scheme"] = "http";
196 headers[":version"] = "HTTP/1.1";
197 request_data_ = SerializeHeaderBlock(headers);
198 } else {
199 request_data_ = method + " " + path + " HTTP/1.1\r\n\r\n";
200 }
201 }
202
203 void SetResponseString(const std::string& status, const std::string& body) {
204 if (GetParam() == true) {
205 SpdyHeaderBlock headers;
206 headers[":status"] = status;
207 headers[":version"] = "HTTP/1.1";
208 headers["content-type"] = "text/plain";
209 response_data_ = SerializeHeaderBlock(headers) + body;
210 } else {
211 response_data_ = "HTTP/1.1 " + status + " \r\n"
212 "Content-Type: text/plain\r\n\r\n" + body;
213 }
214 }
215
216 std::string SerializeHeaderBlock(const SpdyHeaderBlock& headers) {
217 size_t len = SpdyFramer::GetSerializedLength(3, &headers);
218 SpdyFrameBuilder builder(len);
219 SpdyFramer::WriteHeaderBlock(&builder, 3, &headers);
220 scoped_ptr<SpdyFrame> frame(builder.take());
221 return std::string(frame->data(), len);
222 }
[email protected]f702d572012-12-04 15:56:20223
224 // Returns a newly created packet to send kData on stream 1.
225 QuicEncryptedPacket* ConstructDataPacket(
226 QuicPacketSequenceNumber sequence_number,
227 bool fin,
228 QuicStreamOffset offset,
229 base::StringPiece data) {
230 InitializeHeader(sequence_number);
231 QuicStreamFrame frame(3, fin, offset, data);
232 return ConstructPacket(header_, QuicFrame(&frame));
233 }
234
235 // Returns a newly created packet to send ack data.
236 QuicEncryptedPacket* ConstructAckPacket(
237 QuicPacketSequenceNumber sequence_number,
[email protected]63534512012-12-23 18:49:00238 QuicPacketSequenceNumber largest_received,
239 QuicPacketSequenceNumber least_unacked) {
[email protected]f702d572012-12-04 15:56:20240 InitializeHeader(sequence_number);
241
[email protected]63534512012-12-23 18:49:00242 QuicAckFrame ack(largest_received, least_unacked);
[email protected]f702d572012-12-04 15:56:20243 return ConstructPacket(header_, QuicFrame(&ack));
244 }
245
[email protected]63534512012-12-23 18:49:00246 // Returns a newly created packet to send ack data.
247 QuicEncryptedPacket* ConstructRstPacket(
248 QuicPacketSequenceNumber sequence_number,
249 QuicStreamId stream_id,
250 QuicStreamOffset offset) {
251 InitializeHeader(sequence_number);
252
253 QuicRstStreamFrame rst(stream_id, offset, QUIC_NO_ERROR);
254 return ConstructPacket(header_, QuicFrame(&rst));
255 }
256
[email protected]f702d572012-12-04 15:56:20257 BoundNetLog net_log_;
[email protected]63534512012-12-23 18:49:00258 bool use_closing_stream_;
[email protected]fee17f72013-02-03 07:47:41259 MockSendAlgorithm* send_algorithm_;
260 TestReceiveAlgorithm* receive_algorithm_;
[email protected]f702d572012-12-04 15:56:20261 scoped_refptr<TestTaskRunner> runner_;
262 scoped_array<MockWrite> mock_writes_;
263 MockClock clock_;
[email protected]9558c5d32012-12-22 00:08:14264 MockRandom random_generator_;
[email protected]f702d572012-12-04 15:56:20265 TestQuicConnection* connection_;
[email protected]e13201d82012-12-12 05:00:32266 QuicConnectionHelper* helper_;
[email protected]f702d572012-12-04 15:56:20267 testing::StrictMock<MockConnectionVisitor> visitor_;
268 scoped_ptr<QuicHttpStream> stream_;
269 scoped_ptr<QuicClientSession> session_;
270 TestCompletionCallback callback_;
271 HttpRequestInfo request_;
272 HttpRequestHeaders headers_;
273 HttpResponseInfo response_;
274 scoped_refptr<IOBufferWithSize> read_buffer_;
[email protected]6cca996b2013-01-25 07:43:36275 std::string request_data_;
276 std::string response_data_;
[email protected]f702d572012-12-04 15:56:20277
278 private:
279 void InitializeHeader(QuicPacketSequenceNumber sequence_number) {
[email protected]c995c572013-01-18 05:43:20280 header_.public_header.guid = guid_;
281 header_.public_header.flags = PACKET_PUBLIC_FLAGS_NONE;
[email protected]f702d572012-12-04 15:56:20282 header_.packet_sequence_number = sequence_number;
[email protected]f702d572012-12-04 15:56:20283 header_.fec_group = 0;
[email protected]c995c572013-01-18 05:43:20284 header_.private_flags = PACKET_PRIVATE_FLAGS_NONE;
[email protected]f702d572012-12-04 15:56:20285 }
286
287 QuicEncryptedPacket* ConstructPacket(const QuicPacketHeader& header,
288 const QuicFrame& frame) {
289 QuicFrames frames;
290 frames.push_back(frame);
[email protected]610a7e942012-12-18 00:21:39291 scoped_ptr<QuicPacket> packet(
292 framer_.ConstructFrameDataPacket(header_, frames));
293 return framer_.EncryptPacket(*packet);
[email protected]f702d572012-12-04 15:56:20294 }
295
296 const QuicGuid guid_;
297 QuicFramer framer_;
298 IPEndPoint self_addr_;
299 IPEndPoint peer_addr_;
300 QuicPacketCreator creator_;
301 QuicPacketHeader header_;
[email protected]f702d572012-12-04 15:56:20302 scoped_ptr<StaticSocketDataProvider> socket_data_;
303 std::vector<PacketToWrite> writes_;
304};
305
[email protected]6cca996b2013-01-25 07:43:36306// All tests are run with two different serializations, HTTP/SPDY
307INSTANTIATE_TEST_CASE_P(QuicHttpStreamTests,
308 QuicHttpStreamTest,
309 ::testing::Values(true, false));
310
311TEST_P(QuicHttpStreamTest, RenewStreamForAuth) {
[email protected]f702d572012-12-04 15:56:20312 EXPECT_EQ(NULL, stream_->RenewStreamForAuth());
313}
314
[email protected]6cca996b2013-01-25 07:43:36315TEST_P(QuicHttpStreamTest, CanFindEndOfResponse) {
[email protected]f702d572012-12-04 15:56:20316 EXPECT_TRUE(stream_->CanFindEndOfResponse());
317}
318
[email protected]6cca996b2013-01-25 07:43:36319TEST_P(QuicHttpStreamTest, IsMoreDataBuffered) {
[email protected]f702d572012-12-04 15:56:20320 EXPECT_FALSE(stream_->IsMoreDataBuffered());
321}
322
[email protected]6cca996b2013-01-25 07:43:36323TEST_P(QuicHttpStreamTest, IsConnectionReusable) {
[email protected]f702d572012-12-04 15:56:20324 EXPECT_FALSE(stream_->IsConnectionReusable());
325}
326
[email protected]6cca996b2013-01-25 07:43:36327TEST_P(QuicHttpStreamTest, GetRequest) {
328 SetRequestString("GET", "/");
[email protected]f702d572012-12-04 15:56:20329 AddWrite(SYNCHRONOUS, ConstructDataPacket(1, kFin, 0,
[email protected]6cca996b2013-01-25 07:43:36330 request_data_));
[email protected]63534512012-12-23 18:49:00331 AddWrite(SYNCHRONOUS, ConstructAckPacket(2, 2, 2));
[email protected]f702d572012-12-04 15:56:20332 Initialize();
333
334 request_.method = "GET";
335 request_.url = GURL("http://www.google.com/");
336
337 EXPECT_EQ(OK, stream_->InitializeStream(&request_, net_log_,
338 callback_.callback()));
339 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
340 callback_.callback()));
341 EXPECT_EQ(&response_, stream_->GetResponseInfo());
342
343 // Ack the request.
[email protected]63534512012-12-23 18:49:00344 scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 1, 1));
[email protected]f702d572012-12-04 15:56:20345 ProcessPacket(*ack);
346
347 EXPECT_EQ(ERR_IO_PENDING,
348 stream_->ReadResponseHeaders(callback_.callback()));
349
350 // Send the response without a body.
[email protected]6cca996b2013-01-25 07:43:36351 SetResponseString("404 Not Found", "");
[email protected]f702d572012-12-04 15:56:20352 scoped_ptr<QuicEncryptedPacket> resp(
[email protected]6cca996b2013-01-25 07:43:36353 ConstructDataPacket(2, kFin, 0, response_data_));
[email protected]f702d572012-12-04 15:56:20354 ProcessPacket(*resp);
355
356 // Now that the headers have been processed, the callback will return.
357 EXPECT_EQ(OK, callback_.WaitForResult());
358 ASSERT_TRUE(response_.headers != NULL);
359 EXPECT_EQ(404, response_.headers->response_code());
360 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
361
362 // There is no body, so this should return immediately.
363 EXPECT_EQ(0, stream_->ReadResponseBody(read_buffer_.get(),
364 read_buffer_->size(),
365 callback_.callback()));
366 EXPECT_TRUE(stream_->IsResponseBodyComplete());
367 EXPECT_TRUE(AtEof());
368}
369
[email protected]6cca996b2013-01-25 07:43:36370TEST_P(QuicHttpStreamTest, GetRequestFullResponseInSinglePacket) {
371 SetRequestString("GET", "/");
372 AddWrite(SYNCHRONOUS, ConstructDataPacket(1, kFin, 0, request_data_));
[email protected]63534512012-12-23 18:49:00373 AddWrite(SYNCHRONOUS, ConstructAckPacket(2, 2, 2));
[email protected]f702d572012-12-04 15:56:20374 Initialize();
375
376 request_.method = "GET";
377 request_.url = GURL("http://www.google.com/");
378
379 EXPECT_EQ(OK, stream_->InitializeStream(&request_, net_log_,
380 callback_.callback()));
381 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
382 callback_.callback()));
383 EXPECT_EQ(&response_, stream_->GetResponseInfo());
384
385 // Ack the request.
[email protected]63534512012-12-23 18:49:00386 scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 1, 1));
[email protected]f702d572012-12-04 15:56:20387 ProcessPacket(*ack);
388
389 EXPECT_EQ(ERR_IO_PENDING,
390 stream_->ReadResponseHeaders(callback_.callback()));
391
392 // Send the response with a body.
[email protected]6cca996b2013-01-25 07:43:36393 SetResponseString("200 OK", "hello world!");
[email protected]f702d572012-12-04 15:56:20394 scoped_ptr<QuicEncryptedPacket> resp(
[email protected]6cca996b2013-01-25 07:43:36395 ConstructDataPacket(2, kFin, 0, response_data_));
[email protected]f702d572012-12-04 15:56:20396 ProcessPacket(*resp);
397
398 // Now that the headers have been processed, the callback will return.
399 EXPECT_EQ(OK, callback_.WaitForResult());
400 ASSERT_TRUE(response_.headers != NULL);
[email protected]6cca996b2013-01-25 07:43:36401 EXPECT_EQ(200, response_.headers->response_code());
[email protected]f702d572012-12-04 15:56:20402 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
403
404 // There is no body, so this should return immediately.
405 // Since the body has already arrived, this should return immediately.
406 EXPECT_EQ(12, stream_->ReadResponseBody(read_buffer_.get(),
407 read_buffer_->size(),
408 callback_.callback()));
409 EXPECT_TRUE(stream_->IsResponseBodyComplete());
410 EXPECT_TRUE(AtEof());
411}
412
[email protected]6cca996b2013-01-25 07:43:36413TEST_P(QuicHttpStreamTest, SendPostRequest) {
414 SetRequestString("POST", "/");
415 AddWrite(SYNCHRONOUS, ConstructDataPacket(1, !kFin, 0, request_data_));
416 AddWrite(SYNCHRONOUS, ConstructDataPacket(2, kFin, request_data_.length(),
[email protected]f702d572012-12-04 15:56:20417 kUploadData));
[email protected]63534512012-12-23 18:49:00418 AddWrite(SYNCHRONOUS, ConstructAckPacket(3, 2, 3));
[email protected]f702d572012-12-04 15:56:20419
420 Initialize();
421
[email protected]b2d26cfd2012-12-11 10:36:06422 ScopedVector<UploadElementReader> element_readers;
423 element_readers.push_back(
424 new UploadBytesElementReader(kUploadData, strlen(kUploadData)));
425 UploadDataStream upload_data_stream(&element_readers, 0);
[email protected]f702d572012-12-04 15:56:20426 request_.method = "POST";
427 request_.url = GURL("http://www.google.com/");
428 request_.upload_data_stream = &upload_data_stream;
[email protected]4db27d82012-12-20 11:50:24429 ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback()));
[email protected]f702d572012-12-04 15:56:20430
431 EXPECT_EQ(OK, stream_->InitializeStream(&request_, net_log_,
432 callback_.callback()));
433 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
434 callback_.callback()));
435 EXPECT_EQ(&response_, stream_->GetResponseInfo());
436
437 // Ack both packets in the request.
[email protected]63534512012-12-23 18:49:00438 scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 2, 1));
[email protected]f702d572012-12-04 15:56:20439 ProcessPacket(*ack);
440
441 // Send the response headers (but not the body).
[email protected]6cca996b2013-01-25 07:43:36442 SetResponseString("200 OK", "");
[email protected]f702d572012-12-04 15:56:20443 scoped_ptr<QuicEncryptedPacket> resp(
[email protected]6cca996b2013-01-25 07:43:36444 ConstructDataPacket(2, !kFin, 0, response_data_));
[email protected]f702d572012-12-04 15:56:20445 ProcessPacket(*resp);
446
447 // Since the headers have already arrived, this should return immediately.
448 EXPECT_EQ(OK, stream_->ReadResponseHeaders(callback_.callback()));
449 ASSERT_TRUE(response_.headers != NULL);
450 EXPECT_EQ(200, response_.headers->response_code());
451 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
452
453 // Send the response body.
454 const char kResponseBody[] = "Hello world!";
455 scoped_ptr<QuicEncryptedPacket> resp_body(
[email protected]6cca996b2013-01-25 07:43:36456 ConstructDataPacket(3, kFin, response_data_.length(), kResponseBody));
[email protected]f702d572012-12-04 15:56:20457 ProcessPacket(*resp_body);
458
459 // Since the body has already arrived, this should return immediately.
460 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
461 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
462 callback_.callback()));
463
464 EXPECT_TRUE(stream_->IsResponseBodyComplete());
465 EXPECT_TRUE(AtEof());
466}
467
[email protected]6cca996b2013-01-25 07:43:36468TEST_P(QuicHttpStreamTest, DestroyedEarly) {
469 SetRequestString("GET", "/");
470 AddWrite(SYNCHRONOUS, ConstructDataPacket(1, kFin, 0, request_data_));
471 AddWrite(SYNCHRONOUS, ConstructRstPacket(2, 3, request_data_.length()));
[email protected]63534512012-12-23 18:49:00472 AddWrite(SYNCHRONOUS, ConstructAckPacket(3, 2, 2));
473 use_closing_stream_ = true;
474 Initialize();
475
476 request_.method = "GET";
477 request_.url = GURL("http://www.google.com/");
478
[email protected]63534512012-12-23 18:49:00479 EXPECT_EQ(OK, stream_->InitializeStream(&request_, net_log_,
480 callback_.callback()));
481 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
482 callback_.callback()));
483 EXPECT_EQ(&response_, stream_->GetResponseInfo());
484
485 // Ack the request.
486 scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 1, 1));
487 ProcessPacket(*ack);
488 EXPECT_EQ(ERR_IO_PENDING,
489 stream_->ReadResponseHeaders(callback_.callback()));
490
491 // Send the response with a body.
492 const char kResponseHeaders[] = "HTTP/1.1 404 OK\r\n"
493 "Content-Type: text/plain\r\n\r\nhello world!";
494 scoped_ptr<QuicEncryptedPacket> resp(
495 ConstructDataPacket(2, kFin, 0, kResponseHeaders));
496
497 // In the course of processing this packet, the QuicHttpStream close itself.
498 ProcessPacket(*resp);
499
500 EXPECT_TRUE(AtEof());
501}
502
[email protected]f702d572012-12-04 15:56:20503} // namespace test
504
505} // namespace net