blob: b5a342cea034c627858974715aa58cf56e319bbd [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]4df69842013-02-27 06:32:1616#include "net/quic/crypto/quic_decrypter.h"
17#include "net/quic/crypto/quic_encrypter.h"
[email protected]f702d572012-12-04 15:56:2018#include "net/quic/quic_client_session.h"
19#include "net/quic/quic_connection.h"
20#include "net/quic/quic_connection_helper.h"
21#include "net/quic/test_tools/mock_clock.h"
[email protected]9db443912013-02-25 05:27:0322#include "net/quic/test_tools/mock_random.h"
[email protected]b1f287d2012-12-22 17:25:3923#include "net/quic/test_tools/quic_connection_peer.h"
[email protected]f702d572012-12-04 15:56:2024#include "net/quic/test_tools/quic_test_utils.h"
25#include "net/quic/test_tools/test_task_runner.h"
26#include "net/socket/socket_test_util.h"
[email protected]6cca996b2013-01-25 07:43:3627#include "net/spdy/spdy_frame_builder.h"
28#include "net/spdy/spdy_framer.h"
29#include "net/spdy/spdy_http_utils.h"
30#include "net/spdy/spdy_protocol.h"
[email protected]f702d572012-12-04 15:56:2031#include "testing/gmock/include/gmock/gmock.h"
32#include "testing/gtest/include/gtest/gtest.h"
33
34using testing::_;
35
36namespace net {
[email protected]f702d572012-12-04 15:56:2037namespace test {
[email protected]f702d572012-12-04 15:56:2038namespace {
39
40const char kUploadData[] = "hello world!";
41
42class TestQuicConnection : public QuicConnection {
43 public:
44 TestQuicConnection(QuicGuid guid,
45 IPEndPoint address,
46 QuicConnectionHelper* helper)
[email protected]14e8106c2013-03-14 16:25:3347 : QuicConnection(guid, address, helper, false) {
[email protected]f702d572012-12-04 15:56:2048 }
49
[email protected]fee17f72013-02-03 07:47:4150 void SetSendAlgorithm(SendAlgorithmInterface* send_algorithm) {
51 QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
[email protected]f702d572012-12-04 15:56:2052 }
[email protected]26f3f8e2012-12-13 21:07:1953
[email protected]fee17f72013-02-03 07:47:4154 void SetReceiveAlgorithm(ReceiveAlgorithmInterface* receive_algorithm) {
55 QuicConnectionPeer::SetReceiveAlgorithm(this, receive_algorithm);
[email protected]26f3f8e2012-12-13 21:07:1956 }
57};
58
[email protected]fee17f72013-02-03 07:47:4159class TestReceiveAlgorithm : public ReceiveAlgorithmInterface {
[email protected]26f3f8e2012-12-13 21:07:1960 public:
[email protected]fee17f72013-02-03 07:47:4161 explicit TestReceiveAlgorithm(QuicCongestionFeedbackFrame* feedback)
62 : feedback_(feedback) {
[email protected]26f3f8e2012-12-13 21:07:1963 }
64
65 bool GenerateCongestionFeedback(
66 QuicCongestionFeedbackFrame* congestion_feedback) {
67 if (feedback_ == NULL) {
68 return false;
69 }
70 *congestion_feedback = *feedback_;
71 return true;
72 }
73
74 MOCK_METHOD4(RecordIncomingPacket,
[email protected]fee17f72013-02-03 07:47:4175 void(QuicByteCount, QuicPacketSequenceNumber, QuicTime, bool));
[email protected]26f3f8e2012-12-13 21:07:1976
77 private:
78 MockClock clock_;
79 QuicCongestionFeedbackFrame* feedback_;
80
[email protected]fee17f72013-02-03 07:47:4181 DISALLOW_COPY_AND_ASSIGN(TestReceiveAlgorithm);
[email protected]f702d572012-12-04 15:56:2082};
83
[email protected]63534512012-12-23 18:49:0084// Subclass of QuicHttpStream that closes itself when the first piece of data
85// is received.
86class AutoClosingStream : public QuicHttpStream {
87 public:
[email protected]9d9e7932013-02-25 18:31:0588 explicit AutoClosingStream(QuicReliableClientStream* stream)
89 : QuicHttpStream(stream) {
[email protected]63534512012-12-23 18:49:0090 }
91
[email protected]46fadfd2013-02-06 09:40:1692 virtual int OnDataReceived(const char* data, int length) OVERRIDE {
[email protected]63534512012-12-23 18:49:0093 Close(false);
94 return OK;
95 }
96};
97
[email protected]f702d572012-12-04 15:56:2098} // namespace
99
[email protected]6cca996b2013-01-25 07:43:36100class QuicHttpStreamTest : public ::testing::TestWithParam<bool> {
[email protected]f702d572012-12-04 15:56:20101 protected:
102 const static bool kFin = true;
[email protected]f702d572012-12-04 15:56:20103 // Holds a packet to be written to the wire, and the IO mode that should
104 // be used by the mock socket when performing the write.
105 struct PacketToWrite {
106 PacketToWrite(IoMode mode, QuicEncryptedPacket* packet)
107 : mode(mode),
108 packet(packet) {
109 }
110 IoMode mode;
111 QuicEncryptedPacket* packet;
112 };
113
114 QuicHttpStreamTest()
115 : net_log_(BoundNetLog()),
[email protected]63534512012-12-23 18:49:00116 use_closing_stream_(false),
[email protected]f702d572012-12-04 15:56:20117 read_buffer_(new IOBufferWithSize(4096)),
118 guid_(2),
[email protected]5351cc4b2013-03-03 07:22:41119 framer_(kQuicVersion1,
120 QuicDecrypter::Create(kNULL),
[email protected]14e8106c2013-03-14 16:25:33121 QuicEncrypter::Create(kNULL),
122 false),
123 creator_(guid_, &framer_, &random_, false) {
[email protected]f702d572012-12-04 15:56:20124 IPAddressNumber ip;
125 CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip));
126 peer_addr_ = IPEndPoint(ip, 443);
127 self_addr_ = IPEndPoint(ip, 8435);
[email protected]f702d572012-12-04 15:56:20128 }
129
130 ~QuicHttpStreamTest() {
131 for (size_t i = 0; i < writes_.size(); i++) {
132 delete writes_[i].packet;
133 }
134 }
135
136 // Adds a packet to the list of expected writes.
137 void AddWrite(IoMode mode, QuicEncryptedPacket* packet) {
138 writes_.push_back(PacketToWrite(mode, packet));
139 }
140
141 // Returns the packet to be written at position |pos|.
142 QuicEncryptedPacket* GetWrite(size_t pos) {
143 return writes_[pos].packet;
144 }
145
146 bool AtEof() {
147 return socket_data_->at_read_eof() && socket_data_->at_write_eof();
148 }
149
150 void ProcessPacket(const QuicEncryptedPacket& packet) {
151 connection_->ProcessUdpPacket(self_addr_, peer_addr_, packet);
152 }
153
154 // Configures the test fixture to use the list of expected writes.
155 void Initialize() {
156 mock_writes_.reset(new MockWrite[writes_.size()]);
157 for (size_t i = 0; i < writes_.size(); i++) {
158 mock_writes_[i] = MockWrite(writes_[i].mode,
159 writes_[i].packet->data(),
160 writes_[i].packet->length());
161 };
162
163 socket_data_.reset(new StaticSocketDataProvider(NULL, 0, mock_writes_.get(),
164 writes_.size()));
165
[email protected]e13201d82012-12-12 05:00:32166 MockUDPClientSocket* socket = new MockUDPClientSocket(socket_data_.get(),
167 net_log_.net_log());
168 socket->Connect(peer_addr_);
[email protected]f702d572012-12-04 15:56:20169 runner_ = new TestTaskRunner(&clock_);
[email protected]fee17f72013-02-03 07:47:41170 send_algorithm_ = new MockSendAlgorithm();
171 receive_algorithm_ = new TestReceiveAlgorithm(NULL);
[email protected]14e8106c2013-03-14 16:25:33172 EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _)).
[email protected]c995c572013-01-18 05:43:20173 WillRepeatedly(testing::Return(QuicTime::Delta::Zero()));
[email protected]9558c5d32012-12-22 00:08:14174 helper_ = new QuicConnectionHelper(runner_.get(), &clock_,
175 &random_generator_, socket);
[email protected]e13201d82012-12-12 05:00:32176 connection_ = new TestQuicConnection(guid_, peer_addr_, helper_);
[email protected]f702d572012-12-04 15:56:20177 connection_->set_visitor(&visitor_);
[email protected]fee17f72013-02-03 07:47:41178 connection_->SetSendAlgorithm(send_algorithm_);
179 connection_->SetReceiveAlgorithm(receive_algorithm_);
[email protected]6dcd1d5c2013-03-15 07:28:37180 session_.reset(new QuicClientSession(connection_, socket, NULL,
[email protected]0d10b592013-02-14 16:09:26181 "www.google.com", NULL));
[email protected]14e8106c2013-03-14 16:25:33182 scoped_ptr<QuicPacket> shlo(ConstructServerHelloPacket(
183 guid_, &clock_, &random_generator_, "www.google.com"));
184 scoped_ptr<QuicEncryptedPacket> shlo_packet(
185 framer_.EncryptPacket(1, *shlo));
[email protected]ed3fc15d2013-03-08 18:37:44186 session_->GetCryptoStream()->CryptoConnect();
[email protected]14e8106c2013-03-14 16:25:33187 ProcessPacket(*shlo_packet);
[email protected]f702d572012-12-04 15:56:20188 EXPECT_TRUE(session_->IsCryptoHandshakeComplete());
[email protected]63534512012-12-23 18:49:00189 QuicReliableClientStream* stream =
190 session_->CreateOutgoingReliableStream();
[email protected]6cca996b2013-01-25 07:43:36191 stream_.reset(use_closing_stream_ ?
[email protected]9d9e7932013-02-25 18:31:05192 new AutoClosingStream(stream) :
193 new QuicHttpStream(stream));
[email protected]6cca996b2013-01-25 07:43:36194 }
195
196 void SetRequestString(const std::string& method, const std::string& path) {
[email protected]9d9e7932013-02-25 18:31:05197 SpdyHeaderBlock headers;
198 headers[":method"] = method;
199 headers[":host"] = "www.google.com";
200 headers[":path"] = path;
201 headers[":scheme"] = "http";
202 headers[":version"] = "HTTP/1.1";
203 request_data_ = SerializeHeaderBlock(headers);
[email protected]6cca996b2013-01-25 07:43:36204 }
205
206 void SetResponseString(const std::string& status, const std::string& body) {
[email protected]9d9e7932013-02-25 18:31:05207 SpdyHeaderBlock headers;
208 headers[":status"] = status;
209 headers[":version"] = "HTTP/1.1";
210 headers["content-type"] = "text/plain";
211 response_data_ = SerializeHeaderBlock(headers) + body;
[email protected]6cca996b2013-01-25 07:43:36212 }
213
214 std::string SerializeHeaderBlock(const SpdyHeaderBlock& headers) {
215 size_t len = SpdyFramer::GetSerializedLength(3, &headers);
216 SpdyFrameBuilder builder(len);
217 SpdyFramer::WriteHeaderBlock(&builder, 3, &headers);
218 scoped_ptr<SpdyFrame> frame(builder.take());
219 return std::string(frame->data(), len);
220 }
[email protected]f702d572012-12-04 15:56:20221
[email protected]ed3fc15d2013-03-08 18:37:44222 QuicEncryptedPacket* ConstructChloPacket() {
223 scoped_ptr<QuicPacket> chlo(
224 ConstructClientHelloPacket(guid_, &clock_, &random_generator_,
[email protected]14e8106c2013-03-14 16:25:33225 "www.google.com", true));
[email protected]ed3fc15d2013-03-08 18:37:44226 return framer_.EncryptPacket(1, *chlo);
227 }
228
[email protected]f702d572012-12-04 15:56:20229 // Returns a newly created packet to send kData on stream 1.
230 QuicEncryptedPacket* ConstructDataPacket(
231 QuicPacketSequenceNumber sequence_number,
232 bool fin,
233 QuicStreamOffset offset,
234 base::StringPiece data) {
235 InitializeHeader(sequence_number);
236 QuicStreamFrame frame(3, fin, offset, data);
237 return ConstructPacket(header_, QuicFrame(&frame));
238 }
239
240 // Returns a newly created packet to send ack data.
241 QuicEncryptedPacket* ConstructAckPacket(
242 QuicPacketSequenceNumber sequence_number,
[email protected]63534512012-12-23 18:49:00243 QuicPacketSequenceNumber largest_received,
244 QuicPacketSequenceNumber least_unacked) {
[email protected]f702d572012-12-04 15:56:20245 InitializeHeader(sequence_number);
246
[email protected]14e8106c2013-03-14 16:25:33247 QuicAckFrame ack(largest_received, QuicTime::Zero(), least_unacked);
[email protected]9db443912013-02-25 05:27:03248 ack.sent_info.entropy_hash = 0;
249 ack.received_info.entropy_hash = 0;
250
[email protected]f702d572012-12-04 15:56:20251 return ConstructPacket(header_, QuicFrame(&ack));
252 }
253
[email protected]63534512012-12-23 18:49:00254 // Returns a newly created packet to send ack data.
255 QuicEncryptedPacket* ConstructRstPacket(
256 QuicPacketSequenceNumber sequence_number,
[email protected]9db443912013-02-25 05:27:03257 QuicStreamId stream_id) {
[email protected]63534512012-12-23 18:49:00258 InitializeHeader(sequence_number);
259
[email protected]9db443912013-02-25 05:27:03260 QuicRstStreamFrame rst(stream_id, QUIC_NO_ERROR);
[email protected]63534512012-12-23 18:49:00261 return ConstructPacket(header_, QuicFrame(&rst));
262 }
263
[email protected]f702d572012-12-04 15:56:20264 BoundNetLog net_log_;
[email protected]63534512012-12-23 18:49:00265 bool use_closing_stream_;
[email protected]fee17f72013-02-03 07:47:41266 MockSendAlgorithm* send_algorithm_;
267 TestReceiveAlgorithm* receive_algorithm_;
[email protected]f702d572012-12-04 15:56:20268 scoped_refptr<TestTaskRunner> runner_;
269 scoped_array<MockWrite> mock_writes_;
270 MockClock clock_;
[email protected]9558c5d32012-12-22 00:08:14271 MockRandom random_generator_;
[email protected]f702d572012-12-04 15:56:20272 TestQuicConnection* connection_;
[email protected]e13201d82012-12-12 05:00:32273 QuicConnectionHelper* helper_;
[email protected]f702d572012-12-04 15:56:20274 testing::StrictMock<MockConnectionVisitor> visitor_;
275 scoped_ptr<QuicHttpStream> stream_;
276 scoped_ptr<QuicClientSession> session_;
277 TestCompletionCallback callback_;
278 HttpRequestInfo request_;
279 HttpRequestHeaders headers_;
280 HttpResponseInfo response_;
281 scoped_refptr<IOBufferWithSize> read_buffer_;
[email protected]6cca996b2013-01-25 07:43:36282 std::string request_data_;
283 std::string response_data_;
[email protected]f702d572012-12-04 15:56:20284
285 private:
286 void InitializeHeader(QuicPacketSequenceNumber sequence_number) {
[email protected]c995c572013-01-18 05:43:20287 header_.public_header.guid = guid_;
[email protected]9db443912013-02-25 05:27:03288 header_.public_header.reset_flag = false;
289 header_.public_header.version_flag = false;
[email protected]f702d572012-12-04 15:56:20290 header_.packet_sequence_number = sequence_number;
[email protected]f702d572012-12-04 15:56:20291 header_.fec_group = 0;
[email protected]9db443912013-02-25 05:27:03292 header_.fec_entropy_flag = false;
293 header_.entropy_flag = false;
294 header_.fec_flag = false;
[email protected]f702d572012-12-04 15:56:20295 }
296
297 QuicEncryptedPacket* ConstructPacket(const QuicPacketHeader& header,
298 const QuicFrame& frame) {
299 QuicFrames frames;
300 frames.push_back(frame);
[email protected]610a7e942012-12-18 00:21:39301 scoped_ptr<QuicPacket> packet(
[email protected]9db443912013-02-25 05:27:03302 framer_.ConstructFrameDataPacket(header_, frames).packet);
303 return framer_.EncryptPacket(header.packet_sequence_number, *packet);
[email protected]f702d572012-12-04 15:56:20304 }
305
306 const QuicGuid guid_;
307 QuicFramer framer_;
308 IPEndPoint self_addr_;
309 IPEndPoint peer_addr_;
[email protected]9db443912013-02-25 05:27:03310 MockRandom random_;
[email protected]f702d572012-12-04 15:56:20311 QuicPacketCreator creator_;
312 QuicPacketHeader header_;
[email protected]f702d572012-12-04 15:56:20313 scoped_ptr<StaticSocketDataProvider> socket_data_;
314 std::vector<PacketToWrite> writes_;
315};
316
[email protected]9d9e7932013-02-25 18:31:05317TEST_F(QuicHttpStreamTest, RenewStreamForAuth) {
[email protected]ed3fc15d2013-03-08 18:37:44318 AddWrite(SYNCHRONOUS, ConstructChloPacket());
319 Initialize();
[email protected]f702d572012-12-04 15:56:20320 EXPECT_EQ(NULL, stream_->RenewStreamForAuth());
321}
322
[email protected]9d9e7932013-02-25 18:31:05323TEST_F(QuicHttpStreamTest, CanFindEndOfResponse) {
[email protected]ed3fc15d2013-03-08 18:37:44324 AddWrite(SYNCHRONOUS, ConstructChloPacket());
325 Initialize();
[email protected]f702d572012-12-04 15:56:20326 EXPECT_TRUE(stream_->CanFindEndOfResponse());
327}
328
[email protected]9d9e7932013-02-25 18:31:05329TEST_F(QuicHttpStreamTest, IsConnectionReusable) {
[email protected]ed3fc15d2013-03-08 18:37:44330 AddWrite(SYNCHRONOUS, ConstructChloPacket());
331 Initialize();
[email protected]f702d572012-12-04 15:56:20332 EXPECT_FALSE(stream_->IsConnectionReusable());
333}
334
[email protected]9d9e7932013-02-25 18:31:05335TEST_F(QuicHttpStreamTest, GetRequest) {
[email protected]6cca996b2013-01-25 07:43:36336 SetRequestString("GET", "/");
[email protected]ed3fc15d2013-03-08 18:37:44337 AddWrite(SYNCHRONOUS, ConstructChloPacket());
338 AddWrite(SYNCHRONOUS, ConstructDataPacket(2, kFin, 0,
[email protected]6cca996b2013-01-25 07:43:36339 request_data_));
[email protected]14e8106c2013-03-14 16:25:33340 AddWrite(SYNCHRONOUS, ConstructAckPacket(3, 2, 1));
[email protected]f702d572012-12-04 15:56:20341 Initialize();
342
343 request_.method = "GET";
344 request_.url = GURL("http://www.google.com/");
345
[email protected]262eec82013-03-19 21:01:36346 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
347 net_log_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20348 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
349 callback_.callback()));
350 EXPECT_EQ(&response_, stream_->GetResponseInfo());
351
352 // Ack the request.
[email protected]63534512012-12-23 18:49:00353 scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 1, 1));
[email protected]f702d572012-12-04 15:56:20354 ProcessPacket(*ack);
355
356 EXPECT_EQ(ERR_IO_PENDING,
357 stream_->ReadResponseHeaders(callback_.callback()));
358
359 // Send the response without a body.
[email protected]6cca996b2013-01-25 07:43:36360 SetResponseString("404 Not Found", "");
[email protected]f702d572012-12-04 15:56:20361 scoped_ptr<QuicEncryptedPacket> resp(
[email protected]6cca996b2013-01-25 07:43:36362 ConstructDataPacket(2, kFin, 0, response_data_));
[email protected]f702d572012-12-04 15:56:20363 ProcessPacket(*resp);
364
365 // Now that the headers have been processed, the callback will return.
366 EXPECT_EQ(OK, callback_.WaitForResult());
367 ASSERT_TRUE(response_.headers != NULL);
368 EXPECT_EQ(404, response_.headers->response_code());
369 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
370
371 // There is no body, so this should return immediately.
372 EXPECT_EQ(0, stream_->ReadResponseBody(read_buffer_.get(),
373 read_buffer_->size(),
374 callback_.callback()));
375 EXPECT_TRUE(stream_->IsResponseBodyComplete());
376 EXPECT_TRUE(AtEof());
377}
378
[email protected]9d9e7932013-02-25 18:31:05379TEST_F(QuicHttpStreamTest, GetRequestFullResponseInSinglePacket) {
[email protected]6cca996b2013-01-25 07:43:36380 SetRequestString("GET", "/");
[email protected]ed3fc15d2013-03-08 18:37:44381 AddWrite(SYNCHRONOUS, ConstructChloPacket());
382 AddWrite(SYNCHRONOUS, ConstructDataPacket(2, kFin, 0, request_data_));
[email protected]14e8106c2013-03-14 16:25:33383 AddWrite(SYNCHRONOUS, ConstructAckPacket(3, 2, 1));
[email protected]f702d572012-12-04 15:56:20384 Initialize();
385
386 request_.method = "GET";
387 request_.url = GURL("http://www.google.com/");
388
[email protected]262eec82013-03-19 21:01:36389 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
390 net_log_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20391 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
392 callback_.callback()));
393 EXPECT_EQ(&response_, stream_->GetResponseInfo());
394
395 // Ack the request.
[email protected]63534512012-12-23 18:49:00396 scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 1, 1));
[email protected]f702d572012-12-04 15:56:20397 ProcessPacket(*ack);
398
399 EXPECT_EQ(ERR_IO_PENDING,
400 stream_->ReadResponseHeaders(callback_.callback()));
401
402 // Send the response with a body.
[email protected]6cca996b2013-01-25 07:43:36403 SetResponseString("200 OK", "hello world!");
[email protected]f702d572012-12-04 15:56:20404 scoped_ptr<QuicEncryptedPacket> resp(
[email protected]6cca996b2013-01-25 07:43:36405 ConstructDataPacket(2, kFin, 0, response_data_));
[email protected]f702d572012-12-04 15:56:20406 ProcessPacket(*resp);
407
408 // Now that the headers have been processed, the callback will return.
409 EXPECT_EQ(OK, callback_.WaitForResult());
410 ASSERT_TRUE(response_.headers != NULL);
[email protected]6cca996b2013-01-25 07:43:36411 EXPECT_EQ(200, response_.headers->response_code());
[email protected]f702d572012-12-04 15:56:20412 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
413
414 // There is no body, so this should return immediately.
415 // Since the body has already arrived, this should return immediately.
416 EXPECT_EQ(12, stream_->ReadResponseBody(read_buffer_.get(),
417 read_buffer_->size(),
418 callback_.callback()));
419 EXPECT_TRUE(stream_->IsResponseBodyComplete());
420 EXPECT_TRUE(AtEof());
421}
422
[email protected]9d9e7932013-02-25 18:31:05423TEST_F(QuicHttpStreamTest, SendPostRequest) {
[email protected]6cca996b2013-01-25 07:43:36424 SetRequestString("POST", "/");
[email protected]ed3fc15d2013-03-08 18:37:44425 AddWrite(SYNCHRONOUS, ConstructChloPacket());
426 AddWrite(SYNCHRONOUS, ConstructDataPacket(2, !kFin, 0, request_data_));
427 AddWrite(SYNCHRONOUS, ConstructDataPacket(3, kFin, request_data_.length(),
[email protected]f702d572012-12-04 15:56:20428 kUploadData));
[email protected]14e8106c2013-03-14 16:25:33429 AddWrite(SYNCHRONOUS, ConstructAckPacket(4, 2, 1));
[email protected]f702d572012-12-04 15:56:20430
431 Initialize();
432
[email protected]b2d26cfd2012-12-11 10:36:06433 ScopedVector<UploadElementReader> element_readers;
434 element_readers.push_back(
435 new UploadBytesElementReader(kUploadData, strlen(kUploadData)));
436 UploadDataStream upload_data_stream(&element_readers, 0);
[email protected]f702d572012-12-04 15:56:20437 request_.method = "POST";
438 request_.url = GURL("http://www.google.com/");
439 request_.upload_data_stream = &upload_data_stream;
[email protected]4db27d82012-12-20 11:50:24440 ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback()));
[email protected]f702d572012-12-04 15:56:20441
[email protected]262eec82013-03-19 21:01:36442 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
443 net_log_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20444 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
445 callback_.callback()));
446 EXPECT_EQ(&response_, stream_->GetResponseInfo());
447
448 // Ack both packets in the request.
[email protected]63534512012-12-23 18:49:00449 scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 2, 1));
[email protected]f702d572012-12-04 15:56:20450 ProcessPacket(*ack);
451
452 // Send the response headers (but not the body).
[email protected]6cca996b2013-01-25 07:43:36453 SetResponseString("200 OK", "");
[email protected]f702d572012-12-04 15:56:20454 scoped_ptr<QuicEncryptedPacket> resp(
[email protected]6cca996b2013-01-25 07:43:36455 ConstructDataPacket(2, !kFin, 0, response_data_));
[email protected]f702d572012-12-04 15:56:20456 ProcessPacket(*resp);
457
458 // Since the headers have already arrived, this should return immediately.
459 EXPECT_EQ(OK, stream_->ReadResponseHeaders(callback_.callback()));
460 ASSERT_TRUE(response_.headers != NULL);
461 EXPECT_EQ(200, response_.headers->response_code());
462 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
463
464 // Send the response body.
465 const char kResponseBody[] = "Hello world!";
466 scoped_ptr<QuicEncryptedPacket> resp_body(
[email protected]6cca996b2013-01-25 07:43:36467 ConstructDataPacket(3, kFin, response_data_.length(), kResponseBody));
[email protected]f702d572012-12-04 15:56:20468 ProcessPacket(*resp_body);
469
470 // Since the body has already arrived, this should return immediately.
471 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
472 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
473 callback_.callback()));
474
475 EXPECT_TRUE(stream_->IsResponseBodyComplete());
476 EXPECT_TRUE(AtEof());
477}
478
[email protected]c9e49a02013-02-26 05:56:47479TEST_F(QuicHttpStreamTest, SendChunkedPostRequest) {
480 SetRequestString("POST", "/");
481 size_t chunk_size = strlen(kUploadData);
[email protected]ed3fc15d2013-03-08 18:37:44482 AddWrite(SYNCHRONOUS, ConstructChloPacket());
483 AddWrite(SYNCHRONOUS, ConstructDataPacket(2, !kFin, 0, request_data_));
484 AddWrite(SYNCHRONOUS, ConstructDataPacket(3, !kFin, request_data_.length(),
[email protected]c9e49a02013-02-26 05:56:47485 kUploadData));
[email protected]ed3fc15d2013-03-08 18:37:44486 AddWrite(SYNCHRONOUS, ConstructDataPacket(4, kFin,
[email protected]c9e49a02013-02-26 05:56:47487 request_data_.length() + chunk_size,
488 kUploadData));
[email protected]14e8106c2013-03-14 16:25:33489 AddWrite(SYNCHRONOUS, ConstructAckPacket(5, 2, 1));
[email protected]c9e49a02013-02-26 05:56:47490
491 Initialize();
492
493 UploadDataStream upload_data_stream(UploadDataStream::CHUNKED, 0);
494 upload_data_stream.AppendChunk(kUploadData, chunk_size, false);
495
496 request_.method = "POST";
497 request_.url = GURL("http://www.google.com/");
498 request_.upload_data_stream = &upload_data_stream;
499 ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback()));
500
[email protected]262eec82013-03-19 21:01:36501 ASSERT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
502 net_log_, callback_.callback()));
[email protected]c9e49a02013-02-26 05:56:47503 ASSERT_EQ(ERR_IO_PENDING, stream_->SendRequest(headers_, &response_,
504 callback_.callback()));
505 EXPECT_EQ(&response_, stream_->GetResponseInfo());
506
507 upload_data_stream.AppendChunk(kUploadData, chunk_size, true);
508
509 // Ack both packets in the request.
510 scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 2, 1));
511 ProcessPacket(*ack);
512
513 // Send the response headers (but not the body).
514 SetResponseString("200 OK", "");
515 scoped_ptr<QuicEncryptedPacket> resp(
516 ConstructDataPacket(2, !kFin, 0, response_data_));
517 ProcessPacket(*resp);
518
519 // Since the headers have already arrived, this should return immediately.
520 ASSERT_EQ(OK, stream_->ReadResponseHeaders(callback_.callback()));
521 ASSERT_TRUE(response_.headers != NULL);
522 EXPECT_EQ(200, response_.headers->response_code());
523 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
524
525 // Send the response body.
526 const char kResponseBody[] = "Hello world!";
527 scoped_ptr<QuicEncryptedPacket> resp_body(
528 ConstructDataPacket(3, kFin, response_data_.length(), kResponseBody));
529 ProcessPacket(*resp_body);
530
531 // Since the body has already arrived, this should return immediately.
532 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
533 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
534 callback_.callback()));
535
536 EXPECT_TRUE(stream_->IsResponseBodyComplete());
537 EXPECT_TRUE(AtEof());
538}
539
[email protected]9d9e7932013-02-25 18:31:05540TEST_F(QuicHttpStreamTest, DestroyedEarly) {
[email protected]6cca996b2013-01-25 07:43:36541 SetRequestString("GET", "/");
[email protected]ed3fc15d2013-03-08 18:37:44542 AddWrite(SYNCHRONOUS, ConstructChloPacket());
543 AddWrite(SYNCHRONOUS, ConstructDataPacket(2, kFin, 0, request_data_));
544 AddWrite(SYNCHRONOUS, ConstructRstPacket(3, 3));
[email protected]14e8106c2013-03-14 16:25:33545 AddWrite(SYNCHRONOUS, ConstructAckPacket(4, 2, 1));
[email protected]63534512012-12-23 18:49:00546 use_closing_stream_ = true;
547 Initialize();
548
549 request_.method = "GET";
550 request_.url = GURL("http://www.google.com/");
551
[email protected]262eec82013-03-19 21:01:36552 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
553 net_log_, callback_.callback()));
[email protected]63534512012-12-23 18:49:00554 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
555 callback_.callback()));
556 EXPECT_EQ(&response_, stream_->GetResponseInfo());
557
558 // Ack the request.
559 scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 1, 1));
560 ProcessPacket(*ack);
561 EXPECT_EQ(ERR_IO_PENDING,
562 stream_->ReadResponseHeaders(callback_.callback()));
563
564 // Send the response with a body.
565 const char kResponseHeaders[] = "HTTP/1.1 404 OK\r\n"
566 "Content-Type: text/plain\r\n\r\nhello world!";
567 scoped_ptr<QuicEncryptedPacket> resp(
568 ConstructDataPacket(2, kFin, 0, kResponseHeaders));
569
570 // In the course of processing this packet, the QuicHttpStream close itself.
571 ProcessPacket(*resp);
572
573 EXPECT_TRUE(AtEof());
574}
575
[email protected]f702d572012-12-04 15:56:20576} // namespace test
577
578} // namespace net