blob: 53be4dd1455f046b48a0c6d47106796c59e8ff70 [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
mmenkecbc2b712014-10-09 20:29:079#include "net/base/chunked_upload_data_stream.h"
10#include "net/base/elements_upload_data_stream.h"
[email protected]f702d572012-12-04 15:56:2011#include "net/base/net_errors.h"
12#include "net/base/test_completion_callback.h"
[email protected]b2d26cfd2012-12-11 10:36:0613#include "net/base/upload_bytes_element_reader.h"
[email protected]f702d572012-12-04 15:56:2014#include "net/http/http_response_headers.h"
[email protected]5db452202014-08-19 05:22:1515#include "net/http/transport_security_state.h"
[email protected]fee17f72013-02-03 07:47:4116#include "net/quic/congestion_control/receive_algorithm_interface.h"
17#include "net/quic/congestion_control/send_algorithm_interface.h"
[email protected]e8ff26842013-03-22 21:02:0518#include "net/quic/crypto/crypto_protocol.h"
[email protected]4df69842013-02-27 06:32:1619#include "net/quic/crypto/quic_decrypter.h"
20#include "net/quic/crypto/quic_encrypter.h"
[email protected]17bf15c2014-03-14 10:08:0421#include "net/quic/crypto/quic_server_info.h"
[email protected]f702d572012-12-04 15:56:2022#include "net/quic/quic_client_session.h"
23#include "net/quic/quic_connection.h"
24#include "net/quic/quic_connection_helper.h"
[email protected]cbd731e2013-10-24 00:20:3925#include "net/quic/quic_default_packet_writer.h"
[email protected]24e5bc52013-09-18 15:36:5826#include "net/quic/quic_http_utils.h"
27#include "net/quic/quic_reliable_client_stream.h"
[email protected]9f0dcd4e2014-01-16 15:58:1428#include "net/quic/quic_write_blocked_list.h"
[email protected]3e7dca62013-09-10 16:14:2329#include "net/quic/spdy_utils.h"
[email protected]f702d572012-12-04 15:56:2030#include "net/quic/test_tools/mock_clock.h"
[email protected]e8ff26842013-03-22 21:02:0531#include "net/quic/test_tools/mock_crypto_client_stream_factory.h"
[email protected]9db443912013-02-25 05:27:0332#include "net/quic/test_tools/mock_random.h"
[email protected]b1f287d2012-12-22 17:25:3933#include "net/quic/test_tools/quic_connection_peer.h"
[email protected]1e960032013-12-20 19:00:2034#include "net/quic/test_tools/quic_test_packet_maker.h"
[email protected]f702d572012-12-04 15:56:2035#include "net/quic/test_tools/quic_test_utils.h"
36#include "net/quic/test_tools/test_task_runner.h"
37#include "net/socket/socket_test_util.h"
[email protected]6cca996b2013-01-25 07:43:3638#include "net/spdy/spdy_frame_builder.h"
39#include "net/spdy/spdy_framer.h"
40#include "net/spdy/spdy_http_utils.h"
41#include "net/spdy/spdy_protocol.h"
[email protected]f702d572012-12-04 15:56:2042#include "testing/gmock/include/gmock/gmock.h"
43#include "testing/gtest/include/gtest/gtest.h"
44
45using testing::_;
[email protected]06ff5152013-08-29 01:03:0546using testing::AnyNumber;
47using testing::Return;
[email protected]f702d572012-12-04 15:56:2048
49namespace net {
[email protected]f702d572012-12-04 15:56:2050namespace test {
[email protected]f702d572012-12-04 15:56:2051namespace {
52
[email protected]16ba7742014-08-22 00:57:2553const char kUploadData[] = "Really nifty data!";
[email protected]e4c3ea62014-03-15 00:45:1454const char kServerHostname[] = "www.google.com";
55const uint16 kServerPort = 80;
[email protected]f702d572012-12-04 15:56:2056
57class TestQuicConnection : public QuicConnection {
58 public:
[email protected]1e960032013-12-20 19:00:2059 TestQuicConnection(const QuicVersionVector& versions,
[email protected]3aa9ca72014-02-27 19:39:4360 QuicConnectionId connection_id,
[email protected]f702d572012-12-04 15:56:2061 IPEndPoint address,
[email protected]cbd731e2013-10-24 00:20:3962 QuicConnectionHelper* helper,
[email protected]6d515822014-08-22 01:58:0663 const QuicConnection::PacketWriterFactory& writer_factory)
[email protected]66cd2d62014-08-01 18:42:3964 : QuicConnection(connection_id,
65 address,
66 helper,
[email protected]6d515822014-08-22 01:58:0667 writer_factory,
68 true /* owns_writer */,
[email protected]66cd2d62014-08-01 18:42:3969 false /* is_server */,
[email protected]ce7bb1412014-05-17 15:51:3370 versions) {
[email protected]f702d572012-12-04 15:56:2071 }
72
[email protected]fee17f72013-02-03 07:47:4173 void SetSendAlgorithm(SendAlgorithmInterface* send_algorithm) {
74 QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
[email protected]f702d572012-12-04 15:56:2075 }
[email protected]26f3f8e2012-12-13 21:07:1976
[email protected]fee17f72013-02-03 07:47:4177 void SetReceiveAlgorithm(ReceiveAlgorithmInterface* receive_algorithm) {
78 QuicConnectionPeer::SetReceiveAlgorithm(this, receive_algorithm);
[email protected]26f3f8e2012-12-13 21:07:1979 }
80};
81
[email protected]fee17f72013-02-03 07:47:4182class TestReceiveAlgorithm : public ReceiveAlgorithmInterface {
[email protected]26f3f8e2012-12-13 21:07:1983 public:
[email protected]1e960032013-12-20 19:00:2084 virtual bool GenerateCongestionFeedback(
85 QuicCongestionFeedbackFrame* /*congestion_feedback*/) {
86 return false;
[email protected]26f3f8e2012-12-13 21:07:1987 }
88
[email protected]6ae6e342014-02-06 02:21:4289 MOCK_METHOD3(RecordIncomingPacket,
90 void(QuicByteCount, QuicPacketSequenceNumber, QuicTime));
[email protected]f702d572012-12-04 15:56:2091};
92
[email protected]63534512012-12-23 18:49:0093// Subclass of QuicHttpStream that closes itself when the first piece of data
94// is received.
95class AutoClosingStream : public QuicHttpStream {
96 public:
[email protected]0b2294d32013-08-02 00:46:3697 explicit AutoClosingStream(const base::WeakPtr<QuicClientSession>& session)
98 : QuicHttpStream(session) {
[email protected]63534512012-12-23 18:49:0099 }
100
dchengb03027d2014-10-21 12:00:20101 int OnDataReceived(const char* data, int length) override {
[email protected]63534512012-12-23 18:49:00102 Close(false);
103 return OK;
104 }
105};
106
[email protected]6d515822014-08-22 01:58:06107class TestPacketWriterFactory : public QuicConnection::PacketWriterFactory {
108 public:
109 explicit TestPacketWriterFactory(DatagramClientSocket* socket)
110 : socket_(socket) {}
dchengb03027d2014-10-21 12:00:20111 ~TestPacketWriterFactory() override {}
[email protected]6d515822014-08-22 01:58:06112
dchengb03027d2014-10-21 12:00:20113 QuicPacketWriter* Create(QuicConnection* connection) const override {
[email protected]6d515822014-08-22 01:58:06114 return new QuicDefaultPacketWriter(socket_);
115 }
116
117 private:
118 DatagramClientSocket* socket_;
119};
120
[email protected]f702d572012-12-04 15:56:20121} // namespace
122
[email protected]24e5bc52013-09-18 15:36:58123class QuicHttpStreamPeer {
124 public:
125 static QuicReliableClientStream* GetQuicReliableClientStream(
126 QuicHttpStream* stream) {
127 return stream->stream_;
128 }
129};
130
[email protected]1e960032013-12-20 19:00:20131class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
[email protected]f702d572012-12-04 15:56:20132 protected:
[email protected]1e960032013-12-20 19:00:20133 static const bool kFin = true;
134 static const bool kIncludeVersion = true;
135 static const bool kIncludeCongestionFeedback = true;
136
[email protected]f702d572012-12-04 15:56:20137 // Holds a packet to be written to the wire, and the IO mode that should
138 // be used by the mock socket when performing the write.
139 struct PacketToWrite {
140 PacketToWrite(IoMode mode, QuicEncryptedPacket* packet)
141 : mode(mode),
142 packet(packet) {
143 }
144 IoMode mode;
145 QuicEncryptedPacket* packet;
146 };
147
148 QuicHttpStreamTest()
149 : net_log_(BoundNetLog()),
[email protected]63534512012-12-23 18:49:00150 use_closing_stream_(false),
[email protected]f702d572012-12-04 15:56:20151 read_buffer_(new IOBufferWithSize(4096)),
[email protected]3aa9ca72014-02-27 19:39:43152 connection_id_(2),
[email protected]66ae5962014-05-22 11:13:05153 stream_id_(kClientDataStreamId1),
rtenneti4b06ae72014-08-26 03:43:43154 maker_(GetParam(), connection_id_, &clock_),
[email protected]1e960032013-12-20 19:00:20155 random_generator_(0) {
[email protected]f702d572012-12-04 15:56:20156 IPAddressNumber ip;
157 CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip));
158 peer_addr_ = IPEndPoint(ip, 443);
159 self_addr_ = IPEndPoint(ip, 8435);
rtenneti4b06ae72014-08-26 03:43:43160 clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(20));
[email protected]f702d572012-12-04 15:56:20161 }
162
163 ~QuicHttpStreamTest() {
[email protected]4d283b32013-10-17 12:57:27164 session_->CloseSessionOnError(ERR_ABORTED);
[email protected]f702d572012-12-04 15:56:20165 for (size_t i = 0; i < writes_.size(); i++) {
166 delete writes_[i].packet;
167 }
168 }
169
170 // Adds a packet to the list of expected writes.
[email protected]1e960032013-12-20 19:00:20171 void AddWrite(scoped_ptr<QuicEncryptedPacket> packet) {
172 writes_.push_back(PacketToWrite(SYNCHRONOUS, packet.release()));
[email protected]f702d572012-12-04 15:56:20173 }
174
175 // Returns the packet to be written at position |pos|.
176 QuicEncryptedPacket* GetWrite(size_t pos) {
177 return writes_[pos].packet;
178 }
179
180 bool AtEof() {
181 return socket_data_->at_read_eof() && socket_data_->at_write_eof();
182 }
183
[email protected]1e960032013-12-20 19:00:20184 void ProcessPacket(scoped_ptr<QuicEncryptedPacket> packet) {
185 connection_->ProcessUdpPacket(self_addr_, peer_addr_, *packet);
[email protected]f702d572012-12-04 15:56:20186 }
187
188 // Configures the test fixture to use the list of expected writes.
189 void Initialize() {
190 mock_writes_.reset(new MockWrite[writes_.size()]);
191 for (size_t i = 0; i < writes_.size(); i++) {
192 mock_writes_[i] = MockWrite(writes_[i].mode,
193 writes_[i].packet->data(),
194 writes_[i].packet->length());
195 };
196
rtennetibe635732014-10-02 22:51:42197 socket_data_.reset(new StaticSocketDataProvider(
198 nullptr, 0, mock_writes_.get(), writes_.size()));
[email protected]f702d572012-12-04 15:56:20199
[email protected]e13201d82012-12-12 05:00:32200 MockUDPClientSocket* socket = new MockUDPClientSocket(socket_data_.get(),
201 net_log_.net_log());
202 socket->Connect(peer_addr_);
[email protected]f702d572012-12-04 15:56:20203 runner_ = new TestTaskRunner(&clock_);
[email protected]fee17f72013-02-03 07:47:41204 send_algorithm_ = new MockSendAlgorithm();
[email protected]1e960032013-12-20 19:00:20205 receive_algorithm_ = new TestReceiveAlgorithm();
[email protected]6ae6e342014-02-06 02:21:42206 EXPECT_CALL(*receive_algorithm_, RecordIncomingPacket(_, _, _)).
[email protected]06ff5152013-08-29 01:03:05207 Times(AnyNumber());
[email protected]efecff92013-09-24 07:49:23208 EXPECT_CALL(*send_algorithm_,
[email protected]ef0da582014-05-09 07:16:30209 OnPacketSent(_, _, _, _, _)).WillRepeatedly(Return(true));
[email protected]48878092013-07-26 14:51:56210 EXPECT_CALL(*send_algorithm_, RetransmissionDelay()).WillRepeatedly(
[email protected]06ff5152013-08-29 01:03:05211 Return(QuicTime::Delta::Zero()));
[email protected]08da9adb2014-04-24 08:33:31212 EXPECT_CALL(*send_algorithm_, GetCongestionWindow()).WillRepeatedly(
213 Return(kMaxPacketSize));
[email protected]77b5d50b2014-05-07 22:48:48214 EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _)).
[email protected]06ff5152013-08-29 01:03:05215 WillRepeatedly(Return(QuicTime::Delta::Zero()));
[email protected]ea825e02013-08-21 18:12:45216 EXPECT_CALL(*send_algorithm_, BandwidthEstimate()).WillRepeatedly(
[email protected]06ff5152013-08-29 01:03:05217 Return(QuicBandwidth::Zero()));
[email protected]62f90632013-11-01 13:07:11218 EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(AnyNumber());
[email protected]2cfc6bb82013-10-27 03:40:44219 helper_.reset(new QuicConnectionHelper(runner_.get(), &clock_,
220 &random_generator_));
[email protected]6d515822014-08-22 01:58:06221 TestPacketWriterFactory writer_factory(socket);
[email protected]3aa9ca72014-02-27 19:39:43222 connection_ = new TestQuicConnection(SupportedVersions(GetParam()),
223 connection_id_, peer_addr_,
[email protected]6d515822014-08-22 01:58:06224 helper_.get(), writer_factory);
[email protected]f702d572012-12-04 15:56:20225 connection_->set_visitor(&visitor_);
[email protected]fee17f72013-02-03 07:47:41226 connection_->SetSendAlgorithm(send_algorithm_);
227 connection_->SetReceiveAlgorithm(receive_algorithm_);
[email protected]18ccfdb2013-08-15 00:13:44228 session_.reset(
229 new QuicClientSession(connection_,
[email protected]cbd731e2013-10-24 00:20:39230 scoped_ptr<DatagramClientSocket>(socket),
rtennetibe635732014-10-02 22:51:42231 nullptr,
[email protected]5db452202014-08-19 05:22:15232 &transport_security_state_,
rtennetibe635732014-10-02 22:51:42233 make_scoped_ptr((QuicServerInfo*)nullptr),
rtennetib998b322014-08-26 00:36:33234 DefaultQuicConfig(),
[email protected]65768442014-06-06 23:37:03235 base::MessageLoop::current()->
236 message_loop_proxy().get(),
rtennetibe635732014-10-02 22:51:42237 nullptr));
rtennetib998b322014-08-26 00:36:33238 session_->InitializeSession(QuicServerId(kServerHostname, kServerPort,
239 false, PRIVACY_MODE_DISABLED),
240 &crypto_config_,
241 &crypto_client_stream_factory_);
[email protected]ed3fc15d2013-03-08 18:37:44242 session_->GetCryptoStream()->CryptoConnect();
[email protected]8ba81212013-05-03 13:11:48243 EXPECT_TRUE(session_->IsCryptoHandshakeConfirmed());
[email protected]6cca996b2013-01-25 07:43:36244 stream_.reset(use_closing_stream_ ?
[email protected]0b2294d32013-08-02 00:46:36245 new AutoClosingStream(session_->GetWeakPtr()) :
246 new QuicHttpStream(session_->GetWeakPtr()));
[email protected]6cca996b2013-01-25 07:43:36247 }
248
[email protected]1e960032013-12-20 19:00:20249 void SetRequest(const std::string& method,
250 const std::string& path,
251 RequestPriority priority) {
252 request_headers_ = maker_.GetRequestHeaders(method, "http", path);
[email protected]6cca996b2013-01-25 07:43:36253 }
254
[email protected]1e960032013-12-20 19:00:20255 void SetResponse(const std::string& status, const std::string& body) {
256 response_headers_ = maker_.GetResponseHeaders(status);
[email protected]92bf17c2014-03-03 21:14:03257 response_data_ = body;
[email protected]6cca996b2013-01-25 07:43:36258 }
[email protected]f702d572012-12-04 15:56:20259
[email protected]1e960032013-12-20 19:00:20260 scoped_ptr<QuicEncryptedPacket> ConstructDataPacket(
[email protected]f702d572012-12-04 15:56:20261 QuicPacketSequenceNumber sequence_number,
[email protected]e8ff26842013-03-22 21:02:05262 bool should_include_version,
[email protected]f702d572012-12-04 15:56:20263 bool fin,
264 QuicStreamOffset offset,
265 base::StringPiece data) {
[email protected]1e960032013-12-20 19:00:20266 return maker_.MakeDataPacket(
267 sequence_number, stream_id_, should_include_version, fin, offset, data);
[email protected]f702d572012-12-04 15:56:20268 }
269
[email protected]1e960032013-12-20 19:00:20270 scoped_ptr<QuicEncryptedPacket> ConstructRequestHeadersPacket(
271 QuicPacketSequenceNumber sequence_number,
272 bool fin) {
273 return maker_.MakeRequestHeadersPacket(
274 sequence_number, stream_id_, kIncludeVersion, fin, request_headers_);
275 }
276
277 scoped_ptr<QuicEncryptedPacket> ConstructResponseHeadersPacket(
278 QuicPacketSequenceNumber sequence_number,
279 bool fin) {
280 return maker_.MakeResponseHeadersPacket(
281 sequence_number, stream_id_, !kIncludeVersion, fin, response_headers_);
282 }
283
284 scoped_ptr<QuicEncryptedPacket> ConstructRstStreamPacket(
[email protected]06ff5152013-08-29 01:03:05285 QuicPacketSequenceNumber sequence_number) {
[email protected]1e960032013-12-20 19:00:20286 return maker_.MakeRstPacket(
[email protected]51cc1342014-04-18 23:44:37287 sequence_number, true, stream_id_,
288 AdjustErrorForVersion(QUIC_RST_FLOW_CONTROL_ACCOUNTING, GetParam()));
[email protected]06ff5152013-08-29 01:03:05289 }
290
[email protected]c5e1aca2014-01-30 04:03:04291 scoped_ptr<QuicEncryptedPacket> ConstructAckAndRstStreamPacket(
292 QuicPacketSequenceNumber sequence_number) {
293 return maker_.MakeAckAndRstPacket(
294 sequence_number, !kIncludeVersion, stream_id_, QUIC_STREAM_CANCELLED,
[email protected]08da9adb2014-04-24 08:33:31295 2, 1, !kIncludeCongestionFeedback);
[email protected]c5e1aca2014-01-30 04:03:04296 }
297
[email protected]1e960032013-12-20 19:00:20298 scoped_ptr<QuicEncryptedPacket> ConstructAckPacket(
[email protected]f702d572012-12-04 15:56:20299 QuicPacketSequenceNumber sequence_number,
[email protected]63534512012-12-23 18:49:00300 QuicPacketSequenceNumber largest_received,
301 QuicPacketSequenceNumber least_unacked) {
[email protected]1e960032013-12-20 19:00:20302 return maker_.MakeAckPacket(sequence_number, largest_received,
303 least_unacked, !kIncludeCongestionFeedback);
[email protected]63534512012-12-23 18:49:00304 }
305
[email protected]f702d572012-12-04 15:56:20306 BoundNetLog net_log_;
[email protected]63534512012-12-23 18:49:00307 bool use_closing_stream_;
[email protected]fee17f72013-02-03 07:47:41308 MockSendAlgorithm* send_algorithm_;
309 TestReceiveAlgorithm* receive_algorithm_;
[email protected]f702d572012-12-04 15:56:20310 scoped_refptr<TestTaskRunner> runner_;
[email protected]4356f0f2013-04-07 00:58:17311 scoped_ptr<MockWrite[]> mock_writes_;
[email protected]f702d572012-12-04 15:56:20312 MockClock clock_;
313 TestQuicConnection* connection_;
[email protected]2cfc6bb82013-10-27 03:40:44314 scoped_ptr<QuicConnectionHelper> helper_;
[email protected]f702d572012-12-04 15:56:20315 testing::StrictMock<MockConnectionVisitor> visitor_;
316 scoped_ptr<QuicHttpStream> stream_;
[email protected]5db452202014-08-19 05:22:15317 TransportSecurityState transport_security_state_;
[email protected]f702d572012-12-04 15:56:20318 scoped_ptr<QuicClientSession> session_;
[email protected]ef95114d2013-04-17 17:57:01319 QuicCryptoClientConfig crypto_config_;
[email protected]f702d572012-12-04 15:56:20320 TestCompletionCallback callback_;
321 HttpRequestInfo request_;
322 HttpRequestHeaders headers_;
323 HttpResponseInfo response_;
324 scoped_refptr<IOBufferWithSize> read_buffer_;
[email protected]1e960032013-12-20 19:00:20325 SpdyHeaderBlock request_headers_;
326 SpdyHeaderBlock response_headers_;
[email protected]6cca996b2013-01-25 07:43:36327 std::string request_data_;
328 std::string response_data_;
[email protected]f702d572012-12-04 15:56:20329
330 private:
[email protected]3aa9ca72014-02-27 19:39:43331 const QuicConnectionId connection_id_;
[email protected]1e960032013-12-20 19:00:20332 const QuicStreamId stream_id_;
333 QuicTestPacketMaker maker_;
[email protected]f702d572012-12-04 15:56:20334 IPEndPoint self_addr_;
335 IPEndPoint peer_addr_;
[email protected]457d6952013-12-13 09:24:58336 MockRandom random_generator_;
[email protected]e8ff26842013-03-22 21:02:05337 MockCryptoClientStreamFactory crypto_client_stream_factory_;
[email protected]f702d572012-12-04 15:56:20338 scoped_ptr<StaticSocketDataProvider> socket_data_;
339 std::vector<PacketToWrite> writes_;
340};
341
[email protected]1e960032013-12-20 19:00:20342INSTANTIATE_TEST_CASE_P(Version, QuicHttpStreamTest,
343 ::testing::ValuesIn(QuicSupportedVersions()));
344
345TEST_P(QuicHttpStreamTest, RenewStreamForAuth) {
[email protected]ed3fc15d2013-03-08 18:37:44346 Initialize();
rtennetibe635732014-10-02 22:51:42347 EXPECT_EQ(nullptr, stream_->RenewStreamForAuth());
[email protected]f702d572012-12-04 15:56:20348}
349
[email protected]1e960032013-12-20 19:00:20350TEST_P(QuicHttpStreamTest, CanFindEndOfResponse) {
[email protected]ed3fc15d2013-03-08 18:37:44351 Initialize();
[email protected]f702d572012-12-04 15:56:20352 EXPECT_TRUE(stream_->CanFindEndOfResponse());
353}
354
[email protected]1e960032013-12-20 19:00:20355TEST_P(QuicHttpStreamTest, IsConnectionReusable) {
[email protected]ed3fc15d2013-03-08 18:37:44356 Initialize();
[email protected]f702d572012-12-04 15:56:20357 EXPECT_FALSE(stream_->IsConnectionReusable());
358}
359
[email protected]1e960032013-12-20 19:00:20360TEST_P(QuicHttpStreamTest, GetRequest) {
361 SetRequest("GET", "/", DEFAULT_PRIORITY);
[email protected]92bf17c2014-03-03 21:14:03362 AddWrite(ConstructRequestHeadersPacket(1, kFin));
[email protected]f702d572012-12-04 15:56:20363 Initialize();
364
365 request_.method = "GET";
366 request_.url = GURL("http://www.google.com/");
367
[email protected]262eec82013-03-19 21:01:36368 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
369 net_log_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20370 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
371 callback_.callback()));
[email protected]f702d572012-12-04 15:56:20372
373 // Ack the request.
[email protected]1e960032013-12-20 19:00:20374 ProcessPacket(ConstructAckPacket(1, 0, 0));
[email protected]f702d572012-12-04 15:56:20375
376 EXPECT_EQ(ERR_IO_PENDING,
377 stream_->ReadResponseHeaders(callback_.callback()));
378
[email protected]1e960032013-12-20 19:00:20379 SetResponse("404 Not Found", std::string());
[email protected]92bf17c2014-03-03 21:14:03380 ProcessPacket(ConstructResponseHeadersPacket(2, kFin));
[email protected]f702d572012-12-04 15:56:20381
382 // Now that the headers have been processed, the callback will return.
383 EXPECT_EQ(OK, callback_.WaitForResult());
[email protected]cadac622013-06-11 16:46:36384 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:20385 EXPECT_EQ(404, response_.headers->response_code());
386 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
[email protected]6ed67432014-06-24 01:53:53387 EXPECT_FALSE(response_.response_time.is_null());
388 EXPECT_FALSE(response_.request_time.is_null());
[email protected]f702d572012-12-04 15:56:20389
390 // There is no body, so this should return immediately.
391 EXPECT_EQ(0, stream_->ReadResponseBody(read_buffer_.get(),
392 read_buffer_->size(),
393 callback_.callback()));
394 EXPECT_TRUE(stream_->IsResponseBodyComplete());
395 EXPECT_TRUE(AtEof());
396}
397
[email protected]3e7dca62013-09-10 16:14:23398// Regression test for http://crbug.com/288128
[email protected]1e960032013-12-20 19:00:20399TEST_P(QuicHttpStreamTest, GetRequestLargeResponse) {
400 SetRequest("GET", "/", DEFAULT_PRIORITY);
[email protected]92bf17c2014-03-03 21:14:03401 AddWrite(ConstructRequestHeadersPacket(1, kFin));
[email protected]3e7dca62013-09-10 16:14:23402 Initialize();
403
404 request_.method = "GET";
405 request_.url = GURL("http://www.google.com/");
406
407 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
408 net_log_, callback_.callback()));
409 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
410 callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:23411
412 // Ack the request.
[email protected]1e960032013-12-20 19:00:20413 ProcessPacket(ConstructAckPacket(1, 0, 0));
[email protected]3e7dca62013-09-10 16:14:23414
415 EXPECT_EQ(ERR_IO_PENDING,
416 stream_->ReadResponseHeaders(callback_.callback()));
417
418 SpdyHeaderBlock headers;
419 headers[":status"] = "200 OK";
420 headers[":version"] = "HTTP/1.1";
421 headers["content-type"] = "text/plain";
422 headers["big6"] = std::string(10000, 'x'); // Lots of x's.
423
424 std::string response = SpdyUtils::SerializeUncompressedHeaders(headers);
425 EXPECT_LT(4096u, response.length());
426 stream_->OnDataReceived(response.data(), response.length());
427 stream_->OnClose(QUIC_NO_ERROR);
428
429 // Now that the headers have been processed, the callback will return.
430 EXPECT_EQ(OK, callback_.WaitForResult());
431 ASSERT_TRUE(response_.headers.get());
432 EXPECT_EQ(200, response_.headers->response_code());
433 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
434
435 // There is no body, so this should return immediately.
436 EXPECT_EQ(0, stream_->ReadResponseBody(read_buffer_.get(),
437 read_buffer_->size(),
438 callback_.callback()));
439 EXPECT_TRUE(stream_->IsResponseBodyComplete());
440 EXPECT_TRUE(AtEof());
441}
442
rchf9f103cbc2014-08-30 05:28:04443// Regression test for http://crbug.com/409101
444TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendRequest) {
445 SetRequest("GET", "/", DEFAULT_PRIORITY);
446 Initialize();
447
448 request_.method = "GET";
449 request_.url = GURL("http://www.google.com/");
450
451 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
452 net_log_, callback_.callback()));
453
454 session_->connection()->CloseConnection(QUIC_NO_ERROR, true);
455
456 EXPECT_EQ(ERR_CONNECTION_CLOSED,
457 stream_->SendRequest(headers_, &response_,
458 callback_.callback()));
459}
460
rch11a114a2014-09-04 23:41:59461// Regression test for http://crbug.com/409871
462TEST_P(QuicHttpStreamTest, SessionClosedBeforeReadResponseHeaders) {
463 SetRequest("GET", "/", DEFAULT_PRIORITY);
464 AddWrite(ConstructRequestHeadersPacket(1, kFin));
465 Initialize();
466
467 request_.method = "GET";
468 request_.url = GURL("http://www.google.com/");
469
470 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
471 net_log_, callback_.callback()));
472
473 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
474 callback_.callback()));
475
476 session_->connection()->CloseConnection(QUIC_NO_ERROR, true);
477
478 EXPECT_NE(OK, stream_->ReadResponseHeaders(callback_.callback()));
479}
480
[email protected]1e960032013-12-20 19:00:20481TEST_P(QuicHttpStreamTest, SendPostRequest) {
482 SetRequest("POST", "/", DEFAULT_PRIORITY);
[email protected]92bf17c2014-03-03 21:14:03483 AddWrite(ConstructRequestHeadersPacket(1, !kFin));
484 AddWrite(ConstructDataPacket(2, kIncludeVersion, kFin, 0, kUploadData));
[email protected]1e960032013-12-20 19:00:20485 AddWrite(ConstructAckPacket(3, 3, 1));
[email protected]f702d572012-12-04 15:56:20486
487 Initialize();
488
[email protected]b2d26cfd2012-12-11 10:36:06489 ScopedVector<UploadElementReader> element_readers;
490 element_readers.push_back(
491 new UploadBytesElementReader(kUploadData, strlen(kUploadData)));
mmenkecbc2b712014-10-09 20:29:07492 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
[email protected]f702d572012-12-04 15:56:20493 request_.method = "POST";
494 request_.url = GURL("http://www.google.com/");
495 request_.upload_data_stream = &upload_data_stream;
[email protected]4db27d82012-12-20 11:50:24496 ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback()));
[email protected]f702d572012-12-04 15:56:20497
[email protected]262eec82013-03-19 21:01:36498 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
499 net_log_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20500 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
501 callback_.callback()));
[email protected]f702d572012-12-04 15:56:20502
503 // Ack both packets in the request.
[email protected]1e960032013-12-20 19:00:20504 ProcessPacket(ConstructAckPacket(1, 0, 0));
[email protected]f702d572012-12-04 15:56:20505
506 // Send the response headers (but not the body).
[email protected]1e960032013-12-20 19:00:20507 SetResponse("200 OK", std::string());
[email protected]92bf17c2014-03-03 21:14:03508 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin));
[email protected]f702d572012-12-04 15:56:20509
510 // Since the headers have already arrived, this should return immediately.
511 EXPECT_EQ(OK, stream_->ReadResponseHeaders(callback_.callback()));
[email protected]cadac622013-06-11 16:46:36512 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:20513 EXPECT_EQ(200, response_.headers->response_code());
514 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
515
516 // Send the response body.
517 const char kResponseBody[] = "Hello world!";
[email protected]92bf17c2014-03-03 21:14:03518 ProcessPacket(ConstructDataPacket(3, false, kFin, 0, kResponseBody));
[email protected]f702d572012-12-04 15:56:20519 // Since the body has already arrived, this should return immediately.
520 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
521 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
522 callback_.callback()));
523
524 EXPECT_TRUE(stream_->IsResponseBodyComplete());
525 EXPECT_TRUE(AtEof());
526}
527
[email protected]1e960032013-12-20 19:00:20528TEST_P(QuicHttpStreamTest, SendChunkedPostRequest) {
529 SetRequest("POST", "/", DEFAULT_PRIORITY);
[email protected]c9e49a02013-02-26 05:56:47530 size_t chunk_size = strlen(kUploadData);
[email protected]92bf17c2014-03-03 21:14:03531 AddWrite(ConstructRequestHeadersPacket(1, !kFin));
532 AddWrite(ConstructDataPacket(2, kIncludeVersion, !kFin, 0, kUploadData));
533 AddWrite(ConstructDataPacket(3, kIncludeVersion, kFin, chunk_size,
534 kUploadData));
[email protected]1e960032013-12-20 19:00:20535 AddWrite(ConstructAckPacket(4, 3, 1));
[email protected]c9e49a02013-02-26 05:56:47536 Initialize();
537
mmenkecbc2b712014-10-09 20:29:07538 ChunkedUploadDataStream upload_data_stream(0);
539 upload_data_stream.AppendData(kUploadData, chunk_size, false);
[email protected]c9e49a02013-02-26 05:56:47540
541 request_.method = "POST";
542 request_.url = GURL("http://www.google.com/");
543 request_.upload_data_stream = &upload_data_stream;
mmenkecbc2b712014-10-09 20:29:07544 ASSERT_EQ(OK, request_.upload_data_stream->Init(
545 TestCompletionCallback().callback()));
[email protected]c9e49a02013-02-26 05:56:47546
[email protected]262eec82013-03-19 21:01:36547 ASSERT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
548 net_log_, callback_.callback()));
[email protected]c9e49a02013-02-26 05:56:47549 ASSERT_EQ(ERR_IO_PENDING, stream_->SendRequest(headers_, &response_,
550 callback_.callback()));
[email protected]c9e49a02013-02-26 05:56:47551
mmenkecbc2b712014-10-09 20:29:07552 upload_data_stream.AppendData(kUploadData, chunk_size, true);
[email protected]c9e49a02013-02-26 05:56:47553
554 // Ack both packets in the request.
[email protected]1e960032013-12-20 19:00:20555 ProcessPacket(ConstructAckPacket(1, 0, 0));
[email protected]c9e49a02013-02-26 05:56:47556
557 // Send the response headers (but not the body).
[email protected]1e960032013-12-20 19:00:20558 SetResponse("200 OK", std::string());
[email protected]92bf17c2014-03-03 21:14:03559 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin));
[email protected]c9e49a02013-02-26 05:56:47560
561 // Since the headers have already arrived, this should return immediately.
562 ASSERT_EQ(OK, stream_->ReadResponseHeaders(callback_.callback()));
[email protected]cadac622013-06-11 16:46:36563 ASSERT_TRUE(response_.headers.get());
[email protected]c9e49a02013-02-26 05:56:47564 EXPECT_EQ(200, response_.headers->response_code());
565 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
566
567 // Send the response body.
568 const char kResponseBody[] = "Hello world!";
[email protected]1e960032013-12-20 19:00:20569 ProcessPacket(ConstructDataPacket(3, false, kFin, response_data_.length(),
570 kResponseBody));
[email protected]c9e49a02013-02-26 05:56:47571
572 // Since the body has already arrived, this should return immediately.
573 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
574 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
575 callback_.callback()));
576
577 EXPECT_TRUE(stream_->IsResponseBodyComplete());
578 EXPECT_TRUE(AtEof());
579}
580
[email protected]16ba7742014-08-22 00:57:25581TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithFinalEmptyDataPacket) {
582 SetRequest("POST", "/", DEFAULT_PRIORITY);
583 size_t chunk_size = strlen(kUploadData);
584 AddWrite(ConstructRequestHeadersPacket(1, !kFin));
585 AddWrite(ConstructDataPacket(2, kIncludeVersion, !kFin, 0, kUploadData));
586 AddWrite(ConstructDataPacket(3, kIncludeVersion, kFin, chunk_size, ""));
587 AddWrite(ConstructAckPacket(4, 3, 1));
588 Initialize();
589
mmenkecbc2b712014-10-09 20:29:07590 ChunkedUploadDataStream upload_data_stream(0);
591 upload_data_stream.AppendData(kUploadData, chunk_size, false);
[email protected]16ba7742014-08-22 00:57:25592
593 request_.method = "POST";
594 request_.url = GURL("http://www.google.com/");
595 request_.upload_data_stream = &upload_data_stream;
mmenkecbc2b712014-10-09 20:29:07596 ASSERT_EQ(OK, request_.upload_data_stream->Init(
597 TestCompletionCallback().callback()));
[email protected]16ba7742014-08-22 00:57:25598
599 ASSERT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
600 net_log_, callback_.callback()));
601 ASSERT_EQ(ERR_IO_PENDING, stream_->SendRequest(headers_, &response_,
602 callback_.callback()));
603
mmenkecbc2b712014-10-09 20:29:07604 upload_data_stream.AppendData(nullptr, 0, true);
[email protected]16ba7742014-08-22 00:57:25605
606 ProcessPacket(ConstructAckPacket(1, 0, 0));
607
608 // Send the response headers (but not the body).
609 SetResponse("200 OK", std::string());
610 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin));
611
612 // Since the headers have already arrived, this should return immediately.
613 ASSERT_EQ(OK, stream_->ReadResponseHeaders(callback_.callback()));
614 ASSERT_TRUE(response_.headers.get());
615 EXPECT_EQ(200, response_.headers->response_code());
616 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
617
618 // Send the response body.
619 const char kResponseBody[] = "Hello world!";
620 ProcessPacket(ConstructDataPacket(3, false, kFin, response_data_.length(),
621 kResponseBody));
622
623 // Since the body has already arrived, this should return immediately.
624 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
625 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
626 callback_.callback()));
627
628 EXPECT_TRUE(stream_->IsResponseBodyComplete());
629 EXPECT_TRUE(AtEof());
630}
631
632TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithOneEmptyDataPacket) {
633 SetRequest("POST", "/", DEFAULT_PRIORITY);
634 AddWrite(ConstructRequestHeadersPacket(1, !kFin));
635 AddWrite(ConstructDataPacket(2, kIncludeVersion, kFin, 0, ""));
636 AddWrite(ConstructAckPacket(3, 3, 1));
637 Initialize();
638
mmenkecbc2b712014-10-09 20:29:07639 ChunkedUploadDataStream upload_data_stream(0);
[email protected]16ba7742014-08-22 00:57:25640
641 request_.method = "POST";
642 request_.url = GURL("http://www.google.com/");
643 request_.upload_data_stream = &upload_data_stream;
mmenkecbc2b712014-10-09 20:29:07644 ASSERT_EQ(OK, request_.upload_data_stream->Init(
645 TestCompletionCallback().callback()));
[email protected]16ba7742014-08-22 00:57:25646
647 ASSERT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
648 net_log_, callback_.callback()));
649 ASSERT_EQ(ERR_IO_PENDING, stream_->SendRequest(headers_, &response_,
650 callback_.callback()));
651
mmenkecbc2b712014-10-09 20:29:07652 upload_data_stream.AppendData(nullptr, 0, true);
[email protected]16ba7742014-08-22 00:57:25653
654 ProcessPacket(ConstructAckPacket(1, 0, 0));
655
656 // Send the response headers (but not the body).
657 SetResponse("200 OK", std::string());
658 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin));
659
660 // Since the headers have already arrived, this should return immediately.
661 ASSERT_EQ(OK, stream_->ReadResponseHeaders(callback_.callback()));
662 ASSERT_TRUE(response_.headers.get());
663 EXPECT_EQ(200, response_.headers->response_code());
664 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
665
666 // Send the response body.
667 const char kResponseBody[] = "Hello world!";
668 ProcessPacket(ConstructDataPacket(3, false, kFin, response_data_.length(),
669 kResponseBody));
670
671 // Since the body has already arrived, this should return immediately.
672 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
673 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
674 callback_.callback()));
675
676 EXPECT_TRUE(stream_->IsResponseBodyComplete());
677 EXPECT_TRUE(AtEof());
678}
679
[email protected]1e960032013-12-20 19:00:20680TEST_P(QuicHttpStreamTest, DestroyedEarly) {
681 SetRequest("GET", "/", DEFAULT_PRIORITY);
[email protected]92bf17c2014-03-03 21:14:03682 AddWrite(ConstructRequestHeadersPacket(1, kFin));
[email protected]c5e1aca2014-01-30 04:03:04683 AddWrite(ConstructAckAndRstStreamPacket(2));
[email protected]63534512012-12-23 18:49:00684 use_closing_stream_ = true;
685 Initialize();
686
687 request_.method = "GET";
688 request_.url = GURL("http://www.google.com/");
689
[email protected]262eec82013-03-19 21:01:36690 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
691 net_log_, callback_.callback()));
[email protected]63534512012-12-23 18:49:00692 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
[email protected]24e5bc52013-09-18 15:36:58693 callback_.callback()));
[email protected]63534512012-12-23 18:49:00694
695 // Ack the request.
[email protected]1e960032013-12-20 19:00:20696 ProcessPacket(ConstructAckPacket(1, 0, 0));
[email protected]63534512012-12-23 18:49:00697 EXPECT_EQ(ERR_IO_PENDING,
698 stream_->ReadResponseHeaders(callback_.callback()));
699
700 // Send the response with a body.
[email protected]1e960032013-12-20 19:00:20701 SetResponse("404 OK", "hello world!");
[email protected]63534512012-12-23 18:49:00702 // In the course of processing this packet, the QuicHttpStream close itself.
[email protected]92bf17c2014-03-03 21:14:03703 ProcessPacket(ConstructResponseHeadersPacket(2, kFin));
[email protected]63534512012-12-23 18:49:00704
705 EXPECT_TRUE(AtEof());
706}
707
[email protected]1e960032013-12-20 19:00:20708TEST_P(QuicHttpStreamTest, Priority) {
709 SetRequest("GET", "/", MEDIUM);
[email protected]92bf17c2014-03-03 21:14:03710 AddWrite(ConstructRequestHeadersPacket(1, kFin));
[email protected]c5e1aca2014-01-30 04:03:04711 AddWrite(ConstructAckAndRstStreamPacket(2));
[email protected]24e5bc52013-09-18 15:36:58712 use_closing_stream_ = true;
713 Initialize();
714
715 request_.method = "GET";
716 request_.url = GURL("http://www.google.com/");
717
718 EXPECT_EQ(OK, stream_->InitializeStream(&request_, MEDIUM,
719 net_log_, callback_.callback()));
720
721 // Check that priority is highest.
722 QuicReliableClientStream* reliable_stream =
723 QuicHttpStreamPeer::GetQuicReliableClientStream(stream_.get());
724 DCHECK(reliable_stream);
[email protected]9f0dcd4e2014-01-16 15:58:14725 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority,
[email protected]24e5bc52013-09-18 15:36:58726 reliable_stream->EffectivePriority());
727
728 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
729 callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:58730
731 // Check that priority has now dropped back to MEDIUM.
732 DCHECK_EQ(MEDIUM, ConvertQuicPriorityToRequestPriority(
733 reliable_stream->EffectivePriority()));
734
735 // Ack the request.
[email protected]1e960032013-12-20 19:00:20736 ProcessPacket(ConstructAckPacket(1, 0, 0));
[email protected]24e5bc52013-09-18 15:36:58737 EXPECT_EQ(ERR_IO_PENDING,
738 stream_->ReadResponseHeaders(callback_.callback()));
739
740 // Send the response with a body.
[email protected]1e960032013-12-20 19:00:20741 SetResponse("404 OK", "hello world!");
[email protected]24e5bc52013-09-18 15:36:58742 // In the course of processing this packet, the QuicHttpStream close itself.
[email protected]92bf17c2014-03-03 21:14:03743 ProcessPacket(ConstructResponseHeadersPacket(2, kFin));
[email protected]24e5bc52013-09-18 15:36:58744
745 EXPECT_TRUE(AtEof());
746}
747
[email protected]e1cca9a2013-09-20 17:14:44748// Regression test for http://crbug.com/294870
[email protected]1e960032013-12-20 19:00:20749TEST_P(QuicHttpStreamTest, CheckPriorityWithNoDelegate) {
750 SetRequest("GET", "/", MEDIUM);
[email protected]e1cca9a2013-09-20 17:14:44751 use_closing_stream_ = true;
[email protected]459a7402014-02-10 12:58:52752
[email protected]08da9adb2014-04-24 08:33:31753 AddWrite(ConstructRstStreamPacket(1));
[email protected]459a7402014-02-10 12:58:52754
[email protected]e1cca9a2013-09-20 17:14:44755 Initialize();
756
757 request_.method = "GET";
758 request_.url = GURL("http://www.google.com/");
759
760 EXPECT_EQ(OK, stream_->InitializeStream(&request_, MEDIUM,
761 net_log_, callback_.callback()));
762
763 // Check that priority is highest.
764 QuicReliableClientStream* reliable_stream =
765 QuicHttpStreamPeer::GetQuicReliableClientStream(stream_.get());
766 DCHECK(reliable_stream);
767 QuicReliableClientStream::Delegate* delegate = reliable_stream->GetDelegate();
768 DCHECK(delegate);
[email protected]9f0dcd4e2014-01-16 15:58:14769 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority,
[email protected]e1cca9a2013-09-20 17:14:44770 reliable_stream->EffectivePriority());
771
rtennetibe635732014-10-02 22:51:42772 // Set Delegate to nullptr and make sure EffectivePriority returns highest
[email protected]e1cca9a2013-09-20 17:14:44773 // priority.
rtennetibe635732014-10-02 22:51:42774 reliable_stream->SetDelegate(nullptr);
[email protected]9f0dcd4e2014-01-16 15:58:14775 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority,
[email protected]e1cca9a2013-09-20 17:14:44776 reliable_stream->EffectivePriority());
777 reliable_stream->SetDelegate(delegate);
778}
779
[email protected]f702d572012-12-04 15:56:20780} // namespace test
[email protected]f702d572012-12-04 15:56:20781} // namespace net