blob: 37242bf8cd0e2dcebbb4da808b99f4ae10260017 [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"
[email protected]24e5bc52013-09-18 15:36:5822#include "net/quic/quic_http_utils.h"
23#include "net/quic/quic_reliable_client_stream.h"
[email protected]3e7dca62013-09-10 16:14:2324#include "net/quic/spdy_utils.h"
[email protected]f702d572012-12-04 15:56:2025#include "net/quic/test_tools/mock_clock.h"
[email protected]e8ff26842013-03-22 21:02:0526#include "net/quic/test_tools/mock_crypto_client_stream_factory.h"
[email protected]9db443912013-02-25 05:27:0327#include "net/quic/test_tools/mock_random.h"
[email protected]b1f287d2012-12-22 17:25:3928#include "net/quic/test_tools/quic_connection_peer.h"
[email protected]f702d572012-12-04 15:56:2029#include "net/quic/test_tools/quic_test_utils.h"
30#include "net/quic/test_tools/test_task_runner.h"
31#include "net/socket/socket_test_util.h"
[email protected]6cca996b2013-01-25 07:43:3632#include "net/spdy/spdy_frame_builder.h"
33#include "net/spdy/spdy_framer.h"
34#include "net/spdy/spdy_http_utils.h"
35#include "net/spdy/spdy_protocol.h"
[email protected]24e5bc52013-09-18 15:36:5836#include "net/spdy/write_blocked_list.h"
[email protected]f702d572012-12-04 15:56:2037#include "testing/gmock/include/gmock/gmock.h"
38#include "testing/gtest/include/gtest/gtest.h"
39
40using testing::_;
[email protected]06ff5152013-08-29 01:03:0541using testing::AnyNumber;
42using testing::Return;
[email protected]f702d572012-12-04 15:56:2043
44namespace net {
[email protected]f702d572012-12-04 15:56:2045namespace test {
[email protected]f702d572012-12-04 15:56:2046namespace {
47
48const char kUploadData[] = "hello world!";
49
50class TestQuicConnection : public QuicConnection {
51 public:
52 TestQuicConnection(QuicGuid guid,
53 IPEndPoint address,
54 QuicConnectionHelper* helper)
[email protected]48878092013-07-26 14:51:5655 : QuicConnection(guid, address, helper, false, QuicVersionMax()) {
[email protected]f702d572012-12-04 15:56:2056 }
57
[email protected]fee17f72013-02-03 07:47:4158 void SetSendAlgorithm(SendAlgorithmInterface* send_algorithm) {
59 QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
[email protected]f702d572012-12-04 15:56:2060 }
[email protected]26f3f8e2012-12-13 21:07:1961
[email protected]fee17f72013-02-03 07:47:4162 void SetReceiveAlgorithm(ReceiveAlgorithmInterface* receive_algorithm) {
63 QuicConnectionPeer::SetReceiveAlgorithm(this, receive_algorithm);
[email protected]26f3f8e2012-12-13 21:07:1964 }
65};
66
[email protected]fee17f72013-02-03 07:47:4167class TestReceiveAlgorithm : public ReceiveAlgorithmInterface {
[email protected]26f3f8e2012-12-13 21:07:1968 public:
[email protected]fee17f72013-02-03 07:47:4169 explicit TestReceiveAlgorithm(QuicCongestionFeedbackFrame* feedback)
70 : feedback_(feedback) {
[email protected]26f3f8e2012-12-13 21:07:1971 }
72
73 bool GenerateCongestionFeedback(
74 QuicCongestionFeedbackFrame* congestion_feedback) {
75 if (feedback_ == NULL) {
76 return false;
77 }
78 *congestion_feedback = *feedback_;
79 return true;
80 }
81
82 MOCK_METHOD4(RecordIncomingPacket,
[email protected]fee17f72013-02-03 07:47:4183 void(QuicByteCount, QuicPacketSequenceNumber, QuicTime, bool));
[email protected]26f3f8e2012-12-13 21:07:1984
85 private:
86 MockClock clock_;
87 QuicCongestionFeedbackFrame* feedback_;
88
[email protected]fee17f72013-02-03 07:47:4189 DISALLOW_COPY_AND_ASSIGN(TestReceiveAlgorithm);
[email protected]f702d572012-12-04 15:56:2090};
91
[email protected]63534512012-12-23 18:49:0092// Subclass of QuicHttpStream that closes itself when the first piece of data
93// is received.
94class AutoClosingStream : public QuicHttpStream {
95 public:
[email protected]0b2294d32013-08-02 00:46:3696 explicit AutoClosingStream(const base::WeakPtr<QuicClientSession>& session)
97 : QuicHttpStream(session) {
[email protected]63534512012-12-23 18:49:0098 }
99
[email protected]46fadfd2013-02-06 09:40:16100 virtual int OnDataReceived(const char* data, int length) OVERRIDE {
[email protected]63534512012-12-23 18:49:00101 Close(false);
102 return OK;
103 }
104};
105
[email protected]f702d572012-12-04 15:56:20106} // namespace
107
[email protected]24e5bc52013-09-18 15:36:58108class QuicHttpStreamPeer {
109 public:
110 static QuicReliableClientStream* GetQuicReliableClientStream(
111 QuicHttpStream* stream) {
112 return stream->stream_;
113 }
114};
115
[email protected]6cca996b2013-01-25 07:43:36116class QuicHttpStreamTest : public ::testing::TestWithParam<bool> {
[email protected]f702d572012-12-04 15:56:20117 protected:
118 const static bool kFin = true;
[email protected]f702d572012-12-04 15:56:20119 // Holds a packet to be written to the wire, and the IO mode that should
120 // be used by the mock socket when performing the write.
121 struct PacketToWrite {
122 PacketToWrite(IoMode mode, QuicEncryptedPacket* packet)
123 : mode(mode),
124 packet(packet) {
125 }
126 IoMode mode;
127 QuicEncryptedPacket* packet;
128 };
129
130 QuicHttpStreamTest()
131 : net_log_(BoundNetLog()),
[email protected]63534512012-12-23 18:49:00132 use_closing_stream_(false),
[email protected]f702d572012-12-04 15:56:20133 read_buffer_(new IOBufferWithSize(4096)),
134 guid_(2),
[email protected]48878092013-07-26 14:51:56135 framer_(QuicVersionMax(), QuicTime::Zero(), false),
[email protected]14e8106c2013-03-14 16:25:33136 creator_(guid_, &framer_, &random_, false) {
[email protected]f702d572012-12-04 15:56:20137 IPAddressNumber ip;
138 CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip));
139 peer_addr_ = IPEndPoint(ip, 443);
140 self_addr_ = IPEndPoint(ip, 8435);
[email protected]d6202d012013-09-03 21:38:32141 // TODO(rch): remove this.
142 QuicConnection::g_acks_do_not_instigate_acks = true;
[email protected]f702d572012-12-04 15:56:20143 }
144
145 ~QuicHttpStreamTest() {
146 for (size_t i = 0; i < writes_.size(); i++) {
147 delete writes_[i].packet;
148 }
[email protected]d6202d012013-09-03 21:38:32149 // TODO(rch): remove this.
150 QuicConnection::g_acks_do_not_instigate_acks = false;
[email protected]f702d572012-12-04 15:56:20151 }
152
153 // Adds a packet to the list of expected writes.
154 void AddWrite(IoMode mode, QuicEncryptedPacket* packet) {
155 writes_.push_back(PacketToWrite(mode, packet));
156 }
157
158 // Returns the packet to be written at position |pos|.
159 QuicEncryptedPacket* GetWrite(size_t pos) {
160 return writes_[pos].packet;
161 }
162
163 bool AtEof() {
164 return socket_data_->at_read_eof() && socket_data_->at_write_eof();
165 }
166
167 void ProcessPacket(const QuicEncryptedPacket& packet) {
168 connection_->ProcessUdpPacket(self_addr_, peer_addr_, packet);
169 }
170
171 // Configures the test fixture to use the list of expected writes.
172 void Initialize() {
173 mock_writes_.reset(new MockWrite[writes_.size()]);
174 for (size_t i = 0; i < writes_.size(); i++) {
175 mock_writes_[i] = MockWrite(writes_[i].mode,
176 writes_[i].packet->data(),
177 writes_[i].packet->length());
178 };
179
180 socket_data_.reset(new StaticSocketDataProvider(NULL, 0, mock_writes_.get(),
181 writes_.size()));
182
[email protected]e13201d82012-12-12 05:00:32183 MockUDPClientSocket* socket = new MockUDPClientSocket(socket_data_.get(),
184 net_log_.net_log());
185 socket->Connect(peer_addr_);
[email protected]f702d572012-12-04 15:56:20186 runner_ = new TestTaskRunner(&clock_);
[email protected]fee17f72013-02-03 07:47:41187 send_algorithm_ = new MockSendAlgorithm();
188 receive_algorithm_ = new TestReceiveAlgorithm(NULL);
[email protected]06ff5152013-08-29 01:03:05189 EXPECT_CALL(*receive_algorithm_, RecordIncomingPacket(_, _, _, _)).
190 Times(AnyNumber());
[email protected]24e5bc52013-09-18 15:36:58191 EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _, _)).Times(AnyNumber());
[email protected]48878092013-07-26 14:51:56192 EXPECT_CALL(*send_algorithm_, RetransmissionDelay()).WillRepeatedly(
[email protected]06ff5152013-08-29 01:03:05193 Return(QuicTime::Delta::Zero()));
[email protected]575cce62013-08-03 02:06:43194 EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _, _)).
[email protected]06ff5152013-08-29 01:03:05195 WillRepeatedly(Return(QuicTime::Delta::Zero()));
[email protected]ea825e02013-08-21 18:12:45196 EXPECT_CALL(*send_algorithm_, SmoothedRtt()).WillRepeatedly(
[email protected]06ff5152013-08-29 01:03:05197 Return(QuicTime::Delta::Zero()));
[email protected]ea825e02013-08-21 18:12:45198 EXPECT_CALL(*send_algorithm_, BandwidthEstimate()).WillRepeatedly(
[email protected]06ff5152013-08-29 01:03:05199 Return(QuicBandwidth::Zero()));
[email protected]9558c5d32012-12-22 00:08:14200 helper_ = new QuicConnectionHelper(runner_.get(), &clock_,
201 &random_generator_, socket);
[email protected]e13201d82012-12-12 05:00:32202 connection_ = new TestQuicConnection(guid_, peer_addr_, helper_);
[email protected]f702d572012-12-04 15:56:20203 connection_->set_visitor(&visitor_);
[email protected]fee17f72013-02-03 07:47:41204 connection_->SetSendAlgorithm(send_algorithm_);
205 connection_->SetReceiveAlgorithm(receive_algorithm_);
[email protected]ef95114d2013-04-17 17:57:01206 crypto_config_.SetDefaults();
[email protected]18ccfdb2013-08-15 00:13:44207 session_.reset(
208 new QuicClientSession(connection_,
209 scoped_ptr<DatagramClientSocket>(socket), NULL,
210 &crypto_client_stream_factory_,
211 "www.google.com", DefaultQuicConfig(),
212 &crypto_config_, NULL));
[email protected]ed3fc15d2013-03-08 18:37:44213 session_->GetCryptoStream()->CryptoConnect();
[email protected]8ba81212013-05-03 13:11:48214 EXPECT_TRUE(session_->IsCryptoHandshakeConfirmed());
[email protected]6cca996b2013-01-25 07:43:36215 stream_.reset(use_closing_stream_ ?
[email protected]0b2294d32013-08-02 00:46:36216 new AutoClosingStream(session_->GetWeakPtr()) :
217 new QuicHttpStream(session_->GetWeakPtr()));
[email protected]6cca996b2013-01-25 07:43:36218 }
219
[email protected]24e5bc52013-09-18 15:36:58220 void SetRequestString(const std::string& method,
221 const std::string& path,
222 RequestPriority priority) {
[email protected]9d9e7932013-02-25 18:31:05223 SpdyHeaderBlock headers;
224 headers[":method"] = method;
225 headers[":host"] = "www.google.com";
226 headers[":path"] = path;
227 headers[":scheme"] = "http";
228 headers[":version"] = "HTTP/1.1";
[email protected]24e5bc52013-09-18 15:36:58229 request_data_ = SerializeHeaderBlock(headers, true, priority);
[email protected]6cca996b2013-01-25 07:43:36230 }
231
232 void SetResponseString(const std::string& status, const std::string& body) {
[email protected]9d9e7932013-02-25 18:31:05233 SpdyHeaderBlock headers;
234 headers[":status"] = status;
235 headers[":version"] = "HTTP/1.1";
236 headers["content-type"] = "text/plain";
[email protected]24e5bc52013-09-18 15:36:58237 response_data_ = SerializeHeaderBlock(headers, false, DEFAULT_PRIORITY) +
238 body;
[email protected]6cca996b2013-01-25 07:43:36239 }
240
[email protected]8edeb8d2013-08-28 06:11:43241 std::string SerializeHeaderBlock(const SpdyHeaderBlock& headers,
[email protected]24e5bc52013-09-18 15:36:58242 bool write_priority,
243 RequestPriority priority) {
[email protected]821555c2013-05-16 20:20:17244 QuicSpdyCompressor compressor;
[email protected]8edeb8d2013-08-28 06:11:43245 if (framer_.version() >= QUIC_VERSION_9 && write_priority) {
[email protected]24e5bc52013-09-18 15:36:58246 return compressor.CompressHeadersWithPriority(
247 ConvertRequestPriorityToQuicPriority(priority), headers);
[email protected]8edeb8d2013-08-28 06:11:43248 }
[email protected]e4e47462013-08-22 19:37:46249 return compressor.CompressHeaders(headers);
[email protected]6cca996b2013-01-25 07:43:36250 }
[email protected]f702d572012-12-04 15:56:20251
[email protected]06ff5152013-08-29 01:03:05252 // Returns a newly created packet to send kData on stream 3.
[email protected]f702d572012-12-04 15:56:20253 QuicEncryptedPacket* ConstructDataPacket(
254 QuicPacketSequenceNumber sequence_number,
[email protected]e8ff26842013-03-22 21:02:05255 bool should_include_version,
[email protected]f702d572012-12-04 15:56:20256 bool fin,
257 QuicStreamOffset offset,
258 base::StringPiece data) {
[email protected]e8ff26842013-03-22 21:02:05259 InitializeHeader(sequence_number, should_include_version);
[email protected]f702d572012-12-04 15:56:20260 QuicStreamFrame frame(3, fin, offset, data);
261 return ConstructPacket(header_, QuicFrame(&frame));
262 }
263
[email protected]06ff5152013-08-29 01:03:05264 // Returns a newly created packet to RST_STREAM stream 3.
265 QuicEncryptedPacket* ConstructRstStreamPacket(
266 QuicPacketSequenceNumber sequence_number) {
267 InitializeHeader(sequence_number, false);
[email protected]24e5bc52013-09-18 15:36:58268 QuicRstStreamFrame frame(3, QUIC_ERROR_PROCESSING_STREAM);
[email protected]06ff5152013-08-29 01:03:05269 return ConstructPacket(header_, QuicFrame(&frame));
270 }
271
[email protected]f702d572012-12-04 15:56:20272 // Returns a newly created packet to send ack data.
273 QuicEncryptedPacket* ConstructAckPacket(
274 QuicPacketSequenceNumber sequence_number,
[email protected]63534512012-12-23 18:49:00275 QuicPacketSequenceNumber largest_received,
276 QuicPacketSequenceNumber least_unacked) {
[email protected]e8ff26842013-03-22 21:02:05277 InitializeHeader(sequence_number, false);
[email protected]f702d572012-12-04 15:56:20278
[email protected]14e8106c2013-03-14 16:25:33279 QuicAckFrame ack(largest_received, QuicTime::Zero(), least_unacked);
[email protected]9db443912013-02-25 05:27:03280 ack.sent_info.entropy_hash = 0;
281 ack.received_info.entropy_hash = 0;
282
[email protected]f702d572012-12-04 15:56:20283 return ConstructPacket(header_, QuicFrame(&ack));
284 }
285
[email protected]63534512012-12-23 18:49:00286 // Returns a newly created packet to send ack data.
287 QuicEncryptedPacket* ConstructRstPacket(
288 QuicPacketSequenceNumber sequence_number,
[email protected]9db443912013-02-25 05:27:03289 QuicStreamId stream_id) {
[email protected]e8ff26842013-03-22 21:02:05290 InitializeHeader(sequence_number, false);
[email protected]63534512012-12-23 18:49:00291
[email protected]74bda142013-03-31 02:49:11292 QuicRstStreamFrame rst(stream_id, QUIC_STREAM_NO_ERROR);
[email protected]63534512012-12-23 18:49:00293 return ConstructPacket(header_, QuicFrame(&rst));
294 }
295
[email protected]f702d572012-12-04 15:56:20296 BoundNetLog net_log_;
[email protected]63534512012-12-23 18:49:00297 bool use_closing_stream_;
[email protected]fee17f72013-02-03 07:47:41298 MockSendAlgorithm* send_algorithm_;
299 TestReceiveAlgorithm* receive_algorithm_;
[email protected]f702d572012-12-04 15:56:20300 scoped_refptr<TestTaskRunner> runner_;
[email protected]4356f0f2013-04-07 00:58:17301 scoped_ptr<MockWrite[]> mock_writes_;
[email protected]f702d572012-12-04 15:56:20302 MockClock clock_;
[email protected]9558c5d32012-12-22 00:08:14303 MockRandom random_generator_;
[email protected]f702d572012-12-04 15:56:20304 TestQuicConnection* connection_;
[email protected]e13201d82012-12-12 05:00:32305 QuicConnectionHelper* helper_;
[email protected]f702d572012-12-04 15:56:20306 testing::StrictMock<MockConnectionVisitor> visitor_;
307 scoped_ptr<QuicHttpStream> stream_;
308 scoped_ptr<QuicClientSession> session_;
[email protected]ef95114d2013-04-17 17:57:01309 QuicCryptoClientConfig crypto_config_;
[email protected]f702d572012-12-04 15:56:20310 TestCompletionCallback callback_;
311 HttpRequestInfo request_;
312 HttpRequestHeaders headers_;
313 HttpResponseInfo response_;
314 scoped_refptr<IOBufferWithSize> read_buffer_;
[email protected]6cca996b2013-01-25 07:43:36315 std::string request_data_;
316 std::string response_data_;
[email protected]f702d572012-12-04 15:56:20317
318 private:
[email protected]e8ff26842013-03-22 21:02:05319 void InitializeHeader(QuicPacketSequenceNumber sequence_number,
320 bool should_include_version) {
[email protected]c995c572013-01-18 05:43:20321 header_.public_header.guid = guid_;
[email protected]9db443912013-02-25 05:27:03322 header_.public_header.reset_flag = false;
[email protected]e8ff26842013-03-22 21:02:05323 header_.public_header.version_flag = should_include_version;
[email protected]ea825e02013-08-21 18:12:45324 header_.public_header.sequence_number_length = PACKET_1BYTE_SEQUENCE_NUMBER;
[email protected]f702d572012-12-04 15:56:20325 header_.packet_sequence_number = sequence_number;
[email protected]f702d572012-12-04 15:56:20326 header_.fec_group = 0;
[email protected]9db443912013-02-25 05:27:03327 header_.entropy_flag = false;
328 header_.fec_flag = false;
[email protected]f702d572012-12-04 15:56:20329 }
330
331 QuicEncryptedPacket* ConstructPacket(const QuicPacketHeader& header,
332 const QuicFrame& frame) {
333 QuicFrames frames;
334 frames.push_back(frame);
[email protected]610a7e942012-12-18 00:21:39335 scoped_ptr<QuicPacket> packet(
[email protected]3e60db82013-08-05 19:43:06336 framer_.BuildUnsizedDataPacket(header_, frames).packet);
[email protected]8ba81212013-05-03 13:11:48337 return framer_.EncryptPacket(
338 ENCRYPTION_NONE, header.packet_sequence_number, *packet);
[email protected]f702d572012-12-04 15:56:20339 }
340
341 const QuicGuid guid_;
342 QuicFramer framer_;
343 IPEndPoint self_addr_;
344 IPEndPoint peer_addr_;
[email protected]9db443912013-02-25 05:27:03345 MockRandom random_;
[email protected]e8ff26842013-03-22 21:02:05346 MockCryptoClientStreamFactory crypto_client_stream_factory_;
[email protected]f702d572012-12-04 15:56:20347 QuicPacketCreator creator_;
348 QuicPacketHeader header_;
[email protected]f702d572012-12-04 15:56:20349 scoped_ptr<StaticSocketDataProvider> socket_data_;
350 std::vector<PacketToWrite> writes_;
351};
352
[email protected]9d9e7932013-02-25 18:31:05353TEST_F(QuicHttpStreamTest, RenewStreamForAuth) {
[email protected]ed3fc15d2013-03-08 18:37:44354 Initialize();
[email protected]f702d572012-12-04 15:56:20355 EXPECT_EQ(NULL, stream_->RenewStreamForAuth());
356}
357
[email protected]9d9e7932013-02-25 18:31:05358TEST_F(QuicHttpStreamTest, CanFindEndOfResponse) {
[email protected]ed3fc15d2013-03-08 18:37:44359 Initialize();
[email protected]f702d572012-12-04 15:56:20360 EXPECT_TRUE(stream_->CanFindEndOfResponse());
361}
362
[email protected]9d9e7932013-02-25 18:31:05363TEST_F(QuicHttpStreamTest, IsConnectionReusable) {
[email protected]ed3fc15d2013-03-08 18:37:44364 Initialize();
[email protected]f702d572012-12-04 15:56:20365 EXPECT_FALSE(stream_->IsConnectionReusable());
366}
367
[email protected]9d9e7932013-02-25 18:31:05368TEST_F(QuicHttpStreamTest, GetRequest) {
[email protected]24e5bc52013-09-18 15:36:58369 SetRequestString("GET", "/", DEFAULT_PRIORITY);
[email protected]e8ff26842013-03-22 21:02:05370 AddWrite(SYNCHRONOUS, ConstructDataPacket(1, true, kFin, 0,
[email protected]6cca996b2013-01-25 07:43:36371 request_data_));
[email protected]f702d572012-12-04 15:56:20372 Initialize();
373
374 request_.method = "GET";
375 request_.url = GURL("http://www.google.com/");
376
[email protected]262eec82013-03-19 21:01:36377 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
378 net_log_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20379 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
380 callback_.callback()));
381 EXPECT_EQ(&response_, stream_->GetResponseInfo());
382
383 // Ack the request.
[email protected]e8ff26842013-03-22 21:02:05384 scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0, 0));
[email protected]f702d572012-12-04 15:56:20385 ProcessPacket(*ack);
386
387 EXPECT_EQ(ERR_IO_PENDING,
388 stream_->ReadResponseHeaders(callback_.callback()));
389
390 // Send the response without a body.
[email protected]007b3f82013-04-09 08:46:45391 SetResponseString("404 Not Found", std::string());
[email protected]f702d572012-12-04 15:56:20392 scoped_ptr<QuicEncryptedPacket> resp(
[email protected]e8ff26842013-03-22 21:02:05393 ConstructDataPacket(2, false, kFin, 0, response_data_));
[email protected]f702d572012-12-04 15:56:20394 ProcessPacket(*resp);
395
396 // Now that the headers have been processed, the callback will return.
397 EXPECT_EQ(OK, callback_.WaitForResult());
[email protected]cadac622013-06-11 16:46:36398 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:20399 EXPECT_EQ(404, response_.headers->response_code());
400 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
401
402 // There is no body, so this should return immediately.
403 EXPECT_EQ(0, stream_->ReadResponseBody(read_buffer_.get(),
404 read_buffer_->size(),
405 callback_.callback()));
406 EXPECT_TRUE(stream_->IsResponseBodyComplete());
407 EXPECT_TRUE(AtEof());
408}
409
[email protected]3e7dca62013-09-10 16:14:23410// Regression test for http://crbug.com/288128
411TEST_F(QuicHttpStreamTest, GetRequestLargeResponse) {
[email protected]24e5bc52013-09-18 15:36:58412 SetRequestString("GET", "/", DEFAULT_PRIORITY);
[email protected]3e7dca62013-09-10 16:14:23413 AddWrite(SYNCHRONOUS, ConstructDataPacket(1, true, kFin, 0,
414 request_data_));
415 Initialize();
416
417 request_.method = "GET";
418 request_.url = GURL("http://www.google.com/");
419
420 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
421 net_log_, callback_.callback()));
422 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
423 callback_.callback()));
424 EXPECT_EQ(&response_, stream_->GetResponseInfo());
425
426 // Ack the request.
427 scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0, 0));
428 ProcessPacket(*ack);
429
430 EXPECT_EQ(ERR_IO_PENDING,
431 stream_->ReadResponseHeaders(callback_.callback()));
432
433 SpdyHeaderBlock headers;
434 headers[":status"] = "200 OK";
435 headers[":version"] = "HTTP/1.1";
436 headers["content-type"] = "text/plain";
437 headers["big6"] = std::string(10000, 'x'); // Lots of x's.
438
439 std::string response = SpdyUtils::SerializeUncompressedHeaders(headers);
440 EXPECT_LT(4096u, response.length());
441 stream_->OnDataReceived(response.data(), response.length());
442 stream_->OnClose(QUIC_NO_ERROR);
443
444 // Now that the headers have been processed, the callback will return.
445 EXPECT_EQ(OK, callback_.WaitForResult());
446 ASSERT_TRUE(response_.headers.get());
447 EXPECT_EQ(200, response_.headers->response_code());
448 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
449
450 // There is no body, so this should return immediately.
451 EXPECT_EQ(0, stream_->ReadResponseBody(read_buffer_.get(),
452 read_buffer_->size(),
453 callback_.callback()));
454 EXPECT_TRUE(stream_->IsResponseBodyComplete());
455 EXPECT_TRUE(AtEof());
456}
457
[email protected]9d9e7932013-02-25 18:31:05458TEST_F(QuicHttpStreamTest, GetRequestFullResponseInSinglePacket) {
[email protected]24e5bc52013-09-18 15:36:58459 SetRequestString("GET", "/", DEFAULT_PRIORITY);
[email protected]e8ff26842013-03-22 21:02:05460 AddWrite(SYNCHRONOUS, ConstructDataPacket(1, true, kFin, 0, request_data_));
[email protected]f702d572012-12-04 15:56:20461 Initialize();
462
463 request_.method = "GET";
464 request_.url = GURL("http://www.google.com/");
465
[email protected]262eec82013-03-19 21:01:36466 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
467 net_log_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20468 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
469 callback_.callback()));
470 EXPECT_EQ(&response_, stream_->GetResponseInfo());
471
472 // Ack the request.
[email protected]e8ff26842013-03-22 21:02:05473 scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0, 0));
[email protected]f702d572012-12-04 15:56:20474 ProcessPacket(*ack);
475
476 EXPECT_EQ(ERR_IO_PENDING,
477 stream_->ReadResponseHeaders(callback_.callback()));
478
479 // Send the response with a body.
[email protected]6cca996b2013-01-25 07:43:36480 SetResponseString("200 OK", "hello world!");
[email protected]f702d572012-12-04 15:56:20481 scoped_ptr<QuicEncryptedPacket> resp(
[email protected]e8ff26842013-03-22 21:02:05482 ConstructDataPacket(2, false, kFin, 0, response_data_));
[email protected]f702d572012-12-04 15:56:20483 ProcessPacket(*resp);
484
485 // Now that the headers have been processed, the callback will return.
486 EXPECT_EQ(OK, callback_.WaitForResult());
[email protected]cadac622013-06-11 16:46:36487 ASSERT_TRUE(response_.headers.get());
[email protected]6cca996b2013-01-25 07:43:36488 EXPECT_EQ(200, response_.headers->response_code());
[email protected]f702d572012-12-04 15:56:20489 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
490
491 // There is no body, so this should return immediately.
492 // Since the body has already arrived, this should return immediately.
493 EXPECT_EQ(12, stream_->ReadResponseBody(read_buffer_.get(),
494 read_buffer_->size(),
495 callback_.callback()));
496 EXPECT_TRUE(stream_->IsResponseBodyComplete());
497 EXPECT_TRUE(AtEof());
498}
499
[email protected]9d9e7932013-02-25 18:31:05500TEST_F(QuicHttpStreamTest, SendPostRequest) {
[email protected]24e5bc52013-09-18 15:36:58501 SetRequestString("POST", "/", DEFAULT_PRIORITY);
[email protected]e8ff26842013-03-22 21:02:05502 AddWrite(SYNCHRONOUS, ConstructDataPacket(1, true, !kFin, 0, request_data_));
503 AddWrite(SYNCHRONOUS, ConstructDataPacket(2, true, kFin,
504 request_data_.length(),
[email protected]f702d572012-12-04 15:56:20505 kUploadData));
[email protected]ec640112013-08-09 03:56:18506 AddWrite(SYNCHRONOUS, ConstructAckPacket(3, 3, 1));
[email protected]f702d572012-12-04 15:56:20507
508 Initialize();
509
[email protected]b2d26cfd2012-12-11 10:36:06510 ScopedVector<UploadElementReader> element_readers;
511 element_readers.push_back(
512 new UploadBytesElementReader(kUploadData, strlen(kUploadData)));
513 UploadDataStream upload_data_stream(&element_readers, 0);
[email protected]f702d572012-12-04 15:56:20514 request_.method = "POST";
515 request_.url = GURL("http://www.google.com/");
516 request_.upload_data_stream = &upload_data_stream;
[email protected]4db27d82012-12-20 11:50:24517 ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback()));
[email protected]f702d572012-12-04 15:56:20518
[email protected]262eec82013-03-19 21:01:36519 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
520 net_log_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20521 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
522 callback_.callback()));
523 EXPECT_EQ(&response_, stream_->GetResponseInfo());
524
525 // Ack both packets in the request.
[email protected]e8ff26842013-03-22 21:02:05526 scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0, 0));
[email protected]f702d572012-12-04 15:56:20527 ProcessPacket(*ack);
528
529 // Send the response headers (but not the body).
[email protected]007b3f82013-04-09 08:46:45530 SetResponseString("200 OK", std::string());
[email protected]f702d572012-12-04 15:56:20531 scoped_ptr<QuicEncryptedPacket> resp(
[email protected]e8ff26842013-03-22 21:02:05532 ConstructDataPacket(2, false, !kFin, 0, response_data_));
[email protected]f702d572012-12-04 15:56:20533 ProcessPacket(*resp);
534
535 // Since the headers have already arrived, this should return immediately.
536 EXPECT_EQ(OK, stream_->ReadResponseHeaders(callback_.callback()));
[email protected]cadac622013-06-11 16:46:36537 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:20538 EXPECT_EQ(200, response_.headers->response_code());
539 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
540
541 // Send the response body.
542 const char kResponseBody[] = "Hello world!";
543 scoped_ptr<QuicEncryptedPacket> resp_body(
[email protected]e8ff26842013-03-22 21:02:05544 ConstructDataPacket(3, false, kFin, response_data_.length(),
545 kResponseBody));
[email protected]f702d572012-12-04 15:56:20546 ProcessPacket(*resp_body);
547
548 // Since the body has already arrived, this should return immediately.
549 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
550 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
551 callback_.callback()));
552
553 EXPECT_TRUE(stream_->IsResponseBodyComplete());
554 EXPECT_TRUE(AtEof());
555}
556
[email protected]c9e49a02013-02-26 05:56:47557TEST_F(QuicHttpStreamTest, SendChunkedPostRequest) {
[email protected]24e5bc52013-09-18 15:36:58558 SetRequestString("POST", "/", DEFAULT_PRIORITY);
[email protected]c9e49a02013-02-26 05:56:47559 size_t chunk_size = strlen(kUploadData);
[email protected]e8ff26842013-03-22 21:02:05560 AddWrite(SYNCHRONOUS, ConstructDataPacket(1, true, !kFin, 0, request_data_));
561 AddWrite(SYNCHRONOUS, ConstructDataPacket(2, true, !kFin,
562 request_data_.length(),
[email protected]c9e49a02013-02-26 05:56:47563 kUploadData));
[email protected]e8ff26842013-03-22 21:02:05564 AddWrite(SYNCHRONOUS, ConstructDataPacket(3, true, kFin,
[email protected]c9e49a02013-02-26 05:56:47565 request_data_.length() + chunk_size,
566 kUploadData));
[email protected]ec640112013-08-09 03:56:18567 AddWrite(SYNCHRONOUS, ConstructAckPacket(4, 3, 1));
[email protected]c9e49a02013-02-26 05:56:47568
569 Initialize();
570
571 UploadDataStream upload_data_stream(UploadDataStream::CHUNKED, 0);
572 upload_data_stream.AppendChunk(kUploadData, chunk_size, false);
573
574 request_.method = "POST";
575 request_.url = GURL("http://www.google.com/");
576 request_.upload_data_stream = &upload_data_stream;
577 ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback()));
578
[email protected]262eec82013-03-19 21:01:36579 ASSERT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
580 net_log_, callback_.callback()));
[email protected]c9e49a02013-02-26 05:56:47581 ASSERT_EQ(ERR_IO_PENDING, stream_->SendRequest(headers_, &response_,
582 callback_.callback()));
583 EXPECT_EQ(&response_, stream_->GetResponseInfo());
584
585 upload_data_stream.AppendChunk(kUploadData, chunk_size, true);
586
587 // Ack both packets in the request.
[email protected]e8ff26842013-03-22 21:02:05588 scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0, 0));
[email protected]c9e49a02013-02-26 05:56:47589 ProcessPacket(*ack);
590
591 // Send the response headers (but not the body).
[email protected]007b3f82013-04-09 08:46:45592 SetResponseString("200 OK", std::string());
[email protected]c9e49a02013-02-26 05:56:47593 scoped_ptr<QuicEncryptedPacket> resp(
[email protected]e8ff26842013-03-22 21:02:05594 ConstructDataPacket(2, false, !kFin, 0, response_data_));
[email protected]c9e49a02013-02-26 05:56:47595 ProcessPacket(*resp);
596
597 // Since the headers have already arrived, this should return immediately.
598 ASSERT_EQ(OK, stream_->ReadResponseHeaders(callback_.callback()));
[email protected]cadac622013-06-11 16:46:36599 ASSERT_TRUE(response_.headers.get());
[email protected]c9e49a02013-02-26 05:56:47600 EXPECT_EQ(200, response_.headers->response_code());
601 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
602
603 // Send the response body.
604 const char kResponseBody[] = "Hello world!";
605 scoped_ptr<QuicEncryptedPacket> resp_body(
[email protected]e8ff26842013-03-22 21:02:05606 ConstructDataPacket(3, false, kFin, response_data_.length(),
607 kResponseBody));
[email protected]c9e49a02013-02-26 05:56:47608 ProcessPacket(*resp_body);
609
610 // Since the body has already arrived, this should return immediately.
611 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
612 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
613 callback_.callback()));
614
615 EXPECT_TRUE(stream_->IsResponseBodyComplete());
616 EXPECT_TRUE(AtEof());
617}
618
[email protected]9d9e7932013-02-25 18:31:05619TEST_F(QuicHttpStreamTest, DestroyedEarly) {
[email protected]24e5bc52013-09-18 15:36:58620 SetRequestString("GET", "/", DEFAULT_PRIORITY);
[email protected]e8ff26842013-03-22 21:02:05621 AddWrite(SYNCHRONOUS, ConstructDataPacket(1, true, kFin, 0, request_data_));
[email protected]06ff5152013-08-29 01:03:05622 AddWrite(SYNCHRONOUS, ConstructRstStreamPacket(2));
[email protected]63534512012-12-23 18:49:00623 use_closing_stream_ = true;
624 Initialize();
625
626 request_.method = "GET";
627 request_.url = GURL("http://www.google.com/");
628
[email protected]262eec82013-03-19 21:01:36629 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
630 net_log_, callback_.callback()));
[email protected]63534512012-12-23 18:49:00631 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
[email protected]24e5bc52013-09-18 15:36:58632 callback_.callback()));
[email protected]63534512012-12-23 18:49:00633 EXPECT_EQ(&response_, stream_->GetResponseInfo());
634
635 // Ack the request.
[email protected]e8ff26842013-03-22 21:02:05636 scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0, 0));
[email protected]63534512012-12-23 18:49:00637 ProcessPacket(*ack);
638 EXPECT_EQ(ERR_IO_PENDING,
639 stream_->ReadResponseHeaders(callback_.callback()));
640
641 // Send the response with a body.
[email protected]c244c5a12013-05-07 20:55:04642 SetResponseString("404 OK", "hello world!");
[email protected]63534512012-12-23 18:49:00643 scoped_ptr<QuicEncryptedPacket> resp(
[email protected]c244c5a12013-05-07 20:55:04644 ConstructDataPacket(2, false, kFin, 0, response_data_));
[email protected]63534512012-12-23 18:49:00645
646 // In the course of processing this packet, the QuicHttpStream close itself.
647 ProcessPacket(*resp);
648
649 EXPECT_TRUE(AtEof());
650}
651
[email protected]24e5bc52013-09-18 15:36:58652TEST_F(QuicHttpStreamTest, Priority) {
653 SetRequestString("GET", "/", MEDIUM);
654 AddWrite(SYNCHRONOUS, ConstructDataPacket(1, true, kFin, 0, request_data_));
655 AddWrite(SYNCHRONOUS, ConstructRstStreamPacket(2));
656 use_closing_stream_ = true;
657 Initialize();
658
659 request_.method = "GET";
660 request_.url = GURL("http://www.google.com/");
661
662 EXPECT_EQ(OK, stream_->InitializeStream(&request_, MEDIUM,
663 net_log_, callback_.callback()));
664
665 // Check that priority is highest.
666 QuicReliableClientStream* reliable_stream =
667 QuicHttpStreamPeer::GetQuicReliableClientStream(stream_.get());
668 DCHECK(reliable_stream);
669 DCHECK_EQ(static_cast<QuicPriority>(kHighestPriority),
670 reliable_stream->EffectivePriority());
671
672 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
673 callback_.callback()));
674 EXPECT_EQ(&response_, stream_->GetResponseInfo());
675
676 // Check that priority has now dropped back to MEDIUM.
677 DCHECK_EQ(MEDIUM, ConvertQuicPriorityToRequestPriority(
678 reliable_stream->EffectivePriority()));
679
680 // Ack the request.
681 scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0, 0));
682 ProcessPacket(*ack);
683 EXPECT_EQ(ERR_IO_PENDING,
684 stream_->ReadResponseHeaders(callback_.callback()));
685
686 // Send the response with a body.
687 SetResponseString("404 OK", "hello world!");
688 scoped_ptr<QuicEncryptedPacket> resp(
689 ConstructDataPacket(2, false, kFin, 0, response_data_));
690
691 // In the course of processing this packet, the QuicHttpStream close itself.
692 ProcessPacket(*resp);
693
694 EXPECT_TRUE(AtEof());
695}
696
[email protected]f702d572012-12-04 15:56:20697} // namespace test
698
699} // namespace net