blob: 7f4fef70e70f9ee2bf7c00a7e50c14a575f277ff [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]5351cc4b2013-03-03 07:22:41121 framer_(kQuicVersion1,
122 QuicDecrypter::Create(kNULL),
[email protected]14e8106c2013-03-14 16:25:33123 QuicEncrypter::Create(kNULL),
124 false),
125 creator_(guid_, &framer_, &random_, false) {
[email protected]f702d572012-12-04 15:56:20126 IPAddressNumber ip;
127 CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip));
128 peer_addr_ = IPEndPoint(ip, 443);
129 self_addr_ = IPEndPoint(ip, 8435);
[email protected]f702d572012-12-04 15:56:20130 }
131
132 ~QuicHttpStreamTest() {
133 for (size_t i = 0; i < writes_.size(); i++) {
134 delete writes_[i].packet;
135 }
136 }
137
138 // Adds a packet to the list of expected writes.
139 void AddWrite(IoMode mode, QuicEncryptedPacket* packet) {
140 writes_.push_back(PacketToWrite(mode, packet));
141 }
142
143 // Returns the packet to be written at position |pos|.
144 QuicEncryptedPacket* GetWrite(size_t pos) {
145 return writes_[pos].packet;
146 }
147
148 bool AtEof() {
149 return socket_data_->at_read_eof() && socket_data_->at_write_eof();
150 }
151
152 void ProcessPacket(const QuicEncryptedPacket& packet) {
153 connection_->ProcessUdpPacket(self_addr_, peer_addr_, packet);
154 }
155
156 // Configures the test fixture to use the list of expected writes.
157 void Initialize() {
158 mock_writes_.reset(new MockWrite[writes_.size()]);
159 for (size_t i = 0; i < writes_.size(); i++) {
160 mock_writes_[i] = MockWrite(writes_[i].mode,
161 writes_[i].packet->data(),
162 writes_[i].packet->length());
163 };
164
165 socket_data_.reset(new StaticSocketDataProvider(NULL, 0, mock_writes_.get(),
166 writes_.size()));
167
[email protected]e13201d82012-12-12 05:00:32168 MockUDPClientSocket* socket = new MockUDPClientSocket(socket_data_.get(),
169 net_log_.net_log());
170 socket->Connect(peer_addr_);
[email protected]f702d572012-12-04 15:56:20171 runner_ = new TestTaskRunner(&clock_);
[email protected]fee17f72013-02-03 07:47:41172 send_algorithm_ = new MockSendAlgorithm();
173 receive_algorithm_ = new TestReceiveAlgorithm(NULL);
[email protected]14e8106c2013-03-14 16:25:33174 EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _)).
[email protected]c995c572013-01-18 05:43:20175 WillRepeatedly(testing::Return(QuicTime::Delta::Zero()));
[email protected]9558c5d32012-12-22 00:08:14176 helper_ = new QuicConnectionHelper(runner_.get(), &clock_,
177 &random_generator_, socket);
[email protected]e13201d82012-12-12 05:00:32178 connection_ = new TestQuicConnection(guid_, peer_addr_, helper_);
[email protected]f702d572012-12-04 15:56:20179 connection_->set_visitor(&visitor_);
[email protected]fee17f72013-02-03 07:47:41180 connection_->SetSendAlgorithm(send_algorithm_);
181 connection_->SetReceiveAlgorithm(receive_algorithm_);
[email protected]6dcd1d5c2013-03-15 07:28:37182 session_.reset(new QuicClientSession(connection_, socket, NULL,
[email protected]e8ff26842013-03-22 21:02:05183 &crypto_client_stream_factory_,
[email protected]0d10b592013-02-14 16:09:26184 "www.google.com", NULL));
[email protected]ed3fc15d2013-03-08 18:37:44185 session_->GetCryptoStream()->CryptoConnect();
[email protected]f702d572012-12-04 15:56:20186 EXPECT_TRUE(session_->IsCryptoHandshakeComplete());
[email protected]63534512012-12-23 18:49:00187 QuicReliableClientStream* stream =
188 session_->CreateOutgoingReliableStream();
[email protected]6cca996b2013-01-25 07:43:36189 stream_.reset(use_closing_stream_ ?
[email protected]9d9e7932013-02-25 18:31:05190 new AutoClosingStream(stream) :
191 new QuicHttpStream(stream));
[email protected]6cca996b2013-01-25 07:43:36192 }
193
194 void SetRequestString(const std::string& method, const std::string& path) {
[email protected]9d9e7932013-02-25 18:31:05195 SpdyHeaderBlock headers;
196 headers[":method"] = method;
197 headers[":host"] = "www.google.com";
198 headers[":path"] = path;
199 headers[":scheme"] = "http";
200 headers[":version"] = "HTTP/1.1";
201 request_data_ = SerializeHeaderBlock(headers);
[email protected]6cca996b2013-01-25 07:43:36202 }
203
204 void SetResponseString(const std::string& status, const std::string& body) {
[email protected]9d9e7932013-02-25 18:31:05205 SpdyHeaderBlock headers;
206 headers[":status"] = status;
207 headers[":version"] = "HTTP/1.1";
208 headers["content-type"] = "text/plain";
209 response_data_ = SerializeHeaderBlock(headers) + body;
[email protected]6cca996b2013-01-25 07:43:36210 }
211
212 std::string SerializeHeaderBlock(const SpdyHeaderBlock& headers) {
213 size_t len = SpdyFramer::GetSerializedLength(3, &headers);
214 SpdyFrameBuilder builder(len);
215 SpdyFramer::WriteHeaderBlock(&builder, 3, &headers);
216 scoped_ptr<SpdyFrame> frame(builder.take());
217 return std::string(frame->data(), len);
218 }
[email protected]f702d572012-12-04 15:56:20219
220 // Returns a newly created packet to send kData on stream 1.
221 QuicEncryptedPacket* ConstructDataPacket(
222 QuicPacketSequenceNumber sequence_number,
[email protected]e8ff26842013-03-22 21:02:05223 bool should_include_version,
[email protected]f702d572012-12-04 15:56:20224 bool fin,
225 QuicStreamOffset offset,
226 base::StringPiece data) {
[email protected]e8ff26842013-03-22 21:02:05227 InitializeHeader(sequence_number, should_include_version);
[email protected]f702d572012-12-04 15:56:20228 QuicStreamFrame frame(3, fin, offset, data);
229 return ConstructPacket(header_, QuicFrame(&frame));
230 }
231
232 // Returns a newly created packet to send ack data.
233 QuicEncryptedPacket* ConstructAckPacket(
234 QuicPacketSequenceNumber sequence_number,
[email protected]63534512012-12-23 18:49:00235 QuicPacketSequenceNumber largest_received,
236 QuicPacketSequenceNumber least_unacked) {
[email protected]e8ff26842013-03-22 21:02:05237 InitializeHeader(sequence_number, false);
[email protected]f702d572012-12-04 15:56:20238
[email protected]14e8106c2013-03-14 16:25:33239 QuicAckFrame ack(largest_received, QuicTime::Zero(), least_unacked);
[email protected]9db443912013-02-25 05:27:03240 ack.sent_info.entropy_hash = 0;
241 ack.received_info.entropy_hash = 0;
242
[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,
[email protected]9db443912013-02-25 05:27:03249 QuicStreamId stream_id) {
[email protected]e8ff26842013-03-22 21:02:05250 InitializeHeader(sequence_number, false);
[email protected]63534512012-12-23 18:49:00251
[email protected]9db443912013-02-25 05:27:03252 QuicRstStreamFrame rst(stream_id, QUIC_NO_ERROR);
[email protected]63534512012-12-23 18:49:00253 return ConstructPacket(header_, QuicFrame(&rst));
254 }
255
[email protected]f702d572012-12-04 15:56:20256 BoundNetLog net_log_;
[email protected]63534512012-12-23 18:49:00257 bool use_closing_stream_;
[email protected]fee17f72013-02-03 07:47:41258 MockSendAlgorithm* send_algorithm_;
259 TestReceiveAlgorithm* receive_algorithm_;
[email protected]f702d572012-12-04 15:56:20260 scoped_refptr<TestTaskRunner> runner_;
261 scoped_array<MockWrite> mock_writes_;
262 MockClock clock_;
[email protected]9558c5d32012-12-22 00:08:14263 MockRandom random_generator_;
[email protected]f702d572012-12-04 15:56:20264 TestQuicConnection* connection_;
[email protected]e13201d82012-12-12 05:00:32265 QuicConnectionHelper* helper_;
[email protected]f702d572012-12-04 15:56:20266 testing::StrictMock<MockConnectionVisitor> visitor_;
267 scoped_ptr<QuicHttpStream> stream_;
268 scoped_ptr<QuicClientSession> session_;
269 TestCompletionCallback callback_;
270 HttpRequestInfo request_;
271 HttpRequestHeaders headers_;
272 HttpResponseInfo response_;
273 scoped_refptr<IOBufferWithSize> read_buffer_;
[email protected]6cca996b2013-01-25 07:43:36274 std::string request_data_;
275 std::string response_data_;
[email protected]f702d572012-12-04 15:56:20276
277 private:
[email protected]e8ff26842013-03-22 21:02:05278 void InitializeHeader(QuicPacketSequenceNumber sequence_number,
279 bool should_include_version) {
[email protected]c995c572013-01-18 05:43:20280 header_.public_header.guid = guid_;
[email protected]9db443912013-02-25 05:27:03281 header_.public_header.reset_flag = false;
[email protected]e8ff26842013-03-22 21:02:05282 header_.public_header.version_flag = should_include_version;
[email protected]f702d572012-12-04 15:56:20283 header_.packet_sequence_number = sequence_number;
[email protected]f702d572012-12-04 15:56:20284 header_.fec_group = 0;
[email protected]9db443912013-02-25 05:27:03285 header_.fec_entropy_flag = false;
286 header_.entropy_flag = false;
287 header_.fec_flag = false;
[email protected]f702d572012-12-04 15:56:20288 }
289
290 QuicEncryptedPacket* ConstructPacket(const QuicPacketHeader& header,
291 const QuicFrame& frame) {
292 QuicFrames frames;
293 frames.push_back(frame);
[email protected]610a7e942012-12-18 00:21:39294 scoped_ptr<QuicPacket> packet(
[email protected]9db443912013-02-25 05:27:03295 framer_.ConstructFrameDataPacket(header_, frames).packet);
296 return framer_.EncryptPacket(header.packet_sequence_number, *packet);
[email protected]f702d572012-12-04 15:56:20297 }
298
299 const QuicGuid guid_;
300 QuicFramer framer_;
301 IPEndPoint self_addr_;
302 IPEndPoint peer_addr_;
[email protected]9db443912013-02-25 05:27:03303 MockRandom random_;
[email protected]e8ff26842013-03-22 21:02:05304 MockCryptoClientStreamFactory crypto_client_stream_factory_;
[email protected]f702d572012-12-04 15:56:20305 QuicPacketCreator creator_;
306 QuicPacketHeader header_;
[email protected]f702d572012-12-04 15:56:20307 scoped_ptr<StaticSocketDataProvider> socket_data_;
308 std::vector<PacketToWrite> writes_;
309};
310
[email protected]9d9e7932013-02-25 18:31:05311TEST_F(QuicHttpStreamTest, RenewStreamForAuth) {
[email protected]ed3fc15d2013-03-08 18:37:44312 Initialize();
[email protected]f702d572012-12-04 15:56:20313 EXPECT_EQ(NULL, stream_->RenewStreamForAuth());
314}
315
[email protected]9d9e7932013-02-25 18:31:05316TEST_F(QuicHttpStreamTest, CanFindEndOfResponse) {
[email protected]ed3fc15d2013-03-08 18:37:44317 Initialize();
[email protected]f702d572012-12-04 15:56:20318 EXPECT_TRUE(stream_->CanFindEndOfResponse());
319}
320
[email protected]9d9e7932013-02-25 18:31:05321TEST_F(QuicHttpStreamTest, IsConnectionReusable) {
[email protected]ed3fc15d2013-03-08 18:37:44322 Initialize();
[email protected]f702d572012-12-04 15:56:20323 EXPECT_FALSE(stream_->IsConnectionReusable());
324}
325
[email protected]9d9e7932013-02-25 18:31:05326TEST_F(QuicHttpStreamTest, GetRequest) {
[email protected]6cca996b2013-01-25 07:43:36327 SetRequestString("GET", "/");
[email protected]e8ff26842013-03-22 21:02:05328 AddWrite(SYNCHRONOUS, ConstructDataPacket(1, true, kFin, 0,
[email protected]6cca996b2013-01-25 07:43:36329 request_data_));
[email protected]e8ff26842013-03-22 21:02:05330 AddWrite(SYNCHRONOUS, ConstructAckPacket(2, 2, 1));
[email protected]f702d572012-12-04 15:56:20331 Initialize();
332
333 request_.method = "GET";
334 request_.url = GURL("http://www.google.com/");
335
[email protected]262eec82013-03-19 21:01:36336 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
337 net_log_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20338 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
339 callback_.callback()));
340 EXPECT_EQ(&response_, stream_->GetResponseInfo());
341
342 // Ack the request.
[email protected]e8ff26842013-03-22 21:02:05343 scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0, 0));
[email protected]f702d572012-12-04 15:56:20344 ProcessPacket(*ack);
345
346 EXPECT_EQ(ERR_IO_PENDING,
347 stream_->ReadResponseHeaders(callback_.callback()));
348
349 // Send the response without a body.
[email protected]6cca996b2013-01-25 07:43:36350 SetResponseString("404 Not Found", "");
[email protected]f702d572012-12-04 15:56:20351 scoped_ptr<QuicEncryptedPacket> resp(
[email protected]e8ff26842013-03-22 21:02:05352 ConstructDataPacket(2, false, kFin, 0, response_data_));
[email protected]f702d572012-12-04 15:56:20353 ProcessPacket(*resp);
354
355 // Now that the headers have been processed, the callback will return.
356 EXPECT_EQ(OK, callback_.WaitForResult());
357 ASSERT_TRUE(response_.headers != NULL);
358 EXPECT_EQ(404, response_.headers->response_code());
359 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
360
361 // There is no body, so this should return immediately.
362 EXPECT_EQ(0, stream_->ReadResponseBody(read_buffer_.get(),
363 read_buffer_->size(),
364 callback_.callback()));
365 EXPECT_TRUE(stream_->IsResponseBodyComplete());
366 EXPECT_TRUE(AtEof());
367}
368
[email protected]9d9e7932013-02-25 18:31:05369TEST_F(QuicHttpStreamTest, GetRequestFullResponseInSinglePacket) {
[email protected]6cca996b2013-01-25 07:43:36370 SetRequestString("GET", "/");
[email protected]e8ff26842013-03-22 21:02:05371 AddWrite(SYNCHRONOUS, ConstructDataPacket(1, true, kFin, 0, request_data_));
372 AddWrite(SYNCHRONOUS, ConstructAckPacket(2, 2, 1));
[email protected]f702d572012-12-04 15:56:20373 Initialize();
374
375 request_.method = "GET";
376 request_.url = GURL("http://www.google.com/");
377
[email protected]262eec82013-03-19 21:01:36378 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
379 net_log_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20380 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
381 callback_.callback()));
382 EXPECT_EQ(&response_, stream_->GetResponseInfo());
383
384 // Ack the request.
[email protected]e8ff26842013-03-22 21:02:05385 scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0, 0));
[email protected]f702d572012-12-04 15:56:20386 ProcessPacket(*ack);
387
388 EXPECT_EQ(ERR_IO_PENDING,
389 stream_->ReadResponseHeaders(callback_.callback()));
390
391 // Send the response with a body.
[email protected]6cca996b2013-01-25 07:43:36392 SetResponseString("200 OK", "hello world!");
[email protected]f702d572012-12-04 15:56:20393 scoped_ptr<QuicEncryptedPacket> resp(
[email protected]e8ff26842013-03-22 21:02:05394 ConstructDataPacket(2, false, kFin, 0, response_data_));
[email protected]f702d572012-12-04 15:56:20395 ProcessPacket(*resp);
396
397 // Now that the headers have been processed, the callback will return.
398 EXPECT_EQ(OK, callback_.WaitForResult());
399 ASSERT_TRUE(response_.headers != NULL);
[email protected]6cca996b2013-01-25 07:43:36400 EXPECT_EQ(200, response_.headers->response_code());
[email protected]f702d572012-12-04 15:56:20401 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
402
403 // There is no body, so this should return immediately.
404 // Since the body has already arrived, this should return immediately.
405 EXPECT_EQ(12, stream_->ReadResponseBody(read_buffer_.get(),
406 read_buffer_->size(),
407 callback_.callback()));
408 EXPECT_TRUE(stream_->IsResponseBodyComplete());
409 EXPECT_TRUE(AtEof());
410}
411
[email protected]9d9e7932013-02-25 18:31:05412TEST_F(QuicHttpStreamTest, SendPostRequest) {
[email protected]6cca996b2013-01-25 07:43:36413 SetRequestString("POST", "/");
[email protected]e8ff26842013-03-22 21:02:05414 AddWrite(SYNCHRONOUS, ConstructDataPacket(1, true, !kFin, 0, request_data_));
415 AddWrite(SYNCHRONOUS, ConstructDataPacket(2, true, kFin,
416 request_data_.length(),
[email protected]f702d572012-12-04 15:56:20417 kUploadData));
[email protected]e8ff26842013-03-22 21:02:05418 AddWrite(SYNCHRONOUS, ConstructAckPacket(3, 2, 1));
[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
[email protected]262eec82013-03-19 21:01:36431 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
432 net_log_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20433 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]e8ff26842013-03-22 21:02:05438 scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0, 0));
[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]e8ff26842013-03-22 21:02:05444 ConstructDataPacket(2, false, !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]e8ff26842013-03-22 21:02:05456 ConstructDataPacket(3, false, kFin, response_data_.length(),
457 kResponseBody));
[email protected]f702d572012-12-04 15:56:20458 ProcessPacket(*resp_body);
459
460 // Since the body has already arrived, this should return immediately.
461 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
462 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
463 callback_.callback()));
464
465 EXPECT_TRUE(stream_->IsResponseBodyComplete());
466 EXPECT_TRUE(AtEof());
467}
468
[email protected]c9e49a02013-02-26 05:56:47469TEST_F(QuicHttpStreamTest, SendChunkedPostRequest) {
470 SetRequestString("POST", "/");
471 size_t chunk_size = strlen(kUploadData);
[email protected]e8ff26842013-03-22 21:02:05472 AddWrite(SYNCHRONOUS, ConstructDataPacket(1, true, !kFin, 0, request_data_));
473 AddWrite(SYNCHRONOUS, ConstructDataPacket(2, true, !kFin,
474 request_data_.length(),
[email protected]c9e49a02013-02-26 05:56:47475 kUploadData));
[email protected]e8ff26842013-03-22 21:02:05476 AddWrite(SYNCHRONOUS, ConstructDataPacket(3, true, kFin,
[email protected]c9e49a02013-02-26 05:56:47477 request_data_.length() + chunk_size,
478 kUploadData));
[email protected]e8ff26842013-03-22 21:02:05479 AddWrite(SYNCHRONOUS, ConstructAckPacket(4, 2, 1));
[email protected]c9e49a02013-02-26 05:56:47480
481 Initialize();
482
483 UploadDataStream upload_data_stream(UploadDataStream::CHUNKED, 0);
484 upload_data_stream.AppendChunk(kUploadData, chunk_size, false);
485
486 request_.method = "POST";
487 request_.url = GURL("http://www.google.com/");
488 request_.upload_data_stream = &upload_data_stream;
489 ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback()));
490
[email protected]262eec82013-03-19 21:01:36491 ASSERT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
492 net_log_, callback_.callback()));
[email protected]c9e49a02013-02-26 05:56:47493 ASSERT_EQ(ERR_IO_PENDING, stream_->SendRequest(headers_, &response_,
494 callback_.callback()));
495 EXPECT_EQ(&response_, stream_->GetResponseInfo());
496
497 upload_data_stream.AppendChunk(kUploadData, chunk_size, true);
498
499 // Ack both packets in the request.
[email protected]e8ff26842013-03-22 21:02:05500 scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0, 0));
[email protected]c9e49a02013-02-26 05:56:47501 ProcessPacket(*ack);
502
503 // Send the response headers (but not the body).
504 SetResponseString("200 OK", "");
505 scoped_ptr<QuicEncryptedPacket> resp(
[email protected]e8ff26842013-03-22 21:02:05506 ConstructDataPacket(2, false, !kFin, 0, response_data_));
[email protected]c9e49a02013-02-26 05:56:47507 ProcessPacket(*resp);
508
509 // Since the headers have already arrived, this should return immediately.
510 ASSERT_EQ(OK, stream_->ReadResponseHeaders(callback_.callback()));
511 ASSERT_TRUE(response_.headers != NULL);
512 EXPECT_EQ(200, response_.headers->response_code());
513 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
514
515 // Send the response body.
516 const char kResponseBody[] = "Hello world!";
517 scoped_ptr<QuicEncryptedPacket> resp_body(
[email protected]e8ff26842013-03-22 21:02:05518 ConstructDataPacket(3, false, kFin, response_data_.length(),
519 kResponseBody));
[email protected]c9e49a02013-02-26 05:56:47520 ProcessPacket(*resp_body);
521
522 // Since the body has already arrived, this should return immediately.
523 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
524 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
525 callback_.callback()));
526
527 EXPECT_TRUE(stream_->IsResponseBodyComplete());
528 EXPECT_TRUE(AtEof());
529}
530
[email protected]9d9e7932013-02-25 18:31:05531TEST_F(QuicHttpStreamTest, DestroyedEarly) {
[email protected]6cca996b2013-01-25 07:43:36532 SetRequestString("GET", "/");
[email protected]e8ff26842013-03-22 21:02:05533 AddWrite(SYNCHRONOUS, ConstructDataPacket(1, true, kFin, 0, request_data_));
534 AddWrite(SYNCHRONOUS, ConstructRstPacket(2, 3));
535 AddWrite(SYNCHRONOUS, ConstructAckPacket(3, 2, 1));
[email protected]63534512012-12-23 18:49:00536 use_closing_stream_ = true;
537 Initialize();
538
539 request_.method = "GET";
540 request_.url = GURL("http://www.google.com/");
541
[email protected]262eec82013-03-19 21:01:36542 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
543 net_log_, callback_.callback()));
[email protected]63534512012-12-23 18:49:00544 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
545 callback_.callback()));
546 EXPECT_EQ(&response_, stream_->GetResponseInfo());
547
548 // Ack the request.
[email protected]e8ff26842013-03-22 21:02:05549 scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0, 0));
[email protected]63534512012-12-23 18:49:00550 ProcessPacket(*ack);
551 EXPECT_EQ(ERR_IO_PENDING,
552 stream_->ReadResponseHeaders(callback_.callback()));
553
554 // Send the response with a body.
555 const char kResponseHeaders[] = "HTTP/1.1 404 OK\r\n"
556 "Content-Type: text/plain\r\n\r\nhello world!";
557 scoped_ptr<QuicEncryptedPacket> resp(
[email protected]e8ff26842013-03-22 21:02:05558 ConstructDataPacket(2, false, kFin, 0, kResponseHeaders));
[email protected]63534512012-12-23 18:49:00559
560 // In the course of processing this packet, the QuicHttpStream close itself.
561 ProcessPacket(*resp);
562
563 EXPECT_TRUE(AtEof());
564}
565
[email protected]f702d572012-12-04 15:56:20566} // namespace test
567
568} // namespace net