blob: 5b4efaa047bc572c2974ae712bac48b31a6294fa [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]9db443912013-02-25 05:27:0320#include "net/quic/test_tools/mock_random.h"
[email protected]b1f287d2012-12-22 17:25:3921#include "net/quic/test_tools/quic_connection_peer.h"
[email protected]f702d572012-12-04 15:56:2022#include "net/quic/test_tools/quic_test_utils.h"
23#include "net/quic/test_tools/test_task_runner.h"
24#include "net/socket/socket_test_util.h"
[email protected]6cca996b2013-01-25 07:43:3625#include "net/spdy/spdy_frame_builder.h"
26#include "net/spdy/spdy_framer.h"
27#include "net/spdy/spdy_http_utils.h"
28#include "net/spdy/spdy_protocol.h"
[email protected]f702d572012-12-04 15:56:2029#include "testing/gmock/include/gmock/gmock.h"
30#include "testing/gtest/include/gtest/gtest.h"
31
32using testing::_;
33
34namespace net {
[email protected]f702d572012-12-04 15:56:2035namespace test {
[email protected]f702d572012-12-04 15:56:2036namespace {
37
38const char kUploadData[] = "hello world!";
39
40class TestQuicConnection : public QuicConnection {
41 public:
42 TestQuicConnection(QuicGuid guid,
43 IPEndPoint address,
44 QuicConnectionHelper* helper)
45 : QuicConnection(guid, address, helper) {
46 }
47
[email protected]fee17f72013-02-03 07:47:4148 void SetSendAlgorithm(SendAlgorithmInterface* send_algorithm) {
49 QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
[email protected]f702d572012-12-04 15:56:2050 }
[email protected]26f3f8e2012-12-13 21:07:1951
[email protected]fee17f72013-02-03 07:47:4152 void SetReceiveAlgorithm(ReceiveAlgorithmInterface* receive_algorithm) {
53 QuicConnectionPeer::SetReceiveAlgorithm(this, receive_algorithm);
[email protected]26f3f8e2012-12-13 21:07:1954 }
55};
56
[email protected]fee17f72013-02-03 07:47:4157class TestReceiveAlgorithm : public ReceiveAlgorithmInterface {
[email protected]26f3f8e2012-12-13 21:07:1958 public:
[email protected]fee17f72013-02-03 07:47:4159 explicit TestReceiveAlgorithm(QuicCongestionFeedbackFrame* feedback)
60 : feedback_(feedback) {
[email protected]26f3f8e2012-12-13 21:07:1961 }
62
63 bool GenerateCongestionFeedback(
64 QuicCongestionFeedbackFrame* congestion_feedback) {
65 if (feedback_ == NULL) {
66 return false;
67 }
68 *congestion_feedback = *feedback_;
69 return true;
70 }
71
72 MOCK_METHOD4(RecordIncomingPacket,
[email protected]fee17f72013-02-03 07:47:4173 void(QuicByteCount, QuicPacketSequenceNumber, QuicTime, bool));
[email protected]26f3f8e2012-12-13 21:07:1974
75 private:
76 MockClock clock_;
77 QuicCongestionFeedbackFrame* feedback_;
78
[email protected]fee17f72013-02-03 07:47:4179 DISALLOW_COPY_AND_ASSIGN(TestReceiveAlgorithm);
[email protected]f702d572012-12-04 15:56:2080};
81
[email protected]63534512012-12-23 18:49:0082// Subclass of QuicHttpStream that closes itself when the first piece of data
83// is received.
84class AutoClosingStream : public QuicHttpStream {
85 public:
[email protected]9d9e7932013-02-25 18:31:0586 explicit AutoClosingStream(QuicReliableClientStream* stream)
87 : QuicHttpStream(stream) {
[email protected]63534512012-12-23 18:49:0088 }
89
[email protected]46fadfd2013-02-06 09:40:1690 virtual int OnDataReceived(const char* data, int length) OVERRIDE {
[email protected]63534512012-12-23 18:49:0091 Close(false);
92 return OK;
93 }
94};
95
[email protected]f702d572012-12-04 15:56:2096} // namespace
97
[email protected]6cca996b2013-01-25 07:43:3698class QuicHttpStreamTest : public ::testing::TestWithParam<bool> {
[email protected]f702d572012-12-04 15:56:2099 protected:
100 const static bool kFin = true;
[email protected]f702d572012-12-04 15:56:20101 // Holds a packet to be written to the wire, and the IO mode that should
102 // be used by the mock socket when performing the write.
103 struct PacketToWrite {
104 PacketToWrite(IoMode mode, QuicEncryptedPacket* packet)
105 : mode(mode),
106 packet(packet) {
107 }
108 IoMode mode;
109 QuicEncryptedPacket* packet;
110 };
111
112 QuicHttpStreamTest()
113 : net_log_(BoundNetLog()),
[email protected]63534512012-12-23 18:49:00114 use_closing_stream_(false),
[email protected]f702d572012-12-04 15:56:20115 read_buffer_(new IOBufferWithSize(4096)),
116 guid_(2),
117 framer_(QuicDecrypter::Create(kNULL), QuicEncrypter::Create(kNULL)),
[email protected]9db443912013-02-25 05:27:03118 creator_(guid_, &framer_, &random_) {
[email protected]f702d572012-12-04 15:56:20119 IPAddressNumber ip;
120 CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip));
121 peer_addr_ = IPEndPoint(ip, 443);
122 self_addr_ = IPEndPoint(ip, 8435);
123 // Do null initialization for simple tests.
124 Initialize();
125 }
126
127 ~QuicHttpStreamTest() {
128 for (size_t i = 0; i < writes_.size(); i++) {
129 delete writes_[i].packet;
130 }
131 }
132
133 // Adds a packet to the list of expected writes.
134 void AddWrite(IoMode mode, QuicEncryptedPacket* packet) {
135 writes_.push_back(PacketToWrite(mode, packet));
136 }
137
138 // Returns the packet to be written at position |pos|.
139 QuicEncryptedPacket* GetWrite(size_t pos) {
140 return writes_[pos].packet;
141 }
142
143 bool AtEof() {
144 return socket_data_->at_read_eof() && socket_data_->at_write_eof();
145 }
146
147 void ProcessPacket(const QuicEncryptedPacket& packet) {
148 connection_->ProcessUdpPacket(self_addr_, peer_addr_, packet);
149 }
150
151 // Configures the test fixture to use the list of expected writes.
152 void Initialize() {
153 mock_writes_.reset(new MockWrite[writes_.size()]);
154 for (size_t i = 0; i < writes_.size(); i++) {
155 mock_writes_[i] = MockWrite(writes_[i].mode,
156 writes_[i].packet->data(),
157 writes_[i].packet->length());
158 };
159
160 socket_data_.reset(new StaticSocketDataProvider(NULL, 0, mock_writes_.get(),
161 writes_.size()));
162
[email protected]e13201d82012-12-12 05:00:32163 MockUDPClientSocket* socket = new MockUDPClientSocket(socket_data_.get(),
164 net_log_.net_log());
165 socket->Connect(peer_addr_);
[email protected]f702d572012-12-04 15:56:20166 runner_ = new TestTaskRunner(&clock_);
[email protected]fee17f72013-02-03 07:47:41167 send_algorithm_ = new MockSendAlgorithm();
168 receive_algorithm_ = new TestReceiveAlgorithm(NULL);
[email protected]9db443912013-02-25 05:27:03169 EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _)).
[email protected]c995c572013-01-18 05:43:20170 WillRepeatedly(testing::Return(QuicTime::Delta::Zero()));
[email protected]9558c5d32012-12-22 00:08:14171 helper_ = new QuicConnectionHelper(runner_.get(), &clock_,
172 &random_generator_, socket);
[email protected]e13201d82012-12-12 05:00:32173 connection_ = new TestQuicConnection(guid_, peer_addr_, helper_);
[email protected]f702d572012-12-04 15:56:20174 connection_->set_visitor(&visitor_);
[email protected]fee17f72013-02-03 07:47:41175 connection_->SetSendAlgorithm(send_algorithm_);
176 connection_->SetReceiveAlgorithm(receive_algorithm_);
[email protected]41d6b172013-01-29 16:10:57177 session_.reset(new QuicClientSession(connection_, helper_, NULL,
[email protected]0d10b592013-02-14 16:09:26178 "www.google.com", NULL));
[email protected]f702d572012-12-04 15:56:20179 CryptoHandshakeMessage message;
180 message.tag = kSHLO;
181 session_->GetCryptoStream()->OnHandshakeMessage(message);
182 EXPECT_TRUE(session_->IsCryptoHandshakeComplete());
[email protected]63534512012-12-23 18:49:00183 QuicReliableClientStream* stream =
184 session_->CreateOutgoingReliableStream();
[email protected]6cca996b2013-01-25 07:43:36185 stream_.reset(use_closing_stream_ ?
[email protected]9d9e7932013-02-25 18:31:05186 new AutoClosingStream(stream) :
187 new QuicHttpStream(stream));
[email protected]6cca996b2013-01-25 07:43:36188 }
189
190 void SetRequestString(const std::string& method, const std::string& path) {
[email protected]9d9e7932013-02-25 18:31:05191 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);
[email protected]6cca996b2013-01-25 07:43:36198 }
199
200 void SetResponseString(const std::string& status, const std::string& body) {
[email protected]9d9e7932013-02-25 18:31:05201 SpdyHeaderBlock headers;
202 headers[":status"] = status;
203 headers[":version"] = "HTTP/1.1";
204 headers["content-type"] = "text/plain";
205 response_data_ = SerializeHeaderBlock(headers) + body;
[email protected]6cca996b2013-01-25 07:43:36206 }
207
208 std::string SerializeHeaderBlock(const SpdyHeaderBlock& headers) {
209 size_t len = SpdyFramer::GetSerializedLength(3, &headers);
210 SpdyFrameBuilder builder(len);
211 SpdyFramer::WriteHeaderBlock(&builder, 3, &headers);
212 scoped_ptr<SpdyFrame> frame(builder.take());
213 return std::string(frame->data(), len);
214 }
[email protected]f702d572012-12-04 15:56:20215
216 // Returns a newly created packet to send kData on stream 1.
217 QuicEncryptedPacket* ConstructDataPacket(
218 QuicPacketSequenceNumber sequence_number,
219 bool fin,
220 QuicStreamOffset offset,
221 base::StringPiece data) {
222 InitializeHeader(sequence_number);
223 QuicStreamFrame frame(3, fin, offset, data);
224 return ConstructPacket(header_, QuicFrame(&frame));
225 }
226
227 // Returns a newly created packet to send ack data.
228 QuicEncryptedPacket* ConstructAckPacket(
229 QuicPacketSequenceNumber sequence_number,
[email protected]63534512012-12-23 18:49:00230 QuicPacketSequenceNumber largest_received,
231 QuicPacketSequenceNumber least_unacked) {
[email protected]f702d572012-12-04 15:56:20232 InitializeHeader(sequence_number);
233
[email protected]63534512012-12-23 18:49:00234 QuicAckFrame ack(largest_received, least_unacked);
[email protected]9db443912013-02-25 05:27:03235 ack.sent_info.entropy_hash = 0;
236 ack.received_info.entropy_hash = 0;
237
[email protected]f702d572012-12-04 15:56:20238 return ConstructPacket(header_, QuicFrame(&ack));
239 }
240
[email protected]63534512012-12-23 18:49:00241 // Returns a newly created packet to send ack data.
242 QuicEncryptedPacket* ConstructRstPacket(
243 QuicPacketSequenceNumber sequence_number,
[email protected]9db443912013-02-25 05:27:03244 QuicStreamId stream_id) {
[email protected]63534512012-12-23 18:49:00245 InitializeHeader(sequence_number);
246
[email protected]9db443912013-02-25 05:27:03247 QuicRstStreamFrame rst(stream_id, QUIC_NO_ERROR);
[email protected]63534512012-12-23 18:49:00248 return ConstructPacket(header_, QuicFrame(&rst));
249 }
250
[email protected]f702d572012-12-04 15:56:20251 BoundNetLog net_log_;
[email protected]63534512012-12-23 18:49:00252 bool use_closing_stream_;
[email protected]fee17f72013-02-03 07:47:41253 MockSendAlgorithm* send_algorithm_;
254 TestReceiveAlgorithm* receive_algorithm_;
[email protected]f702d572012-12-04 15:56:20255 scoped_refptr<TestTaskRunner> runner_;
256 scoped_array<MockWrite> mock_writes_;
257 MockClock clock_;
[email protected]9558c5d32012-12-22 00:08:14258 MockRandom random_generator_;
[email protected]f702d572012-12-04 15:56:20259 TestQuicConnection* connection_;
[email protected]e13201d82012-12-12 05:00:32260 QuicConnectionHelper* helper_;
[email protected]f702d572012-12-04 15:56:20261 testing::StrictMock<MockConnectionVisitor> visitor_;
262 scoped_ptr<QuicHttpStream> stream_;
263 scoped_ptr<QuicClientSession> session_;
264 TestCompletionCallback callback_;
265 HttpRequestInfo request_;
266 HttpRequestHeaders headers_;
267 HttpResponseInfo response_;
268 scoped_refptr<IOBufferWithSize> read_buffer_;
[email protected]6cca996b2013-01-25 07:43:36269 std::string request_data_;
270 std::string response_data_;
[email protected]f702d572012-12-04 15:56:20271
272 private:
273 void InitializeHeader(QuicPacketSequenceNumber sequence_number) {
[email protected]c995c572013-01-18 05:43:20274 header_.public_header.guid = guid_;
[email protected]9db443912013-02-25 05:27:03275 header_.public_header.reset_flag = false;
276 header_.public_header.version_flag = false;
[email protected]f702d572012-12-04 15:56:20277 header_.packet_sequence_number = sequence_number;
[email protected]f702d572012-12-04 15:56:20278 header_.fec_group = 0;
[email protected]9db443912013-02-25 05:27:03279 header_.fec_entropy_flag = false;
280 header_.entropy_flag = false;
281 header_.fec_flag = false;
[email protected]f702d572012-12-04 15:56:20282 }
283
284 QuicEncryptedPacket* ConstructPacket(const QuicPacketHeader& header,
285 const QuicFrame& frame) {
286 QuicFrames frames;
287 frames.push_back(frame);
[email protected]610a7e942012-12-18 00:21:39288 scoped_ptr<QuicPacket> packet(
[email protected]9db443912013-02-25 05:27:03289 framer_.ConstructFrameDataPacket(header_, frames).packet);
290 return framer_.EncryptPacket(header.packet_sequence_number, *packet);
[email protected]f702d572012-12-04 15:56:20291 }
292
293 const QuicGuid guid_;
294 QuicFramer framer_;
295 IPEndPoint self_addr_;
296 IPEndPoint peer_addr_;
[email protected]9db443912013-02-25 05:27:03297 MockRandom random_;
[email protected]f702d572012-12-04 15:56:20298 QuicPacketCreator creator_;
299 QuicPacketHeader header_;
[email protected]f702d572012-12-04 15:56:20300 scoped_ptr<StaticSocketDataProvider> socket_data_;
301 std::vector<PacketToWrite> writes_;
302};
303
[email protected]9d9e7932013-02-25 18:31:05304TEST_F(QuicHttpStreamTest, RenewStreamForAuth) {
[email protected]f702d572012-12-04 15:56:20305 EXPECT_EQ(NULL, stream_->RenewStreamForAuth());
306}
307
[email protected]9d9e7932013-02-25 18:31:05308TEST_F(QuicHttpStreamTest, CanFindEndOfResponse) {
[email protected]f702d572012-12-04 15:56:20309 EXPECT_TRUE(stream_->CanFindEndOfResponse());
310}
311
[email protected]9d9e7932013-02-25 18:31:05312TEST_F(QuicHttpStreamTest, IsMoreDataBuffered) {
[email protected]f702d572012-12-04 15:56:20313 EXPECT_FALSE(stream_->IsMoreDataBuffered());
314}
315
[email protected]9d9e7932013-02-25 18:31:05316TEST_F(QuicHttpStreamTest, IsConnectionReusable) {
[email protected]f702d572012-12-04 15:56:20317 EXPECT_FALSE(stream_->IsConnectionReusable());
318}
319
[email protected]9d9e7932013-02-25 18:31:05320TEST_F(QuicHttpStreamTest, GetRequest) {
[email protected]6cca996b2013-01-25 07:43:36321 SetRequestString("GET", "/");
[email protected]f702d572012-12-04 15:56:20322 AddWrite(SYNCHRONOUS, ConstructDataPacket(1, kFin, 0,
[email protected]6cca996b2013-01-25 07:43:36323 request_data_));
[email protected]63534512012-12-23 18:49:00324 AddWrite(SYNCHRONOUS, ConstructAckPacket(2, 2, 2));
[email protected]f702d572012-12-04 15:56:20325 Initialize();
326
327 request_.method = "GET";
328 request_.url = GURL("http://www.google.com/");
329
330 EXPECT_EQ(OK, stream_->InitializeStream(&request_, net_log_,
331 callback_.callback()));
332 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
333 callback_.callback()));
334 EXPECT_EQ(&response_, stream_->GetResponseInfo());
335
336 // Ack the request.
[email protected]63534512012-12-23 18:49:00337 scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 1, 1));
[email protected]f702d572012-12-04 15:56:20338 ProcessPacket(*ack);
339
340 EXPECT_EQ(ERR_IO_PENDING,
341 stream_->ReadResponseHeaders(callback_.callback()));
342
343 // Send the response without a body.
[email protected]6cca996b2013-01-25 07:43:36344 SetResponseString("404 Not Found", "");
[email protected]f702d572012-12-04 15:56:20345 scoped_ptr<QuicEncryptedPacket> resp(
[email protected]6cca996b2013-01-25 07:43:36346 ConstructDataPacket(2, kFin, 0, response_data_));
[email protected]f702d572012-12-04 15:56:20347 ProcessPacket(*resp);
348
349 // Now that the headers have been processed, the callback will return.
350 EXPECT_EQ(OK, callback_.WaitForResult());
351 ASSERT_TRUE(response_.headers != NULL);
352 EXPECT_EQ(404, response_.headers->response_code());
353 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
354
355 // There is no body, so this should return immediately.
356 EXPECT_EQ(0, stream_->ReadResponseBody(read_buffer_.get(),
357 read_buffer_->size(),
358 callback_.callback()));
359 EXPECT_TRUE(stream_->IsResponseBodyComplete());
360 EXPECT_TRUE(AtEof());
361}
362
[email protected]9d9e7932013-02-25 18:31:05363TEST_F(QuicHttpStreamTest, GetRequestFullResponseInSinglePacket) {
[email protected]6cca996b2013-01-25 07:43:36364 SetRequestString("GET", "/");
365 AddWrite(SYNCHRONOUS, ConstructDataPacket(1, kFin, 0, request_data_));
[email protected]63534512012-12-23 18:49:00366 AddWrite(SYNCHRONOUS, ConstructAckPacket(2, 2, 2));
[email protected]f702d572012-12-04 15:56:20367 Initialize();
368
369 request_.method = "GET";
370 request_.url = GURL("http://www.google.com/");
371
372 EXPECT_EQ(OK, stream_->InitializeStream(&request_, net_log_,
373 callback_.callback()));
374 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
375 callback_.callback()));
376 EXPECT_EQ(&response_, stream_->GetResponseInfo());
377
378 // Ack the request.
[email protected]63534512012-12-23 18:49:00379 scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 1, 1));
[email protected]f702d572012-12-04 15:56:20380 ProcessPacket(*ack);
381
382 EXPECT_EQ(ERR_IO_PENDING,
383 stream_->ReadResponseHeaders(callback_.callback()));
384
385 // Send the response with a body.
[email protected]6cca996b2013-01-25 07:43:36386 SetResponseString("200 OK", "hello world!");
[email protected]f702d572012-12-04 15:56:20387 scoped_ptr<QuicEncryptedPacket> resp(
[email protected]6cca996b2013-01-25 07:43:36388 ConstructDataPacket(2, kFin, 0, response_data_));
[email protected]f702d572012-12-04 15:56:20389 ProcessPacket(*resp);
390
391 // Now that the headers have been processed, the callback will return.
392 EXPECT_EQ(OK, callback_.WaitForResult());
393 ASSERT_TRUE(response_.headers != NULL);
[email protected]6cca996b2013-01-25 07:43:36394 EXPECT_EQ(200, response_.headers->response_code());
[email protected]f702d572012-12-04 15:56:20395 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
396
397 // There is no body, so this should return immediately.
398 // Since the body has already arrived, this should return immediately.
399 EXPECT_EQ(12, stream_->ReadResponseBody(read_buffer_.get(),
400 read_buffer_->size(),
401 callback_.callback()));
402 EXPECT_TRUE(stream_->IsResponseBodyComplete());
403 EXPECT_TRUE(AtEof());
404}
405
[email protected]9d9e7932013-02-25 18:31:05406TEST_F(QuicHttpStreamTest, SendPostRequest) {
[email protected]6cca996b2013-01-25 07:43:36407 SetRequestString("POST", "/");
408 AddWrite(SYNCHRONOUS, ConstructDataPacket(1, !kFin, 0, request_data_));
409 AddWrite(SYNCHRONOUS, ConstructDataPacket(2, kFin, request_data_.length(),
[email protected]f702d572012-12-04 15:56:20410 kUploadData));
[email protected]63534512012-12-23 18:49:00411 AddWrite(SYNCHRONOUS, ConstructAckPacket(3, 2, 3));
[email protected]f702d572012-12-04 15:56:20412
413 Initialize();
414
[email protected]b2d26cfd2012-12-11 10:36:06415 ScopedVector<UploadElementReader> element_readers;
416 element_readers.push_back(
417 new UploadBytesElementReader(kUploadData, strlen(kUploadData)));
418 UploadDataStream upload_data_stream(&element_readers, 0);
[email protected]f702d572012-12-04 15:56:20419 request_.method = "POST";
420 request_.url = GURL("http://www.google.com/");
421 request_.upload_data_stream = &upload_data_stream;
[email protected]4db27d82012-12-20 11:50:24422 ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback()));
[email protected]f702d572012-12-04 15:56:20423
424 EXPECT_EQ(OK, stream_->InitializeStream(&request_, net_log_,
425 callback_.callback()));
426 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
427 callback_.callback()));
428 EXPECT_EQ(&response_, stream_->GetResponseInfo());
429
430 // Ack both packets in the request.
[email protected]63534512012-12-23 18:49:00431 scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 2, 1));
[email protected]f702d572012-12-04 15:56:20432 ProcessPacket(*ack);
433
434 // Send the response headers (but not the body).
[email protected]6cca996b2013-01-25 07:43:36435 SetResponseString("200 OK", "");
[email protected]f702d572012-12-04 15:56:20436 scoped_ptr<QuicEncryptedPacket> resp(
[email protected]6cca996b2013-01-25 07:43:36437 ConstructDataPacket(2, !kFin, 0, response_data_));
[email protected]f702d572012-12-04 15:56:20438 ProcessPacket(*resp);
439
440 // Since the headers have already arrived, this should return immediately.
441 EXPECT_EQ(OK, stream_->ReadResponseHeaders(callback_.callback()));
442 ASSERT_TRUE(response_.headers != NULL);
443 EXPECT_EQ(200, response_.headers->response_code());
444 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
445
446 // Send the response body.
447 const char kResponseBody[] = "Hello world!";
448 scoped_ptr<QuicEncryptedPacket> resp_body(
[email protected]6cca996b2013-01-25 07:43:36449 ConstructDataPacket(3, kFin, response_data_.length(), kResponseBody));
[email protected]f702d572012-12-04 15:56:20450 ProcessPacket(*resp_body);
451
452 // Since the body has already arrived, this should return immediately.
453 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
454 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
455 callback_.callback()));
456
457 EXPECT_TRUE(stream_->IsResponseBodyComplete());
458 EXPECT_TRUE(AtEof());
459}
460
[email protected]c9e49a02013-02-26 05:56:47461TEST_F(QuicHttpStreamTest, SendChunkedPostRequest) {
462 SetRequestString("POST", "/");
463 size_t chunk_size = strlen(kUploadData);
464 AddWrite(SYNCHRONOUS, ConstructDataPacket(1, !kFin, 0, request_data_));
465 AddWrite(SYNCHRONOUS, ConstructDataPacket(2, !kFin, request_data_.length(),
466 kUploadData));
467 AddWrite(SYNCHRONOUS, ConstructDataPacket(3, kFin,
468 request_data_.length() + chunk_size,
469 kUploadData));
470 AddWrite(SYNCHRONOUS, ConstructAckPacket(4, 2, 3));
471
472 Initialize();
473
474 UploadDataStream upload_data_stream(UploadDataStream::CHUNKED, 0);
475 upload_data_stream.AppendChunk(kUploadData, chunk_size, false);
476
477 request_.method = "POST";
478 request_.url = GURL("http://www.google.com/");
479 request_.upload_data_stream = &upload_data_stream;
480 ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback()));
481
482 ASSERT_EQ(OK, stream_->InitializeStream(&request_, net_log_,
483 callback_.callback()));
484 ASSERT_EQ(ERR_IO_PENDING, stream_->SendRequest(headers_, &response_,
485 callback_.callback()));
486 EXPECT_EQ(&response_, stream_->GetResponseInfo());
487
488 upload_data_stream.AppendChunk(kUploadData, chunk_size, true);
489
490 // Ack both packets in the request.
491 scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 2, 1));
492 ProcessPacket(*ack);
493
494 // Send the response headers (but not the body).
495 SetResponseString("200 OK", "");
496 scoped_ptr<QuicEncryptedPacket> resp(
497 ConstructDataPacket(2, !kFin, 0, response_data_));
498 ProcessPacket(*resp);
499
500 // Since the headers have already arrived, this should return immediately.
501 ASSERT_EQ(OK, stream_->ReadResponseHeaders(callback_.callback()));
502 ASSERT_TRUE(response_.headers != NULL);
503 EXPECT_EQ(200, response_.headers->response_code());
504 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
505
506 // Send the response body.
507 const char kResponseBody[] = "Hello world!";
508 scoped_ptr<QuicEncryptedPacket> resp_body(
509 ConstructDataPacket(3, kFin, response_data_.length(), kResponseBody));
510 ProcessPacket(*resp_body);
511
512 // Since the body has already arrived, this should return immediately.
513 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
514 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
515 callback_.callback()));
516
517 EXPECT_TRUE(stream_->IsResponseBodyComplete());
518 EXPECT_TRUE(AtEof());
519}
520
[email protected]9d9e7932013-02-25 18:31:05521TEST_F(QuicHttpStreamTest, DestroyedEarly) {
[email protected]6cca996b2013-01-25 07:43:36522 SetRequestString("GET", "/");
523 AddWrite(SYNCHRONOUS, ConstructDataPacket(1, kFin, 0, request_data_));
[email protected]9db443912013-02-25 05:27:03524 AddWrite(SYNCHRONOUS, ConstructRstPacket(2, 3));
[email protected]63534512012-12-23 18:49:00525 AddWrite(SYNCHRONOUS, ConstructAckPacket(3, 2, 2));
526 use_closing_stream_ = true;
527 Initialize();
528
529 request_.method = "GET";
530 request_.url = GURL("http://www.google.com/");
531
[email protected]63534512012-12-23 18:49:00532 EXPECT_EQ(OK, stream_->InitializeStream(&request_, net_log_,
533 callback_.callback()));
534 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
535 callback_.callback()));
536 EXPECT_EQ(&response_, stream_->GetResponseInfo());
537
538 // Ack the request.
539 scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 1, 1));
540 ProcessPacket(*ack);
541 EXPECT_EQ(ERR_IO_PENDING,
542 stream_->ReadResponseHeaders(callback_.callback()));
543
544 // Send the response with a body.
545 const char kResponseHeaders[] = "HTTP/1.1 404 OK\r\n"
546 "Content-Type: text/plain\r\n\r\nhello world!";
547 scoped_ptr<QuicEncryptedPacket> resp(
548 ConstructDataPacket(2, kFin, 0, kResponseHeaders));
549
550 // In the course of processing this packet, the QuicHttpStream close itself.
551 ProcessPacket(*resp);
552
553 EXPECT_TRUE(AtEof());
554}
555
[email protected]f702d572012-12-04 15:56:20556} // namespace test
557
558} // namespace net