blob: 22ed3b83637359f177e6fcbd75d1defef3330435 [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]cbd731e2013-10-24 00:20:3922#include "net/quic/quic_default_packet_writer.h"
[email protected]24e5bc52013-09-18 15:36:5823#include "net/quic/quic_http_utils.h"
24#include "net/quic/quic_reliable_client_stream.h"
[email protected]3e7dca62013-09-10 16:14:2325#include "net/quic/spdy_utils.h"
[email protected]f702d572012-12-04 15:56:2026#include "net/quic/test_tools/mock_clock.h"
[email protected]e8ff26842013-03-22 21:02:0527#include "net/quic/test_tools/mock_crypto_client_stream_factory.h"
[email protected]9db443912013-02-25 05:27:0328#include "net/quic/test_tools/mock_random.h"
[email protected]b1f287d2012-12-22 17:25:3929#include "net/quic/test_tools/quic_connection_peer.h"
[email protected]1e960032013-12-20 19:00:2030#include "net/quic/test_tools/quic_test_packet_maker.h"
[email protected]f702d572012-12-04 15:56:2031#include "net/quic/test_tools/quic_test_utils.h"
32#include "net/quic/test_tools/test_task_runner.h"
33#include "net/socket/socket_test_util.h"
[email protected]6cca996b2013-01-25 07:43:3634#include "net/spdy/spdy_frame_builder.h"
35#include "net/spdy/spdy_framer.h"
36#include "net/spdy/spdy_http_utils.h"
37#include "net/spdy/spdy_protocol.h"
[email protected]24e5bc52013-09-18 15:36:5838#include "net/spdy/write_blocked_list.h"
[email protected]f702d572012-12-04 15:56:2039#include "testing/gmock/include/gmock/gmock.h"
40#include "testing/gtest/include/gtest/gtest.h"
41
42using testing::_;
[email protected]06ff5152013-08-29 01:03:0543using testing::AnyNumber;
44using testing::Return;
[email protected]f702d572012-12-04 15:56:2045
46namespace net {
[email protected]f702d572012-12-04 15:56:2047namespace test {
[email protected]f702d572012-12-04 15:56:2048namespace {
49
50const char kUploadData[] = "hello world!";
51
52class TestQuicConnection : public QuicConnection {
53 public:
[email protected]1e960032013-12-20 19:00:2054 TestQuicConnection(const QuicVersionVector& versions,
55 QuicGuid guid,
[email protected]f702d572012-12-04 15:56:2056 IPEndPoint address,
[email protected]cbd731e2013-10-24 00:20:3957 QuicConnectionHelper* helper,
58 QuicPacketWriter* writer)
[email protected]1e960032013-12-20 19:00:2059 : QuicConnection(guid, address, helper, writer, false, versions) {
[email protected]f702d572012-12-04 15:56:2060 }
61
[email protected]fee17f72013-02-03 07:47:4162 void SetSendAlgorithm(SendAlgorithmInterface* send_algorithm) {
63 QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
[email protected]f702d572012-12-04 15:56:2064 }
[email protected]26f3f8e2012-12-13 21:07:1965
[email protected]fee17f72013-02-03 07:47:4166 void SetReceiveAlgorithm(ReceiveAlgorithmInterface* receive_algorithm) {
67 QuicConnectionPeer::SetReceiveAlgorithm(this, receive_algorithm);
[email protected]26f3f8e2012-12-13 21:07:1968 }
69};
70
[email protected]fee17f72013-02-03 07:47:4171class TestReceiveAlgorithm : public ReceiveAlgorithmInterface {
[email protected]26f3f8e2012-12-13 21:07:1972 public:
[email protected]1e960032013-12-20 19:00:2073 virtual bool GenerateCongestionFeedback(
74 QuicCongestionFeedbackFrame* /*congestion_feedback*/) {
75 return false;
[email protected]26f3f8e2012-12-13 21:07:1976 }
77
78 MOCK_METHOD4(RecordIncomingPacket,
[email protected]fee17f72013-02-03 07:47:4179 void(QuicByteCount, QuicPacketSequenceNumber, QuicTime, bool));
[email protected]f702d572012-12-04 15:56:2080};
81
[email protected]63534512012-12-23 18:49:0082// Subclass of QuicHttpStream that closes itself when the first piece of data
83// is received.
84class AutoClosingStream : public QuicHttpStream {
85 public:
[email protected]0b2294d32013-08-02 00:46:3686 explicit AutoClosingStream(const base::WeakPtr<QuicClientSession>& session)
87 : QuicHttpStream(session) {
[email protected]63534512012-12-23 18:49:0088 }
89
[email protected]46fadfd2013-02-06 09:40:1690 virtual int OnDataReceived(const char* data, int length) OVERRIDE {
[email protected]63534512012-12-23 18:49:0091 Close(false);
92 return OK;
93 }
94};
95
[email protected]f702d572012-12-04 15:56:2096} // namespace
97
[email protected]24e5bc52013-09-18 15:36:5898class QuicHttpStreamPeer {
99 public:
100 static QuicReliableClientStream* GetQuicReliableClientStream(
101 QuicHttpStream* stream) {
102 return stream->stream_;
103 }
104};
105
[email protected]1e960032013-12-20 19:00:20106class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
[email protected]f702d572012-12-04 15:56:20107 protected:
[email protected]1e960032013-12-20 19:00:20108 static const bool kFin = true;
109 static const bool kIncludeVersion = true;
110 static const bool kIncludeCongestionFeedback = true;
111
[email protected]f702d572012-12-04 15:56:20112 // Holds a packet to be written to the wire, and the IO mode that should
113 // be used by the mock socket when performing the write.
114 struct PacketToWrite {
115 PacketToWrite(IoMode mode, QuicEncryptedPacket* packet)
116 : mode(mode),
117 packet(packet) {
118 }
119 IoMode mode;
120 QuicEncryptedPacket* packet;
121 };
122
123 QuicHttpStreamTest()
124 : net_log_(BoundNetLog()),
[email protected]63534512012-12-23 18:49:00125 use_closing_stream_(false),
[email protected]f702d572012-12-04 15:56:20126 read_buffer_(new IOBufferWithSize(4096)),
127 guid_(2),
[email protected]1e960032013-12-20 19:00:20128 stream_id_(GetParam() > QUIC_VERSION_12 ? 5 : 3),
129 maker_(GetParam(), guid_),
130 random_generator_(0) {
[email protected]f702d572012-12-04 15:56:20131 IPAddressNumber ip;
132 CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip));
133 peer_addr_ = IPEndPoint(ip, 443);
134 self_addr_ = IPEndPoint(ip, 8435);
[email protected]f702d572012-12-04 15:56:20135 }
136
137 ~QuicHttpStreamTest() {
[email protected]4d283b32013-10-17 12:57:27138 session_->CloseSessionOnError(ERR_ABORTED);
[email protected]f702d572012-12-04 15:56:20139 for (size_t i = 0; i < writes_.size(); i++) {
140 delete writes_[i].packet;
141 }
142 }
143
144 // Adds a packet to the list of expected writes.
[email protected]1e960032013-12-20 19:00:20145 void AddWrite(scoped_ptr<QuicEncryptedPacket> packet) {
146 writes_.push_back(PacketToWrite(SYNCHRONOUS, packet.release()));
[email protected]f702d572012-12-04 15:56:20147 }
148
149 // Returns the packet to be written at position |pos|.
150 QuicEncryptedPacket* GetWrite(size_t pos) {
151 return writes_[pos].packet;
152 }
153
154 bool AtEof() {
155 return socket_data_->at_read_eof() && socket_data_->at_write_eof();
156 }
157
[email protected]1e960032013-12-20 19:00:20158 void ProcessPacket(scoped_ptr<QuicEncryptedPacket> packet) {
159 connection_->ProcessUdpPacket(self_addr_, peer_addr_, *packet);
[email protected]f702d572012-12-04 15:56:20160 }
161
162 // Configures the test fixture to use the list of expected writes.
163 void Initialize() {
164 mock_writes_.reset(new MockWrite[writes_.size()]);
165 for (size_t i = 0; i < writes_.size(); i++) {
166 mock_writes_[i] = MockWrite(writes_[i].mode,
167 writes_[i].packet->data(),
168 writes_[i].packet->length());
169 };
170
171 socket_data_.reset(new StaticSocketDataProvider(NULL, 0, mock_writes_.get(),
172 writes_.size()));
173
[email protected]e13201d82012-12-12 05:00:32174 MockUDPClientSocket* socket = new MockUDPClientSocket(socket_data_.get(),
175 net_log_.net_log());
176 socket->Connect(peer_addr_);
[email protected]f702d572012-12-04 15:56:20177 runner_ = new TestTaskRunner(&clock_);
[email protected]fee17f72013-02-03 07:47:41178 send_algorithm_ = new MockSendAlgorithm();
[email protected]1e960032013-12-20 19:00:20179 receive_algorithm_ = new TestReceiveAlgorithm();
[email protected]06ff5152013-08-29 01:03:05180 EXPECT_CALL(*receive_algorithm_, RecordIncomingPacket(_, _, _, _)).
181 Times(AnyNumber());
[email protected]efecff92013-09-24 07:49:23182 EXPECT_CALL(*send_algorithm_,
[email protected]c0680202013-12-18 04:52:34183 OnPacketSent(_, _, _, _, _)).WillRepeatedly(Return(true));
[email protected]48878092013-07-26 14:51:56184 EXPECT_CALL(*send_algorithm_, RetransmissionDelay()).WillRepeatedly(
[email protected]06ff5152013-08-29 01:03:05185 Return(QuicTime::Delta::Zero()));
[email protected]575cce62013-08-03 02:06:43186 EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _, _)).
[email protected]06ff5152013-08-29 01:03:05187 WillRepeatedly(Return(QuicTime::Delta::Zero()));
[email protected]ea825e02013-08-21 18:12:45188 EXPECT_CALL(*send_algorithm_, SmoothedRtt()).WillRepeatedly(
[email protected]06ff5152013-08-29 01:03:05189 Return(QuicTime::Delta::Zero()));
[email protected]ea825e02013-08-21 18:12:45190 EXPECT_CALL(*send_algorithm_, BandwidthEstimate()).WillRepeatedly(
[email protected]06ff5152013-08-29 01:03:05191 Return(QuicBandwidth::Zero()));
[email protected]62f90632013-11-01 13:07:11192 EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(AnyNumber());
[email protected]2cfc6bb82013-10-27 03:40:44193 helper_.reset(new QuicConnectionHelper(runner_.get(), &clock_,
194 &random_generator_));
[email protected]cbd731e2013-10-24 00:20:39195 writer_.reset(new QuicDefaultPacketWriter(socket));
[email protected]1e960032013-12-20 19:00:20196 connection_ = new TestQuicConnection(SupportedVersions(GetParam()), guid_,
197 peer_addr_, helper_.get(),
[email protected]cbd731e2013-10-24 00:20:39198 writer_.get());
[email protected]f702d572012-12-04 15:56:20199 connection_->set_visitor(&visitor_);
[email protected]fee17f72013-02-03 07:47:41200 connection_->SetSendAlgorithm(send_algorithm_);
201 connection_->SetReceiveAlgorithm(receive_algorithm_);
[email protected]ef95114d2013-04-17 17:57:01202 crypto_config_.SetDefaults();
[email protected]18ccfdb2013-08-15 00:13:44203 session_.reset(
204 new QuicClientSession(connection_,
[email protected]cbd731e2013-10-24 00:20:39205 scoped_ptr<DatagramClientSocket>(socket),
206 writer_.Pass(), NULL,
[email protected]18ccfdb2013-08-15 00:13:44207 &crypto_client_stream_factory_,
208 "www.google.com", DefaultQuicConfig(),
209 &crypto_config_, NULL));
[email protected]ed3fc15d2013-03-08 18:37:44210 session_->GetCryptoStream()->CryptoConnect();
[email protected]8ba81212013-05-03 13:11:48211 EXPECT_TRUE(session_->IsCryptoHandshakeConfirmed());
[email protected]6cca996b2013-01-25 07:43:36212 stream_.reset(use_closing_stream_ ?
[email protected]0b2294d32013-08-02 00:46:36213 new AutoClosingStream(session_->GetWeakPtr()) :
214 new QuicHttpStream(session_->GetWeakPtr()));
[email protected]6cca996b2013-01-25 07:43:36215 }
216
[email protected]1e960032013-12-20 19:00:20217 void SetRequest(const std::string& method,
218 const std::string& path,
219 RequestPriority priority) {
220 request_headers_ = maker_.GetRequestHeaders(method, "http", path);
221 request_data_ = GetParam() > QUIC_VERSION_12 ? "" :
222 SerializeHeaderBlock(request_headers_, true, priority);
[email protected]6cca996b2013-01-25 07:43:36223 }
224
[email protected]1e960032013-12-20 19:00:20225 void SetResponse(const std::string& status, const std::string& body) {
226 response_headers_ = maker_.GetResponseHeaders(status);
227 if (GetParam() > QUIC_VERSION_12) {
228 response_data_ = body;
229 } else {
230 response_data_ =
231 SerializeHeaderBlock(response_headers_, false, DEFAULT_PRIORITY) +
232 body;
[email protected]8edeb8d2013-08-28 06:11:43233 }
[email protected]6cca996b2013-01-25 07:43:36234 }
[email protected]f702d572012-12-04 15:56:20235
[email protected]1e960032013-12-20 19:00:20236 scoped_ptr<QuicEncryptedPacket> ConstructDataPacket(
[email protected]f702d572012-12-04 15:56:20237 QuicPacketSequenceNumber sequence_number,
[email protected]e8ff26842013-03-22 21:02:05238 bool should_include_version,
[email protected]f702d572012-12-04 15:56:20239 bool fin,
240 QuicStreamOffset offset,
241 base::StringPiece data) {
[email protected]1e960032013-12-20 19:00:20242 return maker_.MakeDataPacket(
243 sequence_number, stream_id_, should_include_version, fin, offset, data);
[email protected]f702d572012-12-04 15:56:20244 }
245
[email protected]1e960032013-12-20 19:00:20246 scoped_ptr<QuicEncryptedPacket> ConstructRequestHeadersPacket(
247 QuicPacketSequenceNumber sequence_number,
248 bool fin) {
249 return maker_.MakeRequestHeadersPacket(
250 sequence_number, stream_id_, kIncludeVersion, fin, request_headers_);
251 }
252
253 scoped_ptr<QuicEncryptedPacket> ConstructResponseHeadersPacket(
254 QuicPacketSequenceNumber sequence_number,
255 bool fin) {
256 return maker_.MakeResponseHeadersPacket(
257 sequence_number, stream_id_, !kIncludeVersion, fin, response_headers_);
258 }
259
260 scoped_ptr<QuicEncryptedPacket> ConstructRstStreamPacket(
[email protected]06ff5152013-08-29 01:03:05261 QuicPacketSequenceNumber sequence_number) {
[email protected]1e960032013-12-20 19:00:20262 return maker_.MakeRstPacket(
263 sequence_number, !kIncludeVersion, stream_id_, QUIC_STREAM_CANCELLED);
[email protected]06ff5152013-08-29 01:03:05264 }
265
[email protected]1e960032013-12-20 19:00:20266 scoped_ptr<QuicEncryptedPacket> ConstructAckPacket(
[email protected]f702d572012-12-04 15:56:20267 QuicPacketSequenceNumber sequence_number,
[email protected]63534512012-12-23 18:49:00268 QuicPacketSequenceNumber largest_received,
269 QuicPacketSequenceNumber least_unacked) {
[email protected]1e960032013-12-20 19:00:20270 return maker_.MakeAckPacket(sequence_number, largest_received,
271 least_unacked, !kIncludeCongestionFeedback);
[email protected]63534512012-12-23 18:49:00272 }
273
[email protected]f702d572012-12-04 15:56:20274 BoundNetLog net_log_;
[email protected]63534512012-12-23 18:49:00275 bool use_closing_stream_;
[email protected]fee17f72013-02-03 07:47:41276 MockSendAlgorithm* send_algorithm_;
277 TestReceiveAlgorithm* receive_algorithm_;
[email protected]f702d572012-12-04 15:56:20278 scoped_refptr<TestTaskRunner> runner_;
[email protected]4356f0f2013-04-07 00:58:17279 scoped_ptr<MockWrite[]> mock_writes_;
[email protected]f702d572012-12-04 15:56:20280 MockClock clock_;
281 TestQuicConnection* connection_;
[email protected]2cfc6bb82013-10-27 03:40:44282 scoped_ptr<QuicConnectionHelper> helper_;
[email protected]f702d572012-12-04 15:56:20283 testing::StrictMock<MockConnectionVisitor> visitor_;
284 scoped_ptr<QuicHttpStream> stream_;
[email protected]cbd731e2013-10-24 00:20:39285 scoped_ptr<QuicDefaultPacketWriter> writer_;
[email protected]f702d572012-12-04 15:56:20286 scoped_ptr<QuicClientSession> session_;
[email protected]ef95114d2013-04-17 17:57:01287 QuicCryptoClientConfig crypto_config_;
[email protected]f702d572012-12-04 15:56:20288 TestCompletionCallback callback_;
289 HttpRequestInfo request_;
290 HttpRequestHeaders headers_;
291 HttpResponseInfo response_;
292 scoped_refptr<IOBufferWithSize> read_buffer_;
[email protected]1e960032013-12-20 19:00:20293 SpdyHeaderBlock request_headers_;
294 SpdyHeaderBlock response_headers_;
[email protected]6cca996b2013-01-25 07:43:36295 std::string request_data_;
296 std::string response_data_;
[email protected]f702d572012-12-04 15:56:20297
298 private:
[email protected]1e960032013-12-20 19:00:20299 std::string SerializeHeaderBlock(const SpdyHeaderBlock& headers,
300 bool write_priority,
301 RequestPriority priority) {
302 QuicSpdyCompressor compressor;
303 if (write_priority) {
304 return compressor.CompressHeadersWithPriority(
305 ConvertRequestPriorityToQuicPriority(priority), headers);
306 }
307 return compressor.CompressHeaders(headers);
[email protected]f702d572012-12-04 15:56:20308 }
309
310 const QuicGuid guid_;
[email protected]1e960032013-12-20 19:00:20311 const QuicStreamId stream_id_;
312 QuicTestPacketMaker maker_;
[email protected]f702d572012-12-04 15:56:20313 IPEndPoint self_addr_;
314 IPEndPoint peer_addr_;
[email protected]457d6952013-12-13 09:24:58315 MockRandom random_generator_;
[email protected]e8ff26842013-03-22 21:02:05316 MockCryptoClientStreamFactory crypto_client_stream_factory_;
[email protected]f702d572012-12-04 15:56:20317 scoped_ptr<StaticSocketDataProvider> socket_data_;
318 std::vector<PacketToWrite> writes_;
319};
320
[email protected]1e960032013-12-20 19:00:20321INSTANTIATE_TEST_CASE_P(Version, QuicHttpStreamTest,
322 ::testing::ValuesIn(QuicSupportedVersions()));
323
324TEST_P(QuicHttpStreamTest, RenewStreamForAuth) {
[email protected]ed3fc15d2013-03-08 18:37:44325 Initialize();
[email protected]f702d572012-12-04 15:56:20326 EXPECT_EQ(NULL, stream_->RenewStreamForAuth());
327}
328
[email protected]1e960032013-12-20 19:00:20329TEST_P(QuicHttpStreamTest, CanFindEndOfResponse) {
[email protected]ed3fc15d2013-03-08 18:37:44330 Initialize();
[email protected]f702d572012-12-04 15:56:20331 EXPECT_TRUE(stream_->CanFindEndOfResponse());
332}
333
[email protected]1e960032013-12-20 19:00:20334TEST_P(QuicHttpStreamTest, IsConnectionReusable) {
[email protected]ed3fc15d2013-03-08 18:37:44335 Initialize();
[email protected]f702d572012-12-04 15:56:20336 EXPECT_FALSE(stream_->IsConnectionReusable());
337}
338
[email protected]1e960032013-12-20 19:00:20339TEST_P(QuicHttpStreamTest, GetRequest) {
340 SetRequest("GET", "/", DEFAULT_PRIORITY);
341 if (GetParam() > QUIC_VERSION_12) {
342 AddWrite(ConstructRequestHeadersPacket(1, kFin));
343 } else {
344 AddWrite(ConstructDataPacket(1, kIncludeVersion, kFin, 0, request_data_));
345 }
[email protected]f702d572012-12-04 15:56:20346 Initialize();
347
348 request_.method = "GET";
349 request_.url = GURL("http://www.google.com/");
350
[email protected]262eec82013-03-19 21:01:36351 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
352 net_log_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20353 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
354 callback_.callback()));
355 EXPECT_EQ(&response_, stream_->GetResponseInfo());
356
357 // Ack the request.
[email protected]1e960032013-12-20 19:00:20358 ProcessPacket(ConstructAckPacket(1, 0, 0));
[email protected]f702d572012-12-04 15:56:20359
360 EXPECT_EQ(ERR_IO_PENDING,
361 stream_->ReadResponseHeaders(callback_.callback()));
362
[email protected]1e960032013-12-20 19:00:20363 SetResponse("404 Not Found", std::string());
364 if (GetParam() > QUIC_VERSION_12) {
365 ProcessPacket(ConstructResponseHeadersPacket(2, kFin));
366 } else {
367 ProcessPacket(ConstructDataPacket(2, false, kFin, 0, response_data_));
368 }
[email protected]f702d572012-12-04 15:56:20369
370 // Now that the headers have been processed, the callback will return.
371 EXPECT_EQ(OK, callback_.WaitForResult());
[email protected]cadac622013-06-11 16:46:36372 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:20373 EXPECT_EQ(404, response_.headers->response_code());
374 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
375
376 // There is no body, so this should return immediately.
377 EXPECT_EQ(0, stream_->ReadResponseBody(read_buffer_.get(),
378 read_buffer_->size(),
379 callback_.callback()));
380 EXPECT_TRUE(stream_->IsResponseBodyComplete());
381 EXPECT_TRUE(AtEof());
382}
383
[email protected]3e7dca62013-09-10 16:14:23384// Regression test for http://crbug.com/288128
[email protected]1e960032013-12-20 19:00:20385TEST_P(QuicHttpStreamTest, GetRequestLargeResponse) {
386 SetRequest("GET", "/", DEFAULT_PRIORITY);
387 if (GetParam() > QUIC_VERSION_12) {
388 AddWrite(ConstructRequestHeadersPacket(1, kFin));
389 } else {
390 AddWrite(ConstructDataPacket(1, kIncludeVersion, kFin, 0, request_data_));
391 }
[email protected]3e7dca62013-09-10 16:14:23392 Initialize();
393
394 request_.method = "GET";
395 request_.url = GURL("http://www.google.com/");
396
397 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
398 net_log_, callback_.callback()));
399 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
400 callback_.callback()));
401 EXPECT_EQ(&response_, stream_->GetResponseInfo());
402
403 // Ack the request.
[email protected]1e960032013-12-20 19:00:20404 ProcessPacket(ConstructAckPacket(1, 0, 0));
[email protected]3e7dca62013-09-10 16:14:23405
406 EXPECT_EQ(ERR_IO_PENDING,
407 stream_->ReadResponseHeaders(callback_.callback()));
408
409 SpdyHeaderBlock headers;
410 headers[":status"] = "200 OK";
411 headers[":version"] = "HTTP/1.1";
412 headers["content-type"] = "text/plain";
413 headers["big6"] = std::string(10000, 'x'); // Lots of x's.
414
415 std::string response = SpdyUtils::SerializeUncompressedHeaders(headers);
416 EXPECT_LT(4096u, response.length());
417 stream_->OnDataReceived(response.data(), response.length());
418 stream_->OnClose(QUIC_NO_ERROR);
419
420 // Now that the headers have been processed, the callback will return.
421 EXPECT_EQ(OK, callback_.WaitForResult());
422 ASSERT_TRUE(response_.headers.get());
423 EXPECT_EQ(200, response_.headers->response_code());
424 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
425
426 // There is no body, so this should return immediately.
427 EXPECT_EQ(0, stream_->ReadResponseBody(read_buffer_.get(),
428 read_buffer_->size(),
429 callback_.callback()));
430 EXPECT_TRUE(stream_->IsResponseBodyComplete());
431 EXPECT_TRUE(AtEof());
432}
433
[email protected]1e960032013-12-20 19:00:20434TEST_P(QuicHttpStreamTest, GetRequestFullResponseInSinglePacket) {
435 SetRequest("GET", "/", DEFAULT_PRIORITY);
436 AddWrite(ConstructDataPacket(1, kIncludeVersion, kFin, 0, request_data_));
[email protected]f702d572012-12-04 15:56:20437 Initialize();
438
[email protected]1e960032013-12-20 19:00:20439 if (GetParam() > QUIC_VERSION_12) {
440 // we can't put the request and response into a single frame.
441 return;
442 }
443
[email protected]f702d572012-12-04 15:56:20444 request_.method = "GET";
445 request_.url = GURL("http://www.google.com/");
446
[email protected]262eec82013-03-19 21:01:36447 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
448 net_log_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20449 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
450 callback_.callback()));
451 EXPECT_EQ(&response_, stream_->GetResponseInfo());
452
453 // Ack the request.
[email protected]1e960032013-12-20 19:00:20454 ProcessPacket(ConstructAckPacket(1, 0, 0));
[email protected]f702d572012-12-04 15:56:20455
456 EXPECT_EQ(ERR_IO_PENDING,
457 stream_->ReadResponseHeaders(callback_.callback()));
458
459 // Send the response with a body.
[email protected]1e960032013-12-20 19:00:20460 SetResponse("200 OK", "hello world!");
461 ProcessPacket(ConstructDataPacket(2, false, kFin, 0, response_data_));
[email protected]f702d572012-12-04 15:56:20462
463 // Now that the headers have been processed, the callback will return.
464 EXPECT_EQ(OK, callback_.WaitForResult());
[email protected]cadac622013-06-11 16:46:36465 ASSERT_TRUE(response_.headers.get());
[email protected]6cca996b2013-01-25 07:43:36466 EXPECT_EQ(200, response_.headers->response_code());
[email protected]f702d572012-12-04 15:56:20467 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
468
469 // There is no body, so this should return immediately.
470 // Since the body has already arrived, this should return immediately.
471 EXPECT_EQ(12, stream_->ReadResponseBody(read_buffer_.get(),
472 read_buffer_->size(),
473 callback_.callback()));
474 EXPECT_TRUE(stream_->IsResponseBodyComplete());
475 EXPECT_TRUE(AtEof());
476}
477
[email protected]1e960032013-12-20 19:00:20478TEST_P(QuicHttpStreamTest, SendPostRequest) {
479 SetRequest("POST", "/", DEFAULT_PRIORITY);
480 if (GetParam() > QUIC_VERSION_12) {
481 AddWrite(ConstructRequestHeadersPacket(1, !kFin));
482 AddWrite(ConstructDataPacket(2, kIncludeVersion, kFin, 0, kUploadData));
483 } else {
484 AddWrite(ConstructDataPacket(1, kIncludeVersion, !kFin, 0, request_data_));
485 AddWrite(ConstructDataPacket(2, kIncludeVersion, kFin,
486 request_data_.length(), kUploadData));
487 }
488 AddWrite(ConstructAckPacket(3, 3, 1));
[email protected]f702d572012-12-04 15:56:20489
490 Initialize();
491
[email protected]b2d26cfd2012-12-11 10:36:06492 ScopedVector<UploadElementReader> element_readers;
493 element_readers.push_back(
494 new UploadBytesElementReader(kUploadData, strlen(kUploadData)));
[email protected]96c77a72013-09-24 09:49:20495 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
[email protected]f702d572012-12-04 15:56:20496 request_.method = "POST";
497 request_.url = GURL("http://www.google.com/");
498 request_.upload_data_stream = &upload_data_stream;
[email protected]4db27d82012-12-20 11:50:24499 ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback()));
[email protected]f702d572012-12-04 15:56:20500
[email protected]262eec82013-03-19 21:01:36501 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
502 net_log_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20503 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
504 callback_.callback()));
505 EXPECT_EQ(&response_, stream_->GetResponseInfo());
506
507 // Ack both packets in the request.
[email protected]1e960032013-12-20 19:00:20508 ProcessPacket(ConstructAckPacket(1, 0, 0));
[email protected]f702d572012-12-04 15:56:20509
510 // Send the response headers (but not the body).
[email protected]1e960032013-12-20 19:00:20511 SetResponse("200 OK", std::string());
512 if (GetParam() > QUIC_VERSION_12) {
513 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin));
514 } else {
515 ProcessPacket(ConstructDataPacket(2, false, !kFin, 0, response_data_));
516 }
[email protected]f702d572012-12-04 15:56:20517
518 // Since the headers have already arrived, this should return immediately.
519 EXPECT_EQ(OK, stream_->ReadResponseHeaders(callback_.callback()));
[email protected]cadac622013-06-11 16:46:36520 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:20521 EXPECT_EQ(200, response_.headers->response_code());
522 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
523
524 // Send the response body.
525 const char kResponseBody[] = "Hello world!";
[email protected]1e960032013-12-20 19:00:20526 if (GetParam() > QUIC_VERSION_12) {
527 ProcessPacket(ConstructDataPacket(3, false, kFin, 0, kResponseBody));
528 } else {
529 ProcessPacket(ConstructDataPacket(3, false, kFin, response_data_.length(),
530 kResponseBody));
531 }
[email protected]f702d572012-12-04 15:56:20532 // Since the body has already arrived, this should return immediately.
533 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
534 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
535 callback_.callback()));
536
537 EXPECT_TRUE(stream_->IsResponseBodyComplete());
538 EXPECT_TRUE(AtEof());
539}
540
[email protected]1e960032013-12-20 19:00:20541TEST_P(QuicHttpStreamTest, SendChunkedPostRequest) {
542 SetRequest("POST", "/", DEFAULT_PRIORITY);
[email protected]c9e49a02013-02-26 05:56:47543 size_t chunk_size = strlen(kUploadData);
[email protected]1e960032013-12-20 19:00:20544 if (GetParam() > QUIC_VERSION_12) {
545 AddWrite(ConstructRequestHeadersPacket(1, !kFin));
546 AddWrite(ConstructDataPacket(2, kIncludeVersion, !kFin, 0, kUploadData));
547 AddWrite(ConstructDataPacket(3, kIncludeVersion, kFin, chunk_size,
548 kUploadData));
549 } else {
550 AddWrite(ConstructDataPacket(1, kIncludeVersion, !kFin, 0, request_data_));
551 AddWrite(ConstructDataPacket(2, kIncludeVersion, !kFin,
552 request_data_.length(), kUploadData));
553 AddWrite(ConstructDataPacket(3, kIncludeVersion, kFin,
554 request_data_.length() + chunk_size,
555 kUploadData));
556 }
557 AddWrite(ConstructAckPacket(4, 3, 1));
[email protected]c9e49a02013-02-26 05:56:47558 Initialize();
559
560 UploadDataStream upload_data_stream(UploadDataStream::CHUNKED, 0);
561 upload_data_stream.AppendChunk(kUploadData, chunk_size, false);
562
563 request_.method = "POST";
564 request_.url = GURL("http://www.google.com/");
565 request_.upload_data_stream = &upload_data_stream;
566 ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback()));
567
[email protected]262eec82013-03-19 21:01:36568 ASSERT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
569 net_log_, callback_.callback()));
[email protected]c9e49a02013-02-26 05:56:47570 ASSERT_EQ(ERR_IO_PENDING, stream_->SendRequest(headers_, &response_,
571 callback_.callback()));
572 EXPECT_EQ(&response_, stream_->GetResponseInfo());
573
574 upload_data_stream.AppendChunk(kUploadData, chunk_size, true);
575
576 // Ack both packets in the request.
[email protected]1e960032013-12-20 19:00:20577 ProcessPacket(ConstructAckPacket(1, 0, 0));
[email protected]c9e49a02013-02-26 05:56:47578
579 // Send the response headers (but not the body).
[email protected]1e960032013-12-20 19:00:20580 SetResponse("200 OK", std::string());
581 if (GetParam() > QUIC_VERSION_12) {
582 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin));
583 } else {
584 ProcessPacket(ConstructDataPacket(2, false, !kFin, 0, response_data_));
585 }
[email protected]c9e49a02013-02-26 05:56:47586
587 // Since the headers have already arrived, this should return immediately.
588 ASSERT_EQ(OK, stream_->ReadResponseHeaders(callback_.callback()));
[email protected]cadac622013-06-11 16:46:36589 ASSERT_TRUE(response_.headers.get());
[email protected]c9e49a02013-02-26 05:56:47590 EXPECT_EQ(200, response_.headers->response_code());
591 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
592
593 // Send the response body.
594 const char kResponseBody[] = "Hello world!";
[email protected]1e960032013-12-20 19:00:20595 ProcessPacket(ConstructDataPacket(3, false, kFin, response_data_.length(),
596 kResponseBody));
[email protected]c9e49a02013-02-26 05:56:47597
598 // Since the body has already arrived, this should return immediately.
599 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
600 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
601 callback_.callback()));
602
603 EXPECT_TRUE(stream_->IsResponseBodyComplete());
604 EXPECT_TRUE(AtEof());
605}
606
[email protected]1e960032013-12-20 19:00:20607TEST_P(QuicHttpStreamTest, DestroyedEarly) {
608 SetRequest("GET", "/", DEFAULT_PRIORITY);
609 if (GetParam() > QUIC_VERSION_12) {
610 AddWrite(ConstructRequestHeadersPacket(1, kFin));
611 } else {
612 AddWrite(ConstructDataPacket(1, kIncludeVersion, kFin, 0, request_data_));
613 }
614 AddWrite(ConstructRstStreamPacket(2));
[email protected]63534512012-12-23 18:49:00615 use_closing_stream_ = true;
616 Initialize();
617
618 request_.method = "GET";
619 request_.url = GURL("http://www.google.com/");
620
[email protected]262eec82013-03-19 21:01:36621 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
622 net_log_, callback_.callback()));
[email protected]63534512012-12-23 18:49:00623 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
[email protected]24e5bc52013-09-18 15:36:58624 callback_.callback()));
[email protected]63534512012-12-23 18:49:00625 EXPECT_EQ(&response_, stream_->GetResponseInfo());
626
627 // Ack the request.
[email protected]1e960032013-12-20 19:00:20628 ProcessPacket(ConstructAckPacket(1, 0, 0));
[email protected]63534512012-12-23 18:49:00629 EXPECT_EQ(ERR_IO_PENDING,
630 stream_->ReadResponseHeaders(callback_.callback()));
631
632 // Send the response with a body.
[email protected]1e960032013-12-20 19:00:20633 SetResponse("404 OK", "hello world!");
[email protected]63534512012-12-23 18:49:00634 // In the course of processing this packet, the QuicHttpStream close itself.
[email protected]1e960032013-12-20 19:00:20635 if (GetParam() > QUIC_VERSION_12) {
636 ProcessPacket(ConstructResponseHeadersPacket(2, kFin));
637 } else {
638 ProcessPacket(ConstructDataPacket(2, false, kFin, 0, response_data_));
639 }
[email protected]63534512012-12-23 18:49:00640
641 EXPECT_TRUE(AtEof());
642}
643
[email protected]1e960032013-12-20 19:00:20644TEST_P(QuicHttpStreamTest, Priority) {
645 SetRequest("GET", "/", MEDIUM);
646 if (GetParam() > QUIC_VERSION_12) {
647 AddWrite(ConstructRequestHeadersPacket(1, kFin));
648 } else {
649 AddWrite(ConstructDataPacket(1, kIncludeVersion, kFin, 0, request_data_));
650 }
651 AddWrite(ConstructRstStreamPacket(2));
[email protected]24e5bc52013-09-18 15:36:58652 use_closing_stream_ = true;
653 Initialize();
654
655 request_.method = "GET";
656 request_.url = GURL("http://www.google.com/");
657
658 EXPECT_EQ(OK, stream_->InitializeStream(&request_, MEDIUM,
659 net_log_, callback_.callback()));
660
661 // Check that priority is highest.
662 QuicReliableClientStream* reliable_stream =
663 QuicHttpStreamPeer::GetQuicReliableClientStream(stream_.get());
664 DCHECK(reliable_stream);
665 DCHECK_EQ(static_cast<QuicPriority>(kHighestPriority),
666 reliable_stream->EffectivePriority());
667
668 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
669 callback_.callback()));
670 EXPECT_EQ(&response_, stream_->GetResponseInfo());
671
672 // Check that priority has now dropped back to MEDIUM.
673 DCHECK_EQ(MEDIUM, ConvertQuicPriorityToRequestPriority(
674 reliable_stream->EffectivePriority()));
675
676 // Ack the request.
[email protected]1e960032013-12-20 19:00:20677 ProcessPacket(ConstructAckPacket(1, 0, 0));
[email protected]24e5bc52013-09-18 15:36:58678 EXPECT_EQ(ERR_IO_PENDING,
679 stream_->ReadResponseHeaders(callback_.callback()));
680
681 // Send the response with a body.
[email protected]1e960032013-12-20 19:00:20682 SetResponse("404 OK", "hello world!");
[email protected]24e5bc52013-09-18 15:36:58683 // In the course of processing this packet, the QuicHttpStream close itself.
[email protected]1e960032013-12-20 19:00:20684 if (GetParam() > QUIC_VERSION_12) {
685 ProcessPacket(ConstructResponseHeadersPacket(2, kFin));
686 } else {
687 ProcessPacket(ConstructDataPacket(2, !kIncludeVersion, kFin, 0,
688 response_data_));
689 }
[email protected]24e5bc52013-09-18 15:36:58690
691 EXPECT_TRUE(AtEof());
692}
693
[email protected]e1cca9a2013-09-20 17:14:44694// Regression test for http://crbug.com/294870
[email protected]1e960032013-12-20 19:00:20695TEST_P(QuicHttpStreamTest, CheckPriorityWithNoDelegate) {
696 SetRequest("GET", "/", MEDIUM);
[email protected]e1cca9a2013-09-20 17:14:44697 use_closing_stream_ = true;
698 Initialize();
699
700 request_.method = "GET";
701 request_.url = GURL("http://www.google.com/");
702
703 EXPECT_EQ(OK, stream_->InitializeStream(&request_, MEDIUM,
704 net_log_, callback_.callback()));
705
706 // Check that priority is highest.
707 QuicReliableClientStream* reliable_stream =
708 QuicHttpStreamPeer::GetQuicReliableClientStream(stream_.get());
709 DCHECK(reliable_stream);
710 QuicReliableClientStream::Delegate* delegate = reliable_stream->GetDelegate();
711 DCHECK(delegate);
712 DCHECK_EQ(static_cast<QuicPriority>(kHighestPriority),
713 reliable_stream->EffectivePriority());
714
715 // Set Delegate to NULL and make sure EffectivePriority returns highest
716 // priority.
717 reliable_stream->SetDelegate(NULL);
718 DCHECK_EQ(static_cast<QuicPriority>(kHighestPriority),
719 reliable_stream->EffectivePriority());
720 reliable_stream->SetDelegate(delegate);
721}
722
[email protected]1e960032013-12-20 19:00:20723TEST_P(QuicHttpStreamTest, DontCompressHeadersWhenNotWritable) {
724 SetRequest("GET", "/", MEDIUM);
725 AddWrite(ConstructDataPacket(1, kIncludeVersion, kFin, 0, request_data_));
[email protected]13428d42013-11-26 18:50:36726 Initialize();
[email protected]1e960032013-12-20 19:00:20727
728 if (GetParam() > QUIC_VERSION_12) {
729 // The behavior tested here is obsolete.
730 return;
731 }
[email protected]13428d42013-11-26 18:50:36732 request_.method = "GET";
733 request_.url = GURL("http://www.google.com/");
734
735 EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _, _)).
736 WillRepeatedly(Return(QuicTime::Delta::Infinite()));
737 EXPECT_EQ(OK, stream_->InitializeStream(&request_, MEDIUM,
738 net_log_, callback_.callback()));
739 EXPECT_EQ(ERR_IO_PENDING, stream_->SendRequest(headers_, &response_,
740 callback_.callback()));
741
742 // Verify that the headers have not been compressed and buffered in
743 // the stream.
744 QuicReliableClientStream* reliable_stream =
745 QuicHttpStreamPeer::GetQuicReliableClientStream(stream_.get());
746 EXPECT_FALSE(reliable_stream->HasBufferedData());
747 EXPECT_FALSE(AtEof());
748
749 EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _, _)).
750 WillRepeatedly(Return(QuicTime::Delta::Zero()));
751
752 // Data should flush out now.
753 connection_->OnCanWrite();
754 EXPECT_FALSE(reliable_stream->HasBufferedData());
755 EXPECT_TRUE(AtEof());
756}
757
[email protected]f702d572012-12-04 15:56:20758} // namespace test
[email protected]f702d572012-12-04 15:56:20759} // namespace net