blob: 26da2a15bdc07f5138a11cdba863ba7a92de1d75 [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]17bf15c2014-03-14 10:08:0419#include "net/quic/crypto/quic_server_info.h"
[email protected]f702d572012-12-04 15:56:2020#include "net/quic/quic_client_session.h"
21#include "net/quic/quic_connection.h"
22#include "net/quic/quic_connection_helper.h"
[email protected]cbd731e2013-10-24 00:20:3923#include "net/quic/quic_default_packet_writer.h"
[email protected]24e5bc52013-09-18 15:36:5824#include "net/quic/quic_http_utils.h"
25#include "net/quic/quic_reliable_client_stream.h"
[email protected]9f0dcd4e2014-01-16 15:58:1426#include "net/quic/quic_write_blocked_list.h"
[email protected]3e7dca62013-09-10 16:14:2327#include "net/quic/spdy_utils.h"
[email protected]f702d572012-12-04 15:56:2028#include "net/quic/test_tools/mock_clock.h"
[email protected]e8ff26842013-03-22 21:02:0529#include "net/quic/test_tools/mock_crypto_client_stream_factory.h"
[email protected]9db443912013-02-25 05:27:0330#include "net/quic/test_tools/mock_random.h"
[email protected]b1f287d2012-12-22 17:25:3931#include "net/quic/test_tools/quic_connection_peer.h"
[email protected]1e960032013-12-20 19:00:2032#include "net/quic/test_tools/quic_test_packet_maker.h"
[email protected]f702d572012-12-04 15:56:2033#include "net/quic/test_tools/quic_test_utils.h"
34#include "net/quic/test_tools/test_task_runner.h"
35#include "net/socket/socket_test_util.h"
[email protected]6cca996b2013-01-25 07:43:3636#include "net/spdy/spdy_frame_builder.h"
37#include "net/spdy/spdy_framer.h"
38#include "net/spdy/spdy_http_utils.h"
39#include "net/spdy/spdy_protocol.h"
[email protected]f702d572012-12-04 15:56:2040#include "testing/gmock/include/gmock/gmock.h"
41#include "testing/gtest/include/gtest/gtest.h"
42
43using testing::_;
[email protected]06ff5152013-08-29 01:03:0544using testing::AnyNumber;
45using testing::Return;
[email protected]f702d572012-12-04 15:56:2046
47namespace net {
[email protected]f702d572012-12-04 15:56:2048namespace test {
[email protected]f702d572012-12-04 15:56:2049namespace {
50
51const char kUploadData[] = "hello world!";
[email protected]e4c3ea62014-03-15 00:45:1452const char kServerHostname[] = "www.google.com";
53const uint16 kServerPort = 80;
[email protected]f702d572012-12-04 15:56:2054
55class TestQuicConnection : public QuicConnection {
56 public:
[email protected]1e960032013-12-20 19:00:2057 TestQuicConnection(const QuicVersionVector& versions,
[email protected]3aa9ca72014-02-27 19:39:4358 QuicConnectionId connection_id,
[email protected]f702d572012-12-04 15:56:2059 IPEndPoint address,
[email protected]cbd731e2013-10-24 00:20:3960 QuicConnectionHelper* helper,
61 QuicPacketWriter* writer)
[email protected]3aa9ca72014-02-27 19:39:4362 : QuicConnection(connection_id, address, helper, writer, false,
[email protected]9bb57c72014-03-31 20:36:0463 versions, kInitialFlowControlWindowForTest) {
[email protected]f702d572012-12-04 15:56:2064 }
65
[email protected]fee17f72013-02-03 07:47:4166 void SetSendAlgorithm(SendAlgorithmInterface* send_algorithm) {
67 QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
[email protected]f702d572012-12-04 15:56:2068 }
[email protected]26f3f8e2012-12-13 21:07:1969
[email protected]fee17f72013-02-03 07:47:4170 void SetReceiveAlgorithm(ReceiveAlgorithmInterface* receive_algorithm) {
71 QuicConnectionPeer::SetReceiveAlgorithm(this, receive_algorithm);
[email protected]26f3f8e2012-12-13 21:07:1972 }
73};
74
[email protected]fee17f72013-02-03 07:47:4175class TestReceiveAlgorithm : public ReceiveAlgorithmInterface {
[email protected]26f3f8e2012-12-13 21:07:1976 public:
[email protected]1e960032013-12-20 19:00:2077 virtual bool GenerateCongestionFeedback(
78 QuicCongestionFeedbackFrame* /*congestion_feedback*/) {
79 return false;
[email protected]26f3f8e2012-12-13 21:07:1980 }
81
[email protected]6ae6e342014-02-06 02:21:4282 MOCK_METHOD3(RecordIncomingPacket,
83 void(QuicByteCount, QuicPacketSequenceNumber, QuicTime));
[email protected]f702d572012-12-04 15:56:2084};
85
[email protected]63534512012-12-23 18:49:0086// Subclass of QuicHttpStream that closes itself when the first piece of data
87// is received.
88class AutoClosingStream : public QuicHttpStream {
89 public:
[email protected]0b2294d32013-08-02 00:46:3690 explicit AutoClosingStream(const base::WeakPtr<QuicClientSession>& session)
91 : QuicHttpStream(session) {
[email protected]63534512012-12-23 18:49:0092 }
93
[email protected]46fadfd2013-02-06 09:40:1694 virtual int OnDataReceived(const char* data, int length) OVERRIDE {
[email protected]63534512012-12-23 18:49:0095 Close(false);
96 return OK;
97 }
98};
99
[email protected]f702d572012-12-04 15:56:20100} // namespace
101
[email protected]24e5bc52013-09-18 15:36:58102class QuicHttpStreamPeer {
103 public:
104 static QuicReliableClientStream* GetQuicReliableClientStream(
105 QuicHttpStream* stream) {
106 return stream->stream_;
107 }
108};
109
[email protected]1e960032013-12-20 19:00:20110class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
[email protected]f702d572012-12-04 15:56:20111 protected:
[email protected]1e960032013-12-20 19:00:20112 static const bool kFin = true;
113 static const bool kIncludeVersion = true;
114 static const bool kIncludeCongestionFeedback = true;
115
[email protected]f702d572012-12-04 15:56:20116 // Holds a packet to be written to the wire, and the IO mode that should
117 // be used by the mock socket when performing the write.
118 struct PacketToWrite {
119 PacketToWrite(IoMode mode, QuicEncryptedPacket* packet)
120 : mode(mode),
121 packet(packet) {
122 }
123 IoMode mode;
124 QuicEncryptedPacket* packet;
125 };
126
127 QuicHttpStreamTest()
128 : net_log_(BoundNetLog()),
[email protected]63534512012-12-23 18:49:00129 use_closing_stream_(false),
[email protected]f702d572012-12-04 15:56:20130 read_buffer_(new IOBufferWithSize(4096)),
[email protected]3aa9ca72014-02-27 19:39:43131 connection_id_(2),
[email protected]92bf17c2014-03-03 21:14:03132 stream_id_(5),
[email protected]3aa9ca72014-02-27 19:39:43133 maker_(GetParam(), connection_id_),
[email protected]1e960032013-12-20 19:00:20134 random_generator_(0) {
[email protected]f702d572012-12-04 15:56:20135 IPAddressNumber ip;
136 CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip));
137 peer_addr_ = IPEndPoint(ip, 443);
138 self_addr_ = IPEndPoint(ip, 8435);
[email protected]f702d572012-12-04 15:56:20139 }
140
141 ~QuicHttpStreamTest() {
[email protected]4d283b32013-10-17 12:57:27142 session_->CloseSessionOnError(ERR_ABORTED);
[email protected]f702d572012-12-04 15:56:20143 for (size_t i = 0; i < writes_.size(); i++) {
144 delete writes_[i].packet;
145 }
146 }
147
148 // Adds a packet to the list of expected writes.
[email protected]1e960032013-12-20 19:00:20149 void AddWrite(scoped_ptr<QuicEncryptedPacket> packet) {
150 writes_.push_back(PacketToWrite(SYNCHRONOUS, packet.release()));
[email protected]f702d572012-12-04 15:56:20151 }
152
153 // Returns the packet to be written at position |pos|.
154 QuicEncryptedPacket* GetWrite(size_t pos) {
155 return writes_[pos].packet;
156 }
157
158 bool AtEof() {
159 return socket_data_->at_read_eof() && socket_data_->at_write_eof();
160 }
161
[email protected]1e960032013-12-20 19:00:20162 void ProcessPacket(scoped_ptr<QuicEncryptedPacket> packet) {
163 connection_->ProcessUdpPacket(self_addr_, peer_addr_, *packet);
[email protected]f702d572012-12-04 15:56:20164 }
165
166 // Configures the test fixture to use the list of expected writes.
167 void Initialize() {
168 mock_writes_.reset(new MockWrite[writes_.size()]);
169 for (size_t i = 0; i < writes_.size(); i++) {
170 mock_writes_[i] = MockWrite(writes_[i].mode,
171 writes_[i].packet->data(),
172 writes_[i].packet->length());
173 };
174
175 socket_data_.reset(new StaticSocketDataProvider(NULL, 0, mock_writes_.get(),
176 writes_.size()));
177
[email protected]e13201d82012-12-12 05:00:32178 MockUDPClientSocket* socket = new MockUDPClientSocket(socket_data_.get(),
179 net_log_.net_log());
180 socket->Connect(peer_addr_);
[email protected]f702d572012-12-04 15:56:20181 runner_ = new TestTaskRunner(&clock_);
[email protected]fee17f72013-02-03 07:47:41182 send_algorithm_ = new MockSendAlgorithm();
[email protected]1e960032013-12-20 19:00:20183 receive_algorithm_ = new TestReceiveAlgorithm();
[email protected]6ae6e342014-02-06 02:21:42184 EXPECT_CALL(*receive_algorithm_, RecordIncomingPacket(_, _, _)).
[email protected]06ff5152013-08-29 01:03:05185 Times(AnyNumber());
[email protected]efecff92013-09-24 07:49:23186 EXPECT_CALL(*send_algorithm_,
[email protected]9bb57c72014-03-31 20:36:04187 OnPacketSent(_, _, _, _)).WillRepeatedly(Return(true));
[email protected]48878092013-07-26 14:51:56188 EXPECT_CALL(*send_algorithm_, RetransmissionDelay()).WillRepeatedly(
[email protected]06ff5152013-08-29 01:03:05189 Return(QuicTime::Delta::Zero()));
[email protected]9bb57c72014-03-31 20:36:04190 EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _)).
[email protected]06ff5152013-08-29 01:03:05191 WillRepeatedly(Return(QuicTime::Delta::Zero()));
[email protected]ea825e02013-08-21 18:12:45192 EXPECT_CALL(*send_algorithm_, BandwidthEstimate()).WillRepeatedly(
[email protected]06ff5152013-08-29 01:03:05193 Return(QuicBandwidth::Zero()));
[email protected]62f90632013-11-01 13:07:11194 EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(AnyNumber());
[email protected]2cfc6bb82013-10-27 03:40:44195 helper_.reset(new QuicConnectionHelper(runner_.get(), &clock_,
196 &random_generator_));
[email protected]cbd731e2013-10-24 00:20:39197 writer_.reset(new QuicDefaultPacketWriter(socket));
[email protected]3aa9ca72014-02-27 19:39:43198 connection_ = new TestQuicConnection(SupportedVersions(GetParam()),
199 connection_id_, peer_addr_,
200 helper_.get(), writer_.get());
[email protected]f702d572012-12-04 15:56:20201 connection_->set_visitor(&visitor_);
[email protected]fee17f72013-02-03 07:47:41202 connection_->SetSendAlgorithm(send_algorithm_);
203 connection_->SetReceiveAlgorithm(receive_algorithm_);
[email protected]ef95114d2013-04-17 17:57:01204 crypto_config_.SetDefaults();
[email protected]18ccfdb2013-08-15 00:13:44205 session_.reset(
206 new QuicClientSession(connection_,
[email protected]cbd731e2013-10-24 00:20:39207 scoped_ptr<DatagramClientSocket>(socket),
208 writer_.Pass(), NULL,
[email protected]18ccfdb2013-08-15 00:13:44209 &crypto_client_stream_factory_,
[email protected]89f79a42014-03-19 11:30:01210 make_scoped_ptr((QuicServerInfo*)NULL),
[email protected]257f24f2014-04-01 09:15:37211 QuicServerId(kServerHostname, kServerPort,
212 false, PRIVACY_MODE_DISABLED),
[email protected]e4c3ea62014-03-15 00:45:14213 DefaultQuicConfig(), &crypto_config_, NULL));
[email protected]ed3fc15d2013-03-08 18:37:44214 session_->GetCryptoStream()->CryptoConnect();
[email protected]8ba81212013-05-03 13:11:48215 EXPECT_TRUE(session_->IsCryptoHandshakeConfirmed());
[email protected]6cca996b2013-01-25 07:43:36216 stream_.reset(use_closing_stream_ ?
[email protected]0b2294d32013-08-02 00:46:36217 new AutoClosingStream(session_->GetWeakPtr()) :
218 new QuicHttpStream(session_->GetWeakPtr()));
[email protected]98a9d1252014-04-04 00:43:59219 clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(20));
[email protected]6cca996b2013-01-25 07:43:36220 }
221
[email protected]1e960032013-12-20 19:00:20222 void SetRequest(const std::string& method,
223 const std::string& path,
224 RequestPriority priority) {
225 request_headers_ = maker_.GetRequestHeaders(method, "http", path);
[email protected]6cca996b2013-01-25 07:43:36226 }
227
[email protected]1e960032013-12-20 19:00:20228 void SetResponse(const std::string& status, const std::string& body) {
229 response_headers_ = maker_.GetResponseHeaders(status);
[email protected]92bf17c2014-03-03 21:14:03230 response_data_ = body;
[email protected]6cca996b2013-01-25 07:43:36231 }
[email protected]f702d572012-12-04 15:56:20232
[email protected]1e960032013-12-20 19:00:20233 scoped_ptr<QuicEncryptedPacket> ConstructDataPacket(
[email protected]f702d572012-12-04 15:56:20234 QuicPacketSequenceNumber sequence_number,
[email protected]e8ff26842013-03-22 21:02:05235 bool should_include_version,
[email protected]f702d572012-12-04 15:56:20236 bool fin,
237 QuicStreamOffset offset,
238 base::StringPiece data) {
[email protected]1e960032013-12-20 19:00:20239 return maker_.MakeDataPacket(
240 sequence_number, stream_id_, should_include_version, fin, offset, data);
[email protected]f702d572012-12-04 15:56:20241 }
242
[email protected]1e960032013-12-20 19:00:20243 scoped_ptr<QuicEncryptedPacket> ConstructRequestHeadersPacket(
244 QuicPacketSequenceNumber sequence_number,
245 bool fin) {
246 return maker_.MakeRequestHeadersPacket(
247 sequence_number, stream_id_, kIncludeVersion, fin, request_headers_);
248 }
249
250 scoped_ptr<QuicEncryptedPacket> ConstructResponseHeadersPacket(
251 QuicPacketSequenceNumber sequence_number,
252 bool fin) {
253 return maker_.MakeResponseHeadersPacket(
254 sequence_number, stream_id_, !kIncludeVersion, fin, response_headers_);
255 }
256
257 scoped_ptr<QuicEncryptedPacket> ConstructRstStreamPacket(
[email protected]06ff5152013-08-29 01:03:05258 QuicPacketSequenceNumber sequence_number) {
[email protected]1e960032013-12-20 19:00:20259 return maker_.MakeRstPacket(
[email protected]51cc1342014-04-18 23:44:37260 sequence_number, true, stream_id_,
261 AdjustErrorForVersion(QUIC_RST_FLOW_CONTROL_ACCOUNTING, GetParam()));
[email protected]06ff5152013-08-29 01:03:05262 }
263
[email protected]c5e1aca2014-01-30 04:03:04264 scoped_ptr<QuicEncryptedPacket> ConstructAckAndRstStreamPacket(
265 QuicPacketSequenceNumber sequence_number) {
266 return maker_.MakeAckAndRstPacket(
267 sequence_number, !kIncludeVersion, stream_id_, QUIC_STREAM_CANCELLED,
268 1, 1, !kIncludeCongestionFeedback);
269 }
270
[email protected]1e960032013-12-20 19:00:20271 scoped_ptr<QuicEncryptedPacket> ConstructAckPacket(
[email protected]f702d572012-12-04 15:56:20272 QuicPacketSequenceNumber sequence_number,
[email protected]63534512012-12-23 18:49:00273 QuicPacketSequenceNumber largest_received,
274 QuicPacketSequenceNumber least_unacked) {
[email protected]1e960032013-12-20 19:00:20275 return maker_.MakeAckPacket(sequence_number, largest_received,
276 least_unacked, !kIncludeCongestionFeedback);
[email protected]63534512012-12-23 18:49:00277 }
278
[email protected]f702d572012-12-04 15:56:20279 BoundNetLog net_log_;
[email protected]63534512012-12-23 18:49:00280 bool use_closing_stream_;
[email protected]fee17f72013-02-03 07:47:41281 MockSendAlgorithm* send_algorithm_;
282 TestReceiveAlgorithm* receive_algorithm_;
[email protected]f702d572012-12-04 15:56:20283 scoped_refptr<TestTaskRunner> runner_;
[email protected]4356f0f2013-04-07 00:58:17284 scoped_ptr<MockWrite[]> mock_writes_;
[email protected]f702d572012-12-04 15:56:20285 MockClock clock_;
286 TestQuicConnection* connection_;
[email protected]2cfc6bb82013-10-27 03:40:44287 scoped_ptr<QuicConnectionHelper> helper_;
[email protected]f702d572012-12-04 15:56:20288 testing::StrictMock<MockConnectionVisitor> visitor_;
289 scoped_ptr<QuicHttpStream> stream_;
[email protected]cbd731e2013-10-24 00:20:39290 scoped_ptr<QuicDefaultPacketWriter> writer_;
[email protected]f702d572012-12-04 15:56:20291 scoped_ptr<QuicClientSession> session_;
[email protected]ef95114d2013-04-17 17:57:01292 QuicCryptoClientConfig crypto_config_;
[email protected]f702d572012-12-04 15:56:20293 TestCompletionCallback callback_;
294 HttpRequestInfo request_;
295 HttpRequestHeaders headers_;
296 HttpResponseInfo response_;
297 scoped_refptr<IOBufferWithSize> read_buffer_;
[email protected]1e960032013-12-20 19:00:20298 SpdyHeaderBlock request_headers_;
299 SpdyHeaderBlock response_headers_;
[email protected]6cca996b2013-01-25 07:43:36300 std::string request_data_;
301 std::string response_data_;
[email protected]f702d572012-12-04 15:56:20302
303 private:
[email protected]3aa9ca72014-02-27 19:39:43304 const QuicConnectionId connection_id_;
[email protected]1e960032013-12-20 19:00:20305 const QuicStreamId stream_id_;
306 QuicTestPacketMaker maker_;
[email protected]f702d572012-12-04 15:56:20307 IPEndPoint self_addr_;
308 IPEndPoint peer_addr_;
[email protected]457d6952013-12-13 09:24:58309 MockRandom random_generator_;
[email protected]e8ff26842013-03-22 21:02:05310 MockCryptoClientStreamFactory crypto_client_stream_factory_;
[email protected]f702d572012-12-04 15:56:20311 scoped_ptr<StaticSocketDataProvider> socket_data_;
312 std::vector<PacketToWrite> writes_;
313};
314
[email protected]1e960032013-12-20 19:00:20315INSTANTIATE_TEST_CASE_P(Version, QuicHttpStreamTest,
316 ::testing::ValuesIn(QuicSupportedVersions()));
317
318TEST_P(QuicHttpStreamTest, RenewStreamForAuth) {
[email protected]ed3fc15d2013-03-08 18:37:44319 Initialize();
[email protected]f702d572012-12-04 15:56:20320 EXPECT_EQ(NULL, stream_->RenewStreamForAuth());
321}
322
[email protected]1e960032013-12-20 19:00:20323TEST_P(QuicHttpStreamTest, CanFindEndOfResponse) {
[email protected]ed3fc15d2013-03-08 18:37:44324 Initialize();
[email protected]f702d572012-12-04 15:56:20325 EXPECT_TRUE(stream_->CanFindEndOfResponse());
326}
327
[email protected]1e960032013-12-20 19:00:20328TEST_P(QuicHttpStreamTest, IsConnectionReusable) {
[email protected]ed3fc15d2013-03-08 18:37:44329 Initialize();
[email protected]f702d572012-12-04 15:56:20330 EXPECT_FALSE(stream_->IsConnectionReusable());
331}
332
[email protected]1e960032013-12-20 19:00:20333TEST_P(QuicHttpStreamTest, GetRequest) {
334 SetRequest("GET", "/", DEFAULT_PRIORITY);
[email protected]92bf17c2014-03-03 21:14:03335 AddWrite(ConstructRequestHeadersPacket(1, kFin));
[email protected]f702d572012-12-04 15:56:20336 Initialize();
337
338 request_.method = "GET";
339 request_.url = GURL("http://www.google.com/");
340
[email protected]262eec82013-03-19 21:01:36341 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
342 net_log_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20343 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
344 callback_.callback()));
345 EXPECT_EQ(&response_, stream_->GetResponseInfo());
346
347 // Ack the request.
[email protected]1e960032013-12-20 19:00:20348 ProcessPacket(ConstructAckPacket(1, 0, 0));
[email protected]f702d572012-12-04 15:56:20349
350 EXPECT_EQ(ERR_IO_PENDING,
351 stream_->ReadResponseHeaders(callback_.callback()));
352
[email protected]1e960032013-12-20 19:00:20353 SetResponse("404 Not Found", std::string());
[email protected]92bf17c2014-03-03 21:14:03354 ProcessPacket(ConstructResponseHeadersPacket(2, kFin));
[email protected]f702d572012-12-04 15:56:20355
356 // Now that the headers have been processed, the callback will return.
357 EXPECT_EQ(OK, callback_.WaitForResult());
[email protected]cadac622013-06-11 16:46:36358 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:20359 EXPECT_EQ(404, response_.headers->response_code());
360 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
361
362 // There is no body, so this should return immediately.
363 EXPECT_EQ(0, stream_->ReadResponseBody(read_buffer_.get(),
364 read_buffer_->size(),
365 callback_.callback()));
366 EXPECT_TRUE(stream_->IsResponseBodyComplete());
367 EXPECT_TRUE(AtEof());
368}
369
[email protected]3e7dca62013-09-10 16:14:23370// Regression test for http://crbug.com/288128
[email protected]1e960032013-12-20 19:00:20371TEST_P(QuicHttpStreamTest, GetRequestLargeResponse) {
372 SetRequest("GET", "/", DEFAULT_PRIORITY);
[email protected]92bf17c2014-03-03 21:14:03373 AddWrite(ConstructRequestHeadersPacket(1, kFin));
[email protected]3e7dca62013-09-10 16:14:23374 Initialize();
375
376 request_.method = "GET";
377 request_.url = GURL("http://www.google.com/");
378
379 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
380 net_log_, callback_.callback()));
381 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
382 callback_.callback()));
383 EXPECT_EQ(&response_, stream_->GetResponseInfo());
384
385 // Ack the request.
[email protected]1e960032013-12-20 19:00:20386 ProcessPacket(ConstructAckPacket(1, 0, 0));
[email protected]3e7dca62013-09-10 16:14:23387
388 EXPECT_EQ(ERR_IO_PENDING,
389 stream_->ReadResponseHeaders(callback_.callback()));
390
391 SpdyHeaderBlock headers;
392 headers[":status"] = "200 OK";
393 headers[":version"] = "HTTP/1.1";
394 headers["content-type"] = "text/plain";
395 headers["big6"] = std::string(10000, 'x'); // Lots of x's.
396
397 std::string response = SpdyUtils::SerializeUncompressedHeaders(headers);
398 EXPECT_LT(4096u, response.length());
399 stream_->OnDataReceived(response.data(), response.length());
400 stream_->OnClose(QUIC_NO_ERROR);
401
402 // Now that the headers have been processed, the callback will return.
403 EXPECT_EQ(OK, callback_.WaitForResult());
404 ASSERT_TRUE(response_.headers.get());
405 EXPECT_EQ(200, response_.headers->response_code());
406 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
407
408 // There is no body, so this should return immediately.
409 EXPECT_EQ(0, stream_->ReadResponseBody(read_buffer_.get(),
410 read_buffer_->size(),
411 callback_.callback()));
412 EXPECT_TRUE(stream_->IsResponseBodyComplete());
413 EXPECT_TRUE(AtEof());
414}
415
[email protected]1e960032013-12-20 19:00:20416TEST_P(QuicHttpStreamTest, SendPostRequest) {
417 SetRequest("POST", "/", DEFAULT_PRIORITY);
[email protected]92bf17c2014-03-03 21:14:03418 AddWrite(ConstructRequestHeadersPacket(1, !kFin));
419 AddWrite(ConstructDataPacket(2, kIncludeVersion, kFin, 0, kUploadData));
[email protected]1e960032013-12-20 19:00:20420 AddWrite(ConstructAckPacket(3, 3, 1));
[email protected]f702d572012-12-04 15:56:20421
422 Initialize();
423
[email protected]b2d26cfd2012-12-11 10:36:06424 ScopedVector<UploadElementReader> element_readers;
425 element_readers.push_back(
426 new UploadBytesElementReader(kUploadData, strlen(kUploadData)));
[email protected]96c77a72013-09-24 09:49:20427 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
[email protected]f702d572012-12-04 15:56:20428 request_.method = "POST";
429 request_.url = GURL("http://www.google.com/");
430 request_.upload_data_stream = &upload_data_stream;
[email protected]4db27d82012-12-20 11:50:24431 ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback()));
[email protected]f702d572012-12-04 15:56:20432
[email protected]262eec82013-03-19 21:01:36433 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
434 net_log_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20435 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
436 callback_.callback()));
437 EXPECT_EQ(&response_, stream_->GetResponseInfo());
438
439 // Ack both packets in the request.
[email protected]1e960032013-12-20 19:00:20440 ProcessPacket(ConstructAckPacket(1, 0, 0));
[email protected]f702d572012-12-04 15:56:20441
442 // Send the response headers (but not the body).
[email protected]1e960032013-12-20 19:00:20443 SetResponse("200 OK", std::string());
[email protected]92bf17c2014-03-03 21:14:03444 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin));
[email protected]f702d572012-12-04 15:56:20445
446 // Since the headers have already arrived, this should return immediately.
447 EXPECT_EQ(OK, stream_->ReadResponseHeaders(callback_.callback()));
[email protected]cadac622013-06-11 16:46:36448 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:20449 EXPECT_EQ(200, response_.headers->response_code());
450 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
451
452 // Send the response body.
453 const char kResponseBody[] = "Hello world!";
[email protected]92bf17c2014-03-03 21:14:03454 ProcessPacket(ConstructDataPacket(3, false, kFin, 0, kResponseBody));
[email protected]f702d572012-12-04 15:56:20455 // Since the body has already arrived, this should return immediately.
456 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
457 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
458 callback_.callback()));
459
460 EXPECT_TRUE(stream_->IsResponseBodyComplete());
461 EXPECT_TRUE(AtEof());
462}
463
[email protected]1e960032013-12-20 19:00:20464TEST_P(QuicHttpStreamTest, SendChunkedPostRequest) {
465 SetRequest("POST", "/", DEFAULT_PRIORITY);
[email protected]c9e49a02013-02-26 05:56:47466 size_t chunk_size = strlen(kUploadData);
[email protected]92bf17c2014-03-03 21:14:03467 AddWrite(ConstructRequestHeadersPacket(1, !kFin));
468 AddWrite(ConstructDataPacket(2, kIncludeVersion, !kFin, 0, kUploadData));
469 AddWrite(ConstructDataPacket(3, kIncludeVersion, kFin, chunk_size,
470 kUploadData));
[email protected]1e960032013-12-20 19:00:20471 AddWrite(ConstructAckPacket(4, 3, 1));
[email protected]c9e49a02013-02-26 05:56:47472 Initialize();
473
474 UploadDataStream upload_data_stream(UploadDataStream::CHUNKED, 0);
475 upload_data_stream.AppendChunk(kUploadData, chunk_size, false);
476
477 request_.method = "POST";
478 request_.url = GURL("http://www.google.com/");
479 request_.upload_data_stream = &upload_data_stream;
480 ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback()));
481
[email protected]262eec82013-03-19 21:01:36482 ASSERT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
483 net_log_, callback_.callback()));
[email protected]c9e49a02013-02-26 05:56:47484 ASSERT_EQ(ERR_IO_PENDING, stream_->SendRequest(headers_, &response_,
485 callback_.callback()));
486 EXPECT_EQ(&response_, stream_->GetResponseInfo());
487
488 upload_data_stream.AppendChunk(kUploadData, chunk_size, true);
489
490 // Ack both packets in the request.
[email protected]1e960032013-12-20 19:00:20491 ProcessPacket(ConstructAckPacket(1, 0, 0));
[email protected]c9e49a02013-02-26 05:56:47492
493 // Send the response headers (but not the body).
[email protected]1e960032013-12-20 19:00:20494 SetResponse("200 OK", std::string());
[email protected]92bf17c2014-03-03 21:14:03495 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin));
[email protected]c9e49a02013-02-26 05:56:47496
497 // Since the headers have already arrived, this should return immediately.
498 ASSERT_EQ(OK, stream_->ReadResponseHeaders(callback_.callback()));
[email protected]cadac622013-06-11 16:46:36499 ASSERT_TRUE(response_.headers.get());
[email protected]c9e49a02013-02-26 05:56:47500 EXPECT_EQ(200, response_.headers->response_code());
501 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
502
503 // Send the response body.
504 const char kResponseBody[] = "Hello world!";
[email protected]1e960032013-12-20 19:00:20505 ProcessPacket(ConstructDataPacket(3, false, kFin, response_data_.length(),
506 kResponseBody));
[email protected]c9e49a02013-02-26 05:56:47507
508 // Since the body has already arrived, this should return immediately.
509 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
510 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
511 callback_.callback()));
512
513 EXPECT_TRUE(stream_->IsResponseBodyComplete());
514 EXPECT_TRUE(AtEof());
515}
516
[email protected]1e960032013-12-20 19:00:20517TEST_P(QuicHttpStreamTest, DestroyedEarly) {
518 SetRequest("GET", "/", DEFAULT_PRIORITY);
[email protected]92bf17c2014-03-03 21:14:03519 AddWrite(ConstructRequestHeadersPacket(1, kFin));
[email protected]c5e1aca2014-01-30 04:03:04520 AddWrite(ConstructAckAndRstStreamPacket(2));
[email protected]63534512012-12-23 18:49:00521 use_closing_stream_ = true;
522 Initialize();
523
524 request_.method = "GET";
525 request_.url = GURL("http://www.google.com/");
526
[email protected]262eec82013-03-19 21:01:36527 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
528 net_log_, callback_.callback()));
[email protected]63534512012-12-23 18:49:00529 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
[email protected]24e5bc52013-09-18 15:36:58530 callback_.callback()));
[email protected]63534512012-12-23 18:49:00531 EXPECT_EQ(&response_, stream_->GetResponseInfo());
532
533 // Ack the request.
[email protected]1e960032013-12-20 19:00:20534 ProcessPacket(ConstructAckPacket(1, 0, 0));
[email protected]63534512012-12-23 18:49:00535 EXPECT_EQ(ERR_IO_PENDING,
536 stream_->ReadResponseHeaders(callback_.callback()));
537
538 // Send the response with a body.
[email protected]1e960032013-12-20 19:00:20539 SetResponse("404 OK", "hello world!");
[email protected]63534512012-12-23 18:49:00540 // In the course of processing this packet, the QuicHttpStream close itself.
[email protected]92bf17c2014-03-03 21:14:03541 ProcessPacket(ConstructResponseHeadersPacket(2, kFin));
[email protected]63534512012-12-23 18:49:00542
543 EXPECT_TRUE(AtEof());
544}
545
[email protected]1e960032013-12-20 19:00:20546TEST_P(QuicHttpStreamTest, Priority) {
547 SetRequest("GET", "/", MEDIUM);
[email protected]92bf17c2014-03-03 21:14:03548 AddWrite(ConstructRequestHeadersPacket(1, kFin));
[email protected]c5e1aca2014-01-30 04:03:04549 AddWrite(ConstructAckAndRstStreamPacket(2));
[email protected]24e5bc52013-09-18 15:36:58550 use_closing_stream_ = true;
551 Initialize();
552
553 request_.method = "GET";
554 request_.url = GURL("http://www.google.com/");
555
556 EXPECT_EQ(OK, stream_->InitializeStream(&request_, MEDIUM,
557 net_log_, callback_.callback()));
558
559 // Check that priority is highest.
560 QuicReliableClientStream* reliable_stream =
561 QuicHttpStreamPeer::GetQuicReliableClientStream(stream_.get());
562 DCHECK(reliable_stream);
[email protected]9f0dcd4e2014-01-16 15:58:14563 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority,
[email protected]24e5bc52013-09-18 15:36:58564 reliable_stream->EffectivePriority());
565
566 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
567 callback_.callback()));
568 EXPECT_EQ(&response_, stream_->GetResponseInfo());
569
570 // Check that priority has now dropped back to MEDIUM.
571 DCHECK_EQ(MEDIUM, ConvertQuicPriorityToRequestPriority(
572 reliable_stream->EffectivePriority()));
573
574 // Ack the request.
[email protected]1e960032013-12-20 19:00:20575 ProcessPacket(ConstructAckPacket(1, 0, 0));
[email protected]24e5bc52013-09-18 15:36:58576 EXPECT_EQ(ERR_IO_PENDING,
577 stream_->ReadResponseHeaders(callback_.callback()));
578
579 // Send the response with a body.
[email protected]1e960032013-12-20 19:00:20580 SetResponse("404 OK", "hello world!");
[email protected]24e5bc52013-09-18 15:36:58581 // In the course of processing this packet, the QuicHttpStream close itself.
[email protected]92bf17c2014-03-03 21:14:03582 ProcessPacket(ConstructResponseHeadersPacket(2, kFin));
[email protected]24e5bc52013-09-18 15:36:58583
584 EXPECT_TRUE(AtEof());
585}
586
[email protected]e1cca9a2013-09-20 17:14:44587// Regression test for http://crbug.com/294870
[email protected]1e960032013-12-20 19:00:20588TEST_P(QuicHttpStreamTest, CheckPriorityWithNoDelegate) {
589 SetRequest("GET", "/", MEDIUM);
[email protected]e1cca9a2013-09-20 17:14:44590 use_closing_stream_ = true;
[email protected]459a7402014-02-10 12:58:52591
592 if (GetParam() > QUIC_VERSION_13) {
593 AddWrite(ConstructRstStreamPacket(1));
594 }
595
[email protected]e1cca9a2013-09-20 17:14:44596 Initialize();
597
598 request_.method = "GET";
599 request_.url = GURL("http://www.google.com/");
600
601 EXPECT_EQ(OK, stream_->InitializeStream(&request_, MEDIUM,
602 net_log_, callback_.callback()));
603
604 // Check that priority is highest.
605 QuicReliableClientStream* reliable_stream =
606 QuicHttpStreamPeer::GetQuicReliableClientStream(stream_.get());
607 DCHECK(reliable_stream);
608 QuicReliableClientStream::Delegate* delegate = reliable_stream->GetDelegate();
609 DCHECK(delegate);
[email protected]9f0dcd4e2014-01-16 15:58:14610 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority,
[email protected]e1cca9a2013-09-20 17:14:44611 reliable_stream->EffectivePriority());
612
613 // Set Delegate to NULL and make sure EffectivePriority returns highest
614 // priority.
615 reliable_stream->SetDelegate(NULL);
[email protected]9f0dcd4e2014-01-16 15:58:14616 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority,
[email protected]e1cca9a2013-09-20 17:14:44617 reliable_stream->EffectivePriority());
618 reliable_stream->SetDelegate(delegate);
619}
620
[email protected]f702d572012-12-04 15:56:20621} // namespace test
[email protected]f702d572012-12-04 15:56:20622} // namespace net