blob: 7ccd4040955148f8e7862140c537a6be1d00573b [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]e8ff26842013-03-22 21:02:0516#include "net/quic/crypto/crypto_protocol.h"
[email protected]4df69842013-02-27 06:32:1617#include "net/quic/crypto/quic_decrypter.h"
18#include "net/quic/crypto/quic_encrypter.h"
[email protected]f702d572012-12-04 15:56:2019#include "net/quic/quic_client_session.h"
20#include "net/quic/quic_connection.h"
21#include "net/quic/quic_connection_helper.h"
22#include "net/quic/test_tools/mock_clock.h"
[email protected]e8ff26842013-03-22 21:02:0523#include "net/quic/test_tools/mock_crypto_client_stream_factory.h"
[email protected]9db443912013-02-25 05:27:0324#include "net/quic/test_tools/mock_random.h"
[email protected]b1f287d2012-12-22 17:25:3925#include "net/quic/test_tools/quic_connection_peer.h"
[email protected]f702d572012-12-04 15:56:2026#include "net/quic/test_tools/quic_test_utils.h"
27#include "net/quic/test_tools/test_task_runner.h"
28#include "net/socket/socket_test_util.h"
[email protected]6cca996b2013-01-25 07:43:3629#include "net/spdy/spdy_frame_builder.h"
30#include "net/spdy/spdy_framer.h"
31#include "net/spdy/spdy_http_utils.h"
32#include "net/spdy/spdy_protocol.h"
[email protected]f702d572012-12-04 15:56:2033#include "testing/gmock/include/gmock/gmock.h"
34#include "testing/gtest/include/gtest/gtest.h"
35
36using testing::_;
37
38namespace net {
[email protected]f702d572012-12-04 15:56:2039namespace test {
[email protected]f702d572012-12-04 15:56:2040namespace {
41
42const char kUploadData[] = "hello world!";
43
44class TestQuicConnection : public QuicConnection {
45 public:
46 TestQuicConnection(QuicGuid guid,
47 IPEndPoint address,
48 QuicConnectionHelper* helper)
[email protected]14e8106c2013-03-14 16:25:3349 : QuicConnection(guid, address, helper, false) {
[email protected]f702d572012-12-04 15:56:2050 }
51
[email protected]fee17f72013-02-03 07:47:4152 void SetSendAlgorithm(SendAlgorithmInterface* send_algorithm) {
53 QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
[email protected]f702d572012-12-04 15:56:2054 }
[email protected]26f3f8e2012-12-13 21:07:1955
[email protected]fee17f72013-02-03 07:47:4156 void SetReceiveAlgorithm(ReceiveAlgorithmInterface* receive_algorithm) {
57 QuicConnectionPeer::SetReceiveAlgorithm(this, receive_algorithm);
[email protected]26f3f8e2012-12-13 21:07:1958 }
59};
60
[email protected]fee17f72013-02-03 07:47:4161class TestReceiveAlgorithm : public ReceiveAlgorithmInterface {
[email protected]26f3f8e2012-12-13 21:07:1962 public:
[email protected]fee17f72013-02-03 07:47:4163 explicit TestReceiveAlgorithm(QuicCongestionFeedbackFrame* feedback)
64 : feedback_(feedback) {
[email protected]26f3f8e2012-12-13 21:07:1965 }
66
67 bool GenerateCongestionFeedback(
68 QuicCongestionFeedbackFrame* congestion_feedback) {
69 if (feedback_ == NULL) {
70 return false;
71 }
72 *congestion_feedback = *feedback_;
73 return true;
74 }
75
76 MOCK_METHOD4(RecordIncomingPacket,
[email protected]fee17f72013-02-03 07:47:4177 void(QuicByteCount, QuicPacketSequenceNumber, QuicTime, bool));
[email protected]26f3f8e2012-12-13 21:07:1978
79 private:
80 MockClock clock_;
81 QuicCongestionFeedbackFrame* feedback_;
82
[email protected]fee17f72013-02-03 07:47:4183 DISALLOW_COPY_AND_ASSIGN(TestReceiveAlgorithm);
[email protected]f702d572012-12-04 15:56:2084};
85
[email protected]63534512012-12-23 18:49:0086// Subclass of QuicHttpStream that closes itself when the first piece of data
87// is received.
88class AutoClosingStream : public QuicHttpStream {
89 public:
[email protected]9d9e7932013-02-25 18:31:0590 explicit AutoClosingStream(QuicReliableClientStream* stream)
91 : QuicHttpStream(stream) {
[email protected]63534512012-12-23 18:49:0092 }
93
[email protected]46fadfd2013-02-06 09:40:1694 virtual int OnDataReceived(const char* data, int length) OVERRIDE {
[email protected]63534512012-12-23 18:49:0095 Close(false);
96 return OK;
97 }
98};
99
[email protected]f702d572012-12-04 15:56:20100} // namespace
101
[email protected]6cca996b2013-01-25 07:43:36102class QuicHttpStreamTest : public ::testing::TestWithParam<bool> {
[email protected]f702d572012-12-04 15:56:20103 protected:
104 const static bool kFin = true;
[email protected]f702d572012-12-04 15:56:20105 // Holds a packet to be written to the wire, and the IO mode that should
106 // be used by the mock socket when performing the write.
107 struct PacketToWrite {
108 PacketToWrite(IoMode mode, QuicEncryptedPacket* packet)
109 : mode(mode),
110 packet(packet) {
111 }
112 IoMode mode;
113 QuicEncryptedPacket* packet;
114 };
115
116 QuicHttpStreamTest()
117 : net_log_(BoundNetLog()),
[email protected]63534512012-12-23 18:49:00118 use_closing_stream_(false),
[email protected]f702d572012-12-04 15:56:20119 read_buffer_(new IOBufferWithSize(4096)),
120 guid_(2),
[email protected]8ba81212013-05-03 13:11:48121 framer_(kQuicVersion1, QuicTime::Zero(), false),
[email protected]14e8106c2013-03-14 16:25:33122 creator_(guid_, &framer_, &random_, false) {
[email protected]f702d572012-12-04 15:56:20123 IPAddressNumber ip;
124 CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip));
125 peer_addr_ = IPEndPoint(ip, 443);
126 self_addr_ = IPEndPoint(ip, 8435);
[email protected]f702d572012-12-04 15:56:20127 }
128
129 ~QuicHttpStreamTest() {
130 for (size_t i = 0; i < writes_.size(); i++) {
131 delete writes_[i].packet;
132 }
133 }
134
135 // Adds a packet to the list of expected writes.
136 void AddWrite(IoMode mode, QuicEncryptedPacket* packet) {
137 writes_.push_back(PacketToWrite(mode, packet));
138 }
139
140 // Returns the packet to be written at position |pos|.
141 QuicEncryptedPacket* GetWrite(size_t pos) {
142 return writes_[pos].packet;
143 }
144
145 bool AtEof() {
146 return socket_data_->at_read_eof() && socket_data_->at_write_eof();
147 }
148
149 void ProcessPacket(const QuicEncryptedPacket& packet) {
150 connection_->ProcessUdpPacket(self_addr_, peer_addr_, packet);
151 }
152
153 // Configures the test fixture to use the list of expected writes.
154 void Initialize() {
155 mock_writes_.reset(new MockWrite[writes_.size()]);
156 for (size_t i = 0; i < writes_.size(); i++) {
157 mock_writes_[i] = MockWrite(writes_[i].mode,
158 writes_[i].packet->data(),
159 writes_[i].packet->length());
160 };
161
162 socket_data_.reset(new StaticSocketDataProvider(NULL, 0, mock_writes_.get(),
163 writes_.size()));
164
[email protected]e13201d82012-12-12 05:00:32165 MockUDPClientSocket* socket = new MockUDPClientSocket(socket_data_.get(),
166 net_log_.net_log());
167 socket->Connect(peer_addr_);
[email protected]f702d572012-12-04 15:56:20168 runner_ = new TestTaskRunner(&clock_);
[email protected]fee17f72013-02-03 07:47:41169 send_algorithm_ = new MockSendAlgorithm();
170 receive_algorithm_ = new TestReceiveAlgorithm(NULL);
[email protected]14e8106c2013-03-14 16:25:33171 EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _)).
[email protected]c995c572013-01-18 05:43:20172 WillRepeatedly(testing::Return(QuicTime::Delta::Zero()));
[email protected]9558c5d32012-12-22 00:08:14173 helper_ = new QuicConnectionHelper(runner_.get(), &clock_,
174 &random_generator_, socket);
[email protected]e13201d82012-12-12 05:00:32175 connection_ = new TestQuicConnection(guid_, peer_addr_, helper_);
[email protected]f702d572012-12-04 15:56:20176 connection_->set_visitor(&visitor_);
[email protected]fee17f72013-02-03 07:47:41177 connection_->SetSendAlgorithm(send_algorithm_);
178 connection_->SetReceiveAlgorithm(receive_algorithm_);
[email protected]ef95114d2013-04-17 17:57:01179 crypto_config_.SetDefaults();
[email protected]6dcd1d5c2013-03-15 07:28:37180 session_.reset(new QuicClientSession(connection_, socket, NULL,
[email protected]e8ff26842013-03-22 21:02:05181 &crypto_client_stream_factory_,
[email protected]b064310782013-05-30 21:12:17182 "www.google.com", DefaultQuicConfig(),
[email protected]899951652013-05-16 12:52:39183 &crypto_config_, NULL));
[email protected]ed3fc15d2013-03-08 18:37:44184 session_->GetCryptoStream()->CryptoConnect();
[email protected]8ba81212013-05-03 13:11:48185 EXPECT_TRUE(session_->IsCryptoHandshakeConfirmed());
[email protected]63534512012-12-23 18:49:00186 QuicReliableClientStream* stream =
187 session_->CreateOutgoingReliableStream();
[email protected]6cca996b2013-01-25 07:43:36188 stream_.reset(use_closing_stream_ ?
[email protected]9d9e7932013-02-25 18:31:05189 new AutoClosingStream(stream) :
190 new QuicHttpStream(stream));
[email protected]6cca996b2013-01-25 07:43:36191 }
192
193 void SetRequestString(const std::string& method, const std::string& path) {
[email protected]9d9e7932013-02-25 18:31:05194 SpdyHeaderBlock headers;
195 headers[":method"] = method;
196 headers[":host"] = "www.google.com";
197 headers[":path"] = path;
198 headers[":scheme"] = "http";
199 headers[":version"] = "HTTP/1.1";
200 request_data_ = SerializeHeaderBlock(headers);
[email protected]6cca996b2013-01-25 07:43:36201 }
202
203 void SetResponseString(const std::string& status, const std::string& body) {
[email protected]9d9e7932013-02-25 18:31:05204 SpdyHeaderBlock headers;
205 headers[":status"] = status;
206 headers[":version"] = "HTTP/1.1";
207 headers["content-type"] = "text/plain";
[email protected]821555c2013-05-16 20:20:17208 response_data_ = SerializeHeaderBlock(headers) + body;
[email protected]6cca996b2013-01-25 07:43:36209 }
210
211 std::string SerializeHeaderBlock(const SpdyHeaderBlock& headers) {
[email protected]821555c2013-05-16 20:20:17212 QuicSpdyCompressor compressor;
213 return compressor.CompressHeaders(headers);
[email protected]6cca996b2013-01-25 07:43:36214 }
[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,
[email protected]e8ff26842013-03-22 21:02:05219 bool should_include_version,
[email protected]f702d572012-12-04 15:56:20220 bool fin,
221 QuicStreamOffset offset,
222 base::StringPiece data) {
[email protected]e8ff26842013-03-22 21:02:05223 InitializeHeader(sequence_number, should_include_version);
[email protected]f702d572012-12-04 15:56:20224 QuicStreamFrame frame(3, fin, offset, data);
225 return ConstructPacket(header_, QuicFrame(&frame));
226 }
227
228 // Returns a newly created packet to send ack data.
229 QuicEncryptedPacket* ConstructAckPacket(
230 QuicPacketSequenceNumber sequence_number,
[email protected]63534512012-12-23 18:49:00231 QuicPacketSequenceNumber largest_received,
232 QuicPacketSequenceNumber least_unacked) {
[email protected]e8ff26842013-03-22 21:02:05233 InitializeHeader(sequence_number, false);
[email protected]f702d572012-12-04 15:56:20234
[email protected]14e8106c2013-03-14 16:25:33235 QuicAckFrame ack(largest_received, QuicTime::Zero(), least_unacked);
[email protected]9db443912013-02-25 05:27:03236 ack.sent_info.entropy_hash = 0;
237 ack.received_info.entropy_hash = 0;
238
[email protected]f702d572012-12-04 15:56:20239 return ConstructPacket(header_, QuicFrame(&ack));
240 }
241
[email protected]63534512012-12-23 18:49:00242 // Returns a newly created packet to send ack data.
243 QuicEncryptedPacket* ConstructRstPacket(
244 QuicPacketSequenceNumber sequence_number,
[email protected]9db443912013-02-25 05:27:03245 QuicStreamId stream_id) {
[email protected]e8ff26842013-03-22 21:02:05246 InitializeHeader(sequence_number, false);
[email protected]63534512012-12-23 18:49:00247
[email protected]74bda142013-03-31 02:49:11248 QuicRstStreamFrame rst(stream_id, QUIC_STREAM_NO_ERROR);
[email protected]63534512012-12-23 18:49:00249 return ConstructPacket(header_, QuicFrame(&rst));
250 }
251
[email protected]f702d572012-12-04 15:56:20252 BoundNetLog net_log_;
[email protected]63534512012-12-23 18:49:00253 bool use_closing_stream_;
[email protected]fee17f72013-02-03 07:47:41254 MockSendAlgorithm* send_algorithm_;
255 TestReceiveAlgorithm* receive_algorithm_;
[email protected]f702d572012-12-04 15:56:20256 scoped_refptr<TestTaskRunner> runner_;
[email protected]4356f0f2013-04-07 00:58:17257 scoped_ptr<MockWrite[]> mock_writes_;
[email protected]f702d572012-12-04 15:56:20258 MockClock clock_;
[email protected]9558c5d32012-12-22 00:08:14259 MockRandom random_generator_;
[email protected]f702d572012-12-04 15:56:20260 TestQuicConnection* connection_;
[email protected]e13201d82012-12-12 05:00:32261 QuicConnectionHelper* helper_;
[email protected]f702d572012-12-04 15:56:20262 testing::StrictMock<MockConnectionVisitor> visitor_;
263 scoped_ptr<QuicHttpStream> stream_;
264 scoped_ptr<QuicClientSession> session_;
[email protected]ef95114d2013-04-17 17:57:01265 QuicCryptoClientConfig crypto_config_;
[email protected]f702d572012-12-04 15:56:20266 TestCompletionCallback callback_;
267 HttpRequestInfo request_;
268 HttpRequestHeaders headers_;
269 HttpResponseInfo response_;
270 scoped_refptr<IOBufferWithSize> read_buffer_;
[email protected]6cca996b2013-01-25 07:43:36271 std::string request_data_;
272 std::string response_data_;
[email protected]f702d572012-12-04 15:56:20273
274 private:
[email protected]e8ff26842013-03-22 21:02:05275 void InitializeHeader(QuicPacketSequenceNumber sequence_number,
276 bool should_include_version) {
[email protected]c995c572013-01-18 05:43:20277 header_.public_header.guid = guid_;
[email protected]9db443912013-02-25 05:27:03278 header_.public_header.reset_flag = false;
[email protected]e8ff26842013-03-22 21:02:05279 header_.public_header.version_flag = should_include_version;
[email protected]f702d572012-12-04 15:56:20280 header_.packet_sequence_number = sequence_number;
[email protected]f702d572012-12-04 15:56:20281 header_.fec_group = 0;
[email protected]9db443912013-02-25 05:27:03282 header_.entropy_flag = false;
283 header_.fec_flag = false;
[email protected]f702d572012-12-04 15:56:20284 }
285
286 QuicEncryptedPacket* ConstructPacket(const QuicPacketHeader& header,
287 const QuicFrame& frame) {
288 QuicFrames frames;
289 frames.push_back(frame);
[email protected]610a7e942012-12-18 00:21:39290 scoped_ptr<QuicPacket> packet(
[email protected]9db443912013-02-25 05:27:03291 framer_.ConstructFrameDataPacket(header_, frames).packet);
[email protected]8ba81212013-05-03 13:11:48292 return framer_.EncryptPacket(
293 ENCRYPTION_NONE, header.packet_sequence_number, *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_;
[email protected]9db443912013-02-25 05:27:03300 MockRandom random_;
[email protected]e8ff26842013-03-22 21:02:05301 MockCryptoClientStreamFactory crypto_client_stream_factory_;
[email protected]f702d572012-12-04 15:56:20302 QuicPacketCreator creator_;
303 QuicPacketHeader header_;
[email protected]f702d572012-12-04 15:56:20304 scoped_ptr<StaticSocketDataProvider> socket_data_;
305 std::vector<PacketToWrite> writes_;
306};
307
[email protected]9d9e7932013-02-25 18:31:05308TEST_F(QuicHttpStreamTest, RenewStreamForAuth) {
[email protected]ed3fc15d2013-03-08 18:37:44309 Initialize();
[email protected]f702d572012-12-04 15:56:20310 EXPECT_EQ(NULL, stream_->RenewStreamForAuth());
311}
312
[email protected]9d9e7932013-02-25 18:31:05313TEST_F(QuicHttpStreamTest, CanFindEndOfResponse) {
[email protected]ed3fc15d2013-03-08 18:37:44314 Initialize();
[email protected]f702d572012-12-04 15:56:20315 EXPECT_TRUE(stream_->CanFindEndOfResponse());
316}
317
[email protected]9d9e7932013-02-25 18:31:05318TEST_F(QuicHttpStreamTest, IsConnectionReusable) {
[email protected]ed3fc15d2013-03-08 18:37:44319 Initialize();
[email protected]f702d572012-12-04 15:56:20320 EXPECT_FALSE(stream_->IsConnectionReusable());
321}
322
[email protected]9d9e7932013-02-25 18:31:05323TEST_F(QuicHttpStreamTest, GetRequest) {
[email protected]6cca996b2013-01-25 07:43:36324 SetRequestString("GET", "/");
[email protected]e8ff26842013-03-22 21:02:05325 AddWrite(SYNCHRONOUS, ConstructDataPacket(1, true, kFin, 0,
[email protected]6cca996b2013-01-25 07:43:36326 request_data_));
[email protected]e8ff26842013-03-22 21:02:05327 AddWrite(SYNCHRONOUS, ConstructAckPacket(2, 2, 1));
[email protected]f702d572012-12-04 15:56:20328 Initialize();
329
330 request_.method = "GET";
331 request_.url = GURL("http://www.google.com/");
332
[email protected]262eec82013-03-19 21:01:36333 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
334 net_log_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20335 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
336 callback_.callback()));
337 EXPECT_EQ(&response_, stream_->GetResponseInfo());
338
339 // Ack the request.
[email protected]e8ff26842013-03-22 21:02:05340 scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0, 0));
[email protected]f702d572012-12-04 15:56:20341 ProcessPacket(*ack);
342
343 EXPECT_EQ(ERR_IO_PENDING,
344 stream_->ReadResponseHeaders(callback_.callback()));
345
346 // Send the response without a body.
[email protected]007b3f82013-04-09 08:46:45347 SetResponseString("404 Not Found", std::string());
[email protected]f702d572012-12-04 15:56:20348 scoped_ptr<QuicEncryptedPacket> resp(
[email protected]e8ff26842013-03-22 21:02:05349 ConstructDataPacket(2, false, kFin, 0, response_data_));
[email protected]f702d572012-12-04 15:56:20350 ProcessPacket(*resp);
351
352 // Now that the headers have been processed, the callback will return.
353 EXPECT_EQ(OK, callback_.WaitForResult());
[email protected]25c31dc2013-06-05 17:56:04354 ASSERT_TRUE(response_.headers);
[email protected]f702d572012-12-04 15:56:20355 EXPECT_EQ(404, response_.headers->response_code());
356 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
357
358 // There is no body, so this should return immediately.
359 EXPECT_EQ(0, stream_->ReadResponseBody(read_buffer_.get(),
360 read_buffer_->size(),
361 callback_.callback()));
362 EXPECT_TRUE(stream_->IsResponseBodyComplete());
363 EXPECT_TRUE(AtEof());
364}
365
[email protected]9d9e7932013-02-25 18:31:05366TEST_F(QuicHttpStreamTest, GetRequestFullResponseInSinglePacket) {
[email protected]6cca996b2013-01-25 07:43:36367 SetRequestString("GET", "/");
[email protected]e8ff26842013-03-22 21:02:05368 AddWrite(SYNCHRONOUS, ConstructDataPacket(1, true, kFin, 0, request_data_));
369 AddWrite(SYNCHRONOUS, ConstructAckPacket(2, 2, 1));
[email protected]f702d572012-12-04 15:56:20370 Initialize();
371
372 request_.method = "GET";
373 request_.url = GURL("http://www.google.com/");
374
[email protected]262eec82013-03-19 21:01:36375 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
376 net_log_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20377 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
378 callback_.callback()));
379 EXPECT_EQ(&response_, stream_->GetResponseInfo());
380
381 // Ack the request.
[email protected]e8ff26842013-03-22 21:02:05382 scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0, 0));
[email protected]f702d572012-12-04 15:56:20383 ProcessPacket(*ack);
384
385 EXPECT_EQ(ERR_IO_PENDING,
386 stream_->ReadResponseHeaders(callback_.callback()));
387
388 // Send the response with a body.
[email protected]6cca996b2013-01-25 07:43:36389 SetResponseString("200 OK", "hello world!");
[email protected]f702d572012-12-04 15:56:20390 scoped_ptr<QuicEncryptedPacket> resp(
[email protected]e8ff26842013-03-22 21:02:05391 ConstructDataPacket(2, false, kFin, 0, response_data_));
[email protected]f702d572012-12-04 15:56:20392 ProcessPacket(*resp);
393
394 // Now that the headers have been processed, the callback will return.
395 EXPECT_EQ(OK, callback_.WaitForResult());
[email protected]25c31dc2013-06-05 17:56:04396 ASSERT_TRUE(response_.headers);
[email protected]6cca996b2013-01-25 07:43:36397 EXPECT_EQ(200, response_.headers->response_code());
[email protected]f702d572012-12-04 15:56:20398 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
399
400 // There is no body, so this should return immediately.
401 // Since the body has already arrived, this should return immediately.
402 EXPECT_EQ(12, stream_->ReadResponseBody(read_buffer_.get(),
403 read_buffer_->size(),
404 callback_.callback()));
405 EXPECT_TRUE(stream_->IsResponseBodyComplete());
406 EXPECT_TRUE(AtEof());
407}
408
[email protected]9d9e7932013-02-25 18:31:05409TEST_F(QuicHttpStreamTest, SendPostRequest) {
[email protected]6cca996b2013-01-25 07:43:36410 SetRequestString("POST", "/");
[email protected]e8ff26842013-03-22 21:02:05411 AddWrite(SYNCHRONOUS, ConstructDataPacket(1, true, !kFin, 0, request_data_));
412 AddWrite(SYNCHRONOUS, ConstructDataPacket(2, true, kFin,
413 request_data_.length(),
[email protected]f702d572012-12-04 15:56:20414 kUploadData));
[email protected]e8ff26842013-03-22 21:02:05415 AddWrite(SYNCHRONOUS, ConstructAckPacket(3, 2, 1));
[email protected]f702d572012-12-04 15:56:20416
417 Initialize();
418
[email protected]b2d26cfd2012-12-11 10:36:06419 ScopedVector<UploadElementReader> element_readers;
420 element_readers.push_back(
421 new UploadBytesElementReader(kUploadData, strlen(kUploadData)));
422 UploadDataStream upload_data_stream(&element_readers, 0);
[email protected]f702d572012-12-04 15:56:20423 request_.method = "POST";
424 request_.url = GURL("http://www.google.com/");
425 request_.upload_data_stream = &upload_data_stream;
[email protected]4db27d82012-12-20 11:50:24426 ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback()));
[email protected]f702d572012-12-04 15:56:20427
[email protected]262eec82013-03-19 21:01:36428 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
429 net_log_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20430 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
431 callback_.callback()));
432 EXPECT_EQ(&response_, stream_->GetResponseInfo());
433
434 // Ack both packets in the request.
[email protected]e8ff26842013-03-22 21:02:05435 scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0, 0));
[email protected]f702d572012-12-04 15:56:20436 ProcessPacket(*ack);
437
438 // Send the response headers (but not the body).
[email protected]007b3f82013-04-09 08:46:45439 SetResponseString("200 OK", std::string());
[email protected]f702d572012-12-04 15:56:20440 scoped_ptr<QuicEncryptedPacket> resp(
[email protected]e8ff26842013-03-22 21:02:05441 ConstructDataPacket(2, false, !kFin, 0, response_data_));
[email protected]f702d572012-12-04 15:56:20442 ProcessPacket(*resp);
443
444 // Since the headers have already arrived, this should return immediately.
445 EXPECT_EQ(OK, stream_->ReadResponseHeaders(callback_.callback()));
[email protected]25c31dc2013-06-05 17:56:04446 ASSERT_TRUE(response_.headers);
[email protected]f702d572012-12-04 15:56:20447 EXPECT_EQ(200, response_.headers->response_code());
448 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
449
450 // Send the response body.
451 const char kResponseBody[] = "Hello world!";
452 scoped_ptr<QuicEncryptedPacket> resp_body(
[email protected]e8ff26842013-03-22 21:02:05453 ConstructDataPacket(3, false, kFin, response_data_.length(),
454 kResponseBody));
[email protected]f702d572012-12-04 15:56:20455 ProcessPacket(*resp_body);
456
457 // Since the body has already arrived, this should return immediately.
458 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
459 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
460 callback_.callback()));
461
462 EXPECT_TRUE(stream_->IsResponseBodyComplete());
463 EXPECT_TRUE(AtEof());
464}
465
[email protected]c9e49a02013-02-26 05:56:47466TEST_F(QuicHttpStreamTest, SendChunkedPostRequest) {
467 SetRequestString("POST", "/");
468 size_t chunk_size = strlen(kUploadData);
[email protected]e8ff26842013-03-22 21:02:05469 AddWrite(SYNCHRONOUS, ConstructDataPacket(1, true, !kFin, 0, request_data_));
470 AddWrite(SYNCHRONOUS, ConstructDataPacket(2, true, !kFin,
471 request_data_.length(),
[email protected]c9e49a02013-02-26 05:56:47472 kUploadData));
[email protected]e8ff26842013-03-22 21:02:05473 AddWrite(SYNCHRONOUS, ConstructDataPacket(3, true, kFin,
[email protected]c9e49a02013-02-26 05:56:47474 request_data_.length() + chunk_size,
475 kUploadData));
[email protected]e8ff26842013-03-22 21:02:05476 AddWrite(SYNCHRONOUS, ConstructAckPacket(4, 2, 1));
[email protected]c9e49a02013-02-26 05:56:47477
478 Initialize();
479
480 UploadDataStream upload_data_stream(UploadDataStream::CHUNKED, 0);
481 upload_data_stream.AppendChunk(kUploadData, chunk_size, false);
482
483 request_.method = "POST";
484 request_.url = GURL("http://www.google.com/");
485 request_.upload_data_stream = &upload_data_stream;
486 ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback()));
487
[email protected]262eec82013-03-19 21:01:36488 ASSERT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
489 net_log_, callback_.callback()));
[email protected]c9e49a02013-02-26 05:56:47490 ASSERT_EQ(ERR_IO_PENDING, stream_->SendRequest(headers_, &response_,
491 callback_.callback()));
492 EXPECT_EQ(&response_, stream_->GetResponseInfo());
493
494 upload_data_stream.AppendChunk(kUploadData, chunk_size, true);
495
496 // Ack both packets in the request.
[email protected]e8ff26842013-03-22 21:02:05497 scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0, 0));
[email protected]c9e49a02013-02-26 05:56:47498 ProcessPacket(*ack);
499
500 // Send the response headers (but not the body).
[email protected]007b3f82013-04-09 08:46:45501 SetResponseString("200 OK", std::string());
[email protected]c9e49a02013-02-26 05:56:47502 scoped_ptr<QuicEncryptedPacket> resp(
[email protected]e8ff26842013-03-22 21:02:05503 ConstructDataPacket(2, false, !kFin, 0, response_data_));
[email protected]c9e49a02013-02-26 05:56:47504 ProcessPacket(*resp);
505
506 // Since the headers have already arrived, this should return immediately.
507 ASSERT_EQ(OK, stream_->ReadResponseHeaders(callback_.callback()));
[email protected]25c31dc2013-06-05 17:56:04508 ASSERT_TRUE(response_.headers);
[email protected]c9e49a02013-02-26 05:56:47509 EXPECT_EQ(200, response_.headers->response_code());
510 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
511
512 // Send the response body.
513 const char kResponseBody[] = "Hello world!";
514 scoped_ptr<QuicEncryptedPacket> resp_body(
[email protected]e8ff26842013-03-22 21:02:05515 ConstructDataPacket(3, false, kFin, response_data_.length(),
516 kResponseBody));
[email protected]c9e49a02013-02-26 05:56:47517 ProcessPacket(*resp_body);
518
519 // Since the body has already arrived, this should return immediately.
520 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
521 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
522 callback_.callback()));
523
524 EXPECT_TRUE(stream_->IsResponseBodyComplete());
525 EXPECT_TRUE(AtEof());
526}
527
[email protected]9d9e7932013-02-25 18:31:05528TEST_F(QuicHttpStreamTest, DestroyedEarly) {
[email protected]6cca996b2013-01-25 07:43:36529 SetRequestString("GET", "/");
[email protected]e8ff26842013-03-22 21:02:05530 AddWrite(SYNCHRONOUS, ConstructDataPacket(1, true, kFin, 0, request_data_));
[email protected]25c31dc2013-06-05 17:56:04531 AddWrite(SYNCHRONOUS, ConstructAckPacket(2, 2, 1));
[email protected]63534512012-12-23 18:49:00532 use_closing_stream_ = true;
533 Initialize();
534
535 request_.method = "GET";
536 request_.url = GURL("http://www.google.com/");
537
[email protected]262eec82013-03-19 21:01:36538 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
539 net_log_, callback_.callback()));
[email protected]63534512012-12-23 18:49:00540 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
541 callback_.callback()));
542 EXPECT_EQ(&response_, stream_->GetResponseInfo());
543
544 // Ack the request.
[email protected]e8ff26842013-03-22 21:02:05545 scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0, 0));
[email protected]63534512012-12-23 18:49:00546 ProcessPacket(*ack);
547 EXPECT_EQ(ERR_IO_PENDING,
548 stream_->ReadResponseHeaders(callback_.callback()));
549
550 // Send the response with a body.
[email protected]c244c5a12013-05-07 20:55:04551 SetResponseString("404 OK", "hello world!");
[email protected]63534512012-12-23 18:49:00552 scoped_ptr<QuicEncryptedPacket> resp(
[email protected]c244c5a12013-05-07 20:55:04553 ConstructDataPacket(2, false, kFin, 0, response_data_));
[email protected]63534512012-12-23 18:49:00554
555 // In the course of processing this packet, the QuicHttpStream close itself.
556 ProcessPacket(*resp);
557
558 EXPECT_TRUE(AtEof());
559}
560
[email protected]f702d572012-12-04 15:56:20561} // namespace test
562
563} // namespace net