blob: 26f16eef7112efcbfd011fd60a244cc59d19216c [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
sclittle1edeeb22015-09-02 20:46:107#include <stdint.h>
8
danakjad1777e2016-04-16 00:56:429#include <memory>
bnc086b39e12016-06-24 13:05:2610#include <utility>
[email protected]f702d572012-12-04 15:56:2011
danakjad1777e2016-04-16 00:56:4212#include "base/memory/ptr_util.h"
fdoray92e35a72016-06-10 15:54:5513#include "base/run_loop.h"
xunjieli188bd402016-03-12 00:17:2514#include "base/strings/string_number_conversions.h"
gabf767595f2016-05-11 18:50:3515#include "base/threading/thread_task_runner_handle.h"
mmenkecbc2b712014-10-09 20:29:0716#include "net/base/chunked_upload_data_stream.h"
17#include "net/base/elements_upload_data_stream.h"
[email protected]f702d572012-12-04 15:56:2018#include "net/base/net_errors.h"
19#include "net/base/test_completion_callback.h"
[email protected]b2d26cfd2012-12-11 10:36:0620#include "net/base/upload_bytes_element_reader.h"
[email protected]f702d572012-12-04 15:56:2021#include "net/http/http_response_headers.h"
[email protected]5db452202014-08-19 05:22:1522#include "net/http/transport_security_state.h"
xunjieli5fafe142016-03-23 23:32:5423#include "net/log/test_net_log.h"
24#include "net/log/test_net_log_util.h"
[email protected]fee17f72013-02-03 07:47:4125#include "net/quic/congestion_control/send_algorithm_interface.h"
[email protected]e8ff26842013-03-22 21:02:0526#include "net/quic/crypto/crypto_protocol.h"
rch03b7a202016-02-05 00:54:2027#include "net/quic/crypto/proof_verifier_chromium.h"
[email protected]4df69842013-02-27 06:32:1628#include "net/quic/crypto/quic_decrypter.h"
29#include "net/quic/crypto/quic_encrypter.h"
[email protected]17bf15c2014-03-14 10:08:0430#include "net/quic/crypto/quic_server_info.h"
rch16c74d1d2016-04-22 06:14:0731#include "net/quic/quic_chromium_alarm_factory.h"
rch12fef552016-01-15 16:26:3132#include "net/quic/quic_chromium_connection_helper.h"
rcha02807b42016-01-29 21:56:1533#include "net/quic/quic_chromium_packet_reader.h"
34#include "net/quic/quic_chromium_packet_writer.h"
[email protected]f702d572012-12-04 15:56:2035#include "net/quic/quic_connection.h"
[email protected]24e5bc52013-09-18 15:36:5836#include "net/quic/quic_http_utils.h"
[email protected]9f0dcd4e2014-01-16 15:58:1437#include "net/quic/quic_write_blocked_list.h"
[email protected]3e7dca62013-09-10 16:14:2338#include "net/quic/spdy_utils.h"
rch1fe2eeb2015-10-26 14:45:5739#include "net/quic/test_tools/crypto_test_utils.h"
[email protected]f702d572012-12-04 15:56:2040#include "net/quic/test_tools/mock_clock.h"
[email protected]e8ff26842013-03-22 21:02:0541#include "net/quic/test_tools/mock_crypto_client_stream_factory.h"
[email protected]9db443912013-02-25 05:27:0342#include "net/quic/test_tools/mock_random.h"
[email protected]b1f287d2012-12-22 17:25:3943#include "net/quic/test_tools/quic_connection_peer.h"
[email protected]1e960032013-12-20 19:00:2044#include "net/quic/test_tools/quic_test_packet_maker.h"
[email protected]f702d572012-12-04 15:56:2045#include "net/quic/test_tools/quic_test_utils.h"
46#include "net/quic/test_tools/test_task_runner.h"
tbansalca83c002016-04-28 20:56:2847#include "net/socket/socket_performance_watcher.h"
[email protected]f702d572012-12-04 15:56:2048#include "net/socket/socket_test_util.h"
[email protected]6cca996b2013-01-25 07:43:3649#include "net/spdy/spdy_frame_builder.h"
50#include "net/spdy/spdy_framer.h"
51#include "net/spdy/spdy_http_utils.h"
52#include "net/spdy/spdy_protocol.h"
rch03b7a202016-02-05 00:54:2053#include "net/test/cert_test_util.h"
rsleevia69c79a2016-06-22 03:28:4354#include "net/test/test_data_directory.h"
[email protected]f702d572012-12-04 15:56:2055#include "testing/gmock/include/gmock/gmock.h"
56#include "testing/gtest/include/gtest/gtest.h"
57
bnc614a92d32016-04-04 13:56:0758using std::string;
[email protected]f702d572012-12-04 15:56:2059using testing::_;
[email protected]06ff5152013-08-29 01:03:0560using testing::AnyNumber;
61using testing::Return;
[email protected]f702d572012-12-04 15:56:2062
63namespace net {
[email protected]f702d572012-12-04 15:56:2064namespace test {
[email protected]f702d572012-12-04 15:56:2065namespace {
66
[email protected]16ba7742014-08-22 00:57:2567const char kUploadData[] = "Really nifty data!";
rch9ae5b3b2016-02-11 00:36:2968const char kDefaultServerHostName[] = "www.example.org";
Avi Drissman13fc8932015-12-20 04:40:4669const uint16_t kDefaultServerPort = 80;
[email protected]f702d572012-12-04 15:56:2070
71class TestQuicConnection : public QuicConnection {
72 public:
[email protected]1e960032013-12-20 19:00:2073 TestQuicConnection(const QuicVersionVector& versions,
[email protected]3aa9ca72014-02-27 19:39:4374 QuicConnectionId connection_id,
[email protected]f702d572012-12-04 15:56:2075 IPEndPoint address,
rch12fef552016-01-15 16:26:3176 QuicChromiumConnectionHelper* helper,
rch16c74d1d2016-04-22 06:14:0777 QuicChromiumAlarmFactory* alarm_factory,
jdorfman90d185f32016-01-15 13:22:4778 QuicPacketWriter* writer)
[email protected]66cd2d62014-08-01 18:42:3979 : QuicConnection(connection_id,
80 address,
81 helper,
rch16c74d1d2016-04-22 06:14:0782 alarm_factory,
jdorfman90d185f32016-01-15 13:22:4783 writer,
rtenneti6f48aa92015-03-16 02:18:4884 true /* owns_writer */,
85 Perspective::IS_CLIENT,
rtenneti6f48aa92015-03-16 02:18:4886 versions) {}
[email protected]f702d572012-12-04 15:56:2087
[email protected]fee17f72013-02-03 07:47:4188 void SetSendAlgorithm(SendAlgorithmInterface* send_algorithm) {
89 QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
[email protected]f702d572012-12-04 15:56:2090 }
91};
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:
ckrasic4f9d88d2015-07-22 22:23:1697 explicit AutoClosingStream(
98 const base::WeakPtr<QuicChromiumClientSession>& session)
99 : QuicHttpStream(session) {}
[email protected]63534512012-12-23 18:49:00100
sclittlec4dc1a32015-09-24 00:15:45101 void OnHeadersAvailable(const SpdyHeaderBlock& headers,
102 size_t frame_len) override {
[email protected]63534512012-12-23 18:49:00103 Close(false);
[email protected]63534512012-12-23 18:49:00104 }
rchb27683c2015-07-29 23:53:50105
106 void OnDataAvailable() override { Close(false); }
[email protected]63534512012-12-23 18:49:00107};
108
maksim.sisov84e20c92016-06-23 08:49:34109// UploadDataStream that always returns errors on data read.
110class ReadErrorUploadDataStream : public UploadDataStream {
111 public:
112 enum class FailureMode { SYNC, ASYNC };
113
114 explicit ReadErrorUploadDataStream(FailureMode mode)
115 : UploadDataStream(true, 0), async_(mode), weak_factory_(this) {}
116 ~ReadErrorUploadDataStream() override {}
117
118 private:
119 void CompleteRead() { UploadDataStream::OnReadCompleted(ERR_FAILED); }
120
121 // UploadDataStream implementation:
122 int InitInternal() override { return OK; }
123
124 int ReadInternal(IOBuffer* buf, int buf_len) override {
125 if (async_ == FailureMode::ASYNC) {
126 base::ThreadTaskRunnerHandle::Get()->PostTask(
127 FROM_HERE, base::Bind(&ReadErrorUploadDataStream::CompleteRead,
128 weak_factory_.GetWeakPtr()));
129 return ERR_IO_PENDING;
130 }
131 return ERR_FAILED;
132 }
133
134 void ResetInternal() override {}
135
136 const FailureMode async_;
137
138 base::WeakPtrFactory<ReadErrorUploadDataStream> weak_factory_;
139
140 DISALLOW_COPY_AND_ASSIGN(ReadErrorUploadDataStream);
141};
142
[email protected]f702d572012-12-04 15:56:20143} // namespace
144
[email protected]24e5bc52013-09-18 15:36:58145class QuicHttpStreamPeer {
146 public:
rch12fef552016-01-15 16:26:31147 static QuicChromiumClientStream* GetQuicChromiumClientStream(
[email protected]24e5bc52013-09-18 15:36:58148 QuicHttpStream* stream) {
149 return stream->stream_;
150 }
zhongyica364fbb2015-12-12 03:39:12151
152 static bool WasHandshakeConfirmed(QuicHttpStream* stream) {
153 return stream->was_handshake_confirmed_;
154 }
155
156 static void SetHandshakeConfirmed(QuicHttpStream* stream, bool confirmed) {
157 stream->was_handshake_confirmed_ = confirmed;
158 }
[email protected]24e5bc52013-09-18 15:36:58159};
160
[email protected]1e960032013-12-20 19:00:20161class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
[email protected]f702d572012-12-04 15:56:20162 protected:
[email protected]1e960032013-12-20 19:00:20163 static const bool kFin = true;
164 static const bool kIncludeVersion = true;
165 static const bool kIncludeCongestionFeedback = true;
166
[email protected]f702d572012-12-04 15:56:20167 // Holds a packet to be written to the wire, and the IO mode that should
168 // be used by the mock socket when performing the write.
169 struct PacketToWrite {
jokulikf2bd55c52016-03-24 22:35:30170 PacketToWrite(IoMode mode, QuicReceivedPacket* packet)
rjshaded5ced072015-12-18 19:26:02171 : mode(mode), packet(packet) {}
rtenneti15656ae2016-01-23 03:05:03172 PacketToWrite(IoMode mode, int rv) : mode(mode), packet(nullptr), rv(rv) {}
[email protected]f702d572012-12-04 15:56:20173 IoMode mode;
jokulikf2bd55c52016-03-24 22:35:30174 QuicReceivedPacket* packet;
rtenneti15656ae2016-01-23 03:05:03175 int rv;
[email protected]f702d572012-12-04 15:56:20176 };
177
178 QuicHttpStreamTest()
xunjieli5fafe142016-03-23 23:32:54179 : use_closing_stream_(false),
rch1fe2eeb2015-10-26 14:45:57180 crypto_config_(CryptoTestUtils::ProofVerifierForTesting()),
[email protected]f702d572012-12-04 15:56:20181 read_buffer_(new IOBufferWithSize(4096)),
ckrasic3865ee0f2016-02-29 22:04:56182 promise_id_(kServerDataStreamId1),
[email protected]66ae5962014-05-22 11:13:05183 stream_id_(kClientDataStreamId1),
ckrasic3865ee0f2016-02-29 22:04:56184 connection_id_(2),
alyssar2adf3ac2016-05-03 17:12:58185 client_maker_(GetParam(),
186 connection_id_,
187 &clock_,
188 kDefaultServerHostName,
189 Perspective::IS_CLIENT),
190 server_maker_(GetParam(),
191 connection_id_,
192 &clock_,
193 kDefaultServerHostName,
194 Perspective::IS_SERVER),
ckrasic3865ee0f2016-02-29 22:04:56195 random_generator_(0),
196 response_offset_(0) {
martijn21968ea2016-02-24 18:46:20197 IPAddress ip(192, 0, 2, 33);
[email protected]f702d572012-12-04 15:56:20198 peer_addr_ = IPEndPoint(ip, 443);
199 self_addr_ = IPEndPoint(ip, 8435);
rtenneti4b06ae72014-08-26 03:43:43200 clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(20));
[email protected]f702d572012-12-04 15:56:20201 }
202
203 ~QuicHttpStreamTest() {
rtenneti85dcfac22015-03-27 20:22:19204 session_->CloseSessionOnError(ERR_ABORTED, QUIC_INTERNAL_ERROR);
[email protected]f702d572012-12-04 15:56:20205 for (size_t i = 0; i < writes_.size(); i++) {
206 delete writes_[i].packet;
207 }
208 }
209
210 // Adds a packet to the list of expected writes.
danakjad1777e2016-04-16 00:56:42211 void AddWrite(std::unique_ptr<QuicReceivedPacket> packet) {
[email protected]1e960032013-12-20 19:00:20212 writes_.push_back(PacketToWrite(SYNCHRONOUS, packet.release()));
[email protected]f702d572012-12-04 15:56:20213 }
214
rtenneti15656ae2016-01-23 03:05:03215 void AddWrite(IoMode mode, int rv) {
216 writes_.push_back(PacketToWrite(mode, rv));
217 }
218
[email protected]f702d572012-12-04 15:56:20219 // Returns the packet to be written at position |pos|.
jokulikf2bd55c52016-03-24 22:35:30220 QuicReceivedPacket* GetWrite(size_t pos) { return writes_[pos].packet; }
[email protected]f702d572012-12-04 15:56:20221
222 bool AtEof() {
rch37de576c2015-05-17 20:28:17223 return socket_data_->AllReadDataConsumed() &&
224 socket_data_->AllWriteDataConsumed();
[email protected]f702d572012-12-04 15:56:20225 }
226
danakjad1777e2016-04-16 00:56:42227 void ProcessPacket(std::unique_ptr<QuicReceivedPacket> packet) {
[email protected]1e960032013-12-20 19:00:20228 connection_->ProcessUdpPacket(self_addr_, peer_addr_, *packet);
[email protected]f702d572012-12-04 15:56:20229 }
230
231 // Configures the test fixture to use the list of expected writes.
232 void Initialize() {
233 mock_writes_.reset(new MockWrite[writes_.size()]);
234 for (size_t i = 0; i < writes_.size(); i++) {
rtenneti15656ae2016-01-23 03:05:03235 if (writes_[i].packet == nullptr) {
236 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].rv, i);
237 } else {
238 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].packet->data(),
239 writes_[i].packet->length());
240 }
bnc614a92d32016-04-04 13:56:07241 }
[email protected]f702d572012-12-04 15:56:20242
rtennetibe635732014-10-02 22:51:42243 socket_data_.reset(new StaticSocketDataProvider(
244 nullptr, 0, mock_writes_.get(), writes_.size()));
[email protected]f702d572012-12-04 15:56:20245
danakjad1777e2016-04-16 00:56:42246 std::unique_ptr<MockUDPClientSocket> socket(new MockUDPClientSocket(
xunjielib53b38c2016-03-24 15:54:36247 socket_data_.get(), net_log_.bound().net_log()));
[email protected]e13201d82012-12-12 05:00:32248 socket->Connect(peer_addr_);
[email protected]f702d572012-12-04 15:56:20249 runner_ = new TestTaskRunner(&clock_);
[email protected]fee17f72013-02-03 07:47:41250 send_algorithm_ = new MockSendAlgorithm();
rch7dd15702015-07-01 18:57:57251 EXPECT_CALL(*send_algorithm_, InRecovery()).WillRepeatedly(Return(false));
252 EXPECT_CALL(*send_algorithm_, InSlowStart()).WillRepeatedly(Return(false));
rjshaded5ced072015-12-18 19:26:02253 EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
254 .WillRepeatedly(Return(true));
rtenneti44f4a2e2015-08-07 14:00:07255 EXPECT_CALL(*send_algorithm_, RetransmissionDelay())
256 .WillRepeatedly(Return(QuicTime::Delta::Zero()));
257 EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
258 .WillRepeatedly(Return(kMaxPacketSize));
jokulik0e0a00c32016-06-13 21:51:58259 EXPECT_CALL(*send_algorithm_, PacingRate(_))
rtenneti44f4a2e2015-08-07 14:00:07260 .WillRepeatedly(Return(QuicBandwidth::Zero()));
fnkf57804c2016-03-17 20:57:07261 EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
rtenneti44f4a2e2015-08-07 14:00:07262 .WillRepeatedly(Return(QuicTime::Delta::Zero()));
263 EXPECT_CALL(*send_algorithm_, BandwidthEstimate())
264 .WillRepeatedly(Return(QuicBandwidth::Zero()));
rch1e543ec2015-03-29 07:04:40265 EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(AnyNumber());
rch16c74d1d2016-04-22 06:14:07266 helper_.reset(
267 new QuicChromiumConnectionHelper(&clock_, &random_generator_));
268 alarm_factory_.reset(new QuicChromiumAlarmFactory(runner_.get(), &clock_));
269
270 connection_ =
271 new TestQuicConnection(SupportedVersions(GetParam()), connection_id_,
272 peer_addr_, helper_.get(), alarm_factory_.get(),
273 new QuicChromiumPacketWriter(socket.get()));
[email protected]f702d572012-12-04 15:56:20274 connection_->set_visitor(&visitor_);
[email protected]fee17f72013-02-03 07:47:41275 connection_->SetSendAlgorithm(send_algorithm_);
rch03b7a202016-02-05 00:54:20276
277 // Load a certificate that is valid for *.example.org
278 scoped_refptr<X509Certificate> test_cert(
279 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
280 EXPECT_TRUE(test_cert.get());
281
282 verify_details_.cert_verify_result.verified_cert = test_cert;
283 verify_details_.cert_verify_result.is_issued_by_known_root = true;
284 crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details_);
285
ckrasic4f9d88d2015-07-22 22:23:16286 session_.reset(new QuicChromiumClientSession(
xunjielib53b38c2016-03-24 15:54:36287 connection_, std::move(socket),
rtenneti1cd3b162015-09-29 02:58:28288 /*stream_factory=*/nullptr, &crypto_client_stream_factory_, &clock_,
bnc614a92d32016-04-04 13:56:07289 &transport_security_state_,
danakjad1777e2016-04-16 00:56:42290 base::WrapUnique(static_cast<QuicServerInfo*>(nullptr)),
bncb07c05532015-05-14 19:07:20291 QuicServerId(kDefaultServerHostName, kDefaultServerPort,
rch1fe2eeb2015-10-26 14:45:57292 PRIVACY_MODE_DISABLED),
rtenneti1cd3b162015-09-29 02:58:28293 kQuicYieldAfterPacketsRead,
294 QuicTime::Delta::FromMilliseconds(kQuicYieldAfterDurationMilliseconds),
rtennetia75df622015-06-21 23:59:50295 /*cert_verify_flags=*/0, DefaultQuicConfig(), &crypto_config_,
ckrasic244375a32016-02-04 21:21:22296 "CONNECTION_UNKNOWN", base::TimeTicks::Now(), &push_promise_index_,
tbansalfdf5665b2015-09-21 22:46:40297 base::ThreadTaskRunnerHandle::Get().get(),
xunjieli5fafe142016-03-23 23:32:54298 /*socket_performance_watcher=*/nullptr, net_log_.bound().net_log()));
rtennetid39bd762015-06-12 01:05:52299 session_->Initialize();
[email protected]ed3fc15d2013-03-08 18:37:44300 session_->GetCryptoStream()->CryptoConnect();
[email protected]8ba81212013-05-03 13:11:48301 EXPECT_TRUE(session_->IsCryptoHandshakeConfirmed());
rjshaded5ced072015-12-18 19:26:02302 stream_.reset(use_closing_stream_
303 ? new AutoClosingStream(session_->GetWeakPtr())
304 : new QuicHttpStream(session_->GetWeakPtr()));
ckrasic3865ee0f2016-02-29 22:04:56305
306 promised_stream_.reset(use_closing_stream_
307 ? new AutoClosingStream(session_->GetWeakPtr())
308 : new QuicHttpStream(session_->GetWeakPtr()));
309
310 push_promise_[":path"] = "/bar";
311 push_promise_[":authority"] = "www.example.org";
312 push_promise_[":version"] = "HTTP/1.1";
313 push_promise_[":method"] = "GET";
314 push_promise_[":scheme"] = "https";
315
316 promised_response_[":status"] = "200 OK";
317 promised_response_[":version"] = "HTTP/1.1";
318 promised_response_["content-type"] = "text/plain";
319
320 promise_url_ = SpdyUtils::GetUrlFromHeaderBlock(push_promise_);
321
322 serialized_push_promise_ =
323 SpdyUtils::SerializeUncompressedHeaders(push_promise_);
[email protected]6cca996b2013-01-25 07:43:36324 }
325
bnc614a92d32016-04-04 13:56:07326 void SetRequest(const string& method,
327 const string& path,
[email protected]1e960032013-12-20 19:00:20328 RequestPriority priority) {
alyssar2adf3ac2016-05-03 17:12:58329 request_headers_ = client_maker_.GetRequestHeaders(method, "http", path);
[email protected]6cca996b2013-01-25 07:43:36330 }
331
bnc614a92d32016-04-04 13:56:07332 void SetResponse(const string& status, const string& body) {
alyssar2adf3ac2016-05-03 17:12:58333 response_headers_ = server_maker_.GetResponseHeaders(status);
[email protected]92bf17c2014-03-03 21:14:03334 response_data_ = body;
[email protected]6cca996b2013-01-25 07:43:36335 }
[email protected]f702d572012-12-04 15:56:20336
danakjad1777e2016-04-16 00:56:42337 std::unique_ptr<QuicReceivedPacket> InnerConstructDataPacket(
ckrasic3865ee0f2016-02-29 22:04:56338 QuicPacketNumber packet_number,
339 QuicStreamId stream_id,
340 bool should_include_version,
341 bool fin,
342 QuicStreamOffset offset,
alyssar2adf3ac2016-05-03 17:12:58343 base::StringPiece data,
344 QuicTestPacketMaker* maker) {
345 return maker->MakeDataPacket(packet_number, stream_id,
ckrasic3865ee0f2016-02-29 22:04:56346 should_include_version, fin, offset, data);
347 }
348
alyssar2adf3ac2016-05-03 17:12:58349 std::unique_ptr<QuicReceivedPacket> ConstructClientDataPacket(
rtennetia004d332015-08-28 06:44:57350 QuicPacketNumber packet_number,
[email protected]e8ff26842013-03-22 21:02:05351 bool should_include_version,
[email protected]f702d572012-12-04 15:56:20352 bool fin,
353 QuicStreamOffset offset,
354 base::StringPiece data) {
ckrasic3865ee0f2016-02-29 22:04:56355 return InnerConstructDataPacket(packet_number, stream_id_,
alyssar2adf3ac2016-05-03 17:12:58356 should_include_version, fin, offset, data,
357 &client_maker_);
358 }
359
360 std::unique_ptr<QuicReceivedPacket> ConstructServerDataPacket(
361 QuicPacketNumber packet_number,
362 bool should_include_version,
363 bool fin,
364 QuicStreamOffset offset,
365 base::StringPiece data) {
366 return InnerConstructDataPacket(packet_number, stream_id_,
367 should_include_version, fin, offset, data,
368 &server_maker_);
ckrasic3865ee0f2016-02-29 22:04:56369 }
370
danakjad1777e2016-04-16 00:56:42371 std::unique_ptr<QuicReceivedPacket> InnerConstructRequestHeadersPacket(
ckrasic3865ee0f2016-02-29 22:04:56372 QuicPacketNumber packet_number,
373 QuicStreamId stream_id,
374 bool should_include_version,
375 bool fin,
376 RequestPriority request_priority,
377 size_t* spdy_headers_frame_length) {
378 SpdyPriority priority =
379 ConvertRequestPriorityToQuicPriority(request_priority);
alyssar2adf3ac2016-05-03 17:12:58380 return client_maker_.MakeRequestHeadersPacket(
ckrasic3865ee0f2016-02-29 22:04:56381 packet_number, stream_id, should_include_version, fin, priority,
bnc086b39e12016-06-24 13:05:26382 std::move(request_headers_), spdy_headers_frame_length);
[email protected]f702d572012-12-04 15:56:20383 }
384
danakjad1777e2016-04-16 00:56:42385 std::unique_ptr<QuicReceivedPacket> ConstructRequestHeadersPacket(
rtennetia004d332015-08-28 06:44:57386 QuicPacketNumber packet_number,
rtennetif4bdb542015-01-21 14:33:05387 bool fin,
sclittlec4dc1a32015-09-24 00:15:45388 RequestPriority request_priority,
389 size_t* spdy_headers_frame_length) {
ckrasic3865ee0f2016-02-29 22:04:56390 return InnerConstructRequestHeadersPacket(
391 packet_number, stream_id_, kIncludeVersion, fin, request_priority,
392 spdy_headers_frame_length);
393 }
394
danakjad1777e2016-04-16 00:56:42395 std::unique_ptr<QuicReceivedPacket> InnerConstructResponseHeadersPacket(
ckrasic3865ee0f2016-02-29 22:04:56396 QuicPacketNumber packet_number,
397 QuicStreamId stream_id,
398 bool fin,
399 size_t* spdy_headers_frame_length) {
alyssar2adf3ac2016-05-03 17:12:58400 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26401 packet_number, stream_id, !kIncludeVersion, fin,
402 std::move(response_headers_), spdy_headers_frame_length,
403 &response_offset_);
[email protected]1e960032013-12-20 19:00:20404 }
405
danakjad1777e2016-04-16 00:56:42406 std::unique_ptr<QuicReceivedPacket> ConstructResponseHeadersPacket(
rtennetia004d332015-08-28 06:44:57407 QuicPacketNumber packet_number,
sclittlec4dc1a32015-09-24 00:15:45408 bool fin,
409 size_t* spdy_headers_frame_length) {
ckrasic3865ee0f2016-02-29 22:04:56410 return InnerConstructResponseHeadersPacket(packet_number, stream_id_, fin,
411 spdy_headers_frame_length);
[email protected]1e960032013-12-20 19:00:20412 }
413
danakjad1777e2016-04-16 00:56:42414 std::unique_ptr<QuicReceivedPacket> ConstructResponseHeadersPacketWithOffset(
xunjieli34291fe12016-03-02 13:58:38415 QuicPacketNumber packet_number,
416 bool fin,
417 size_t* spdy_headers_frame_length,
418 QuicStreamOffset* offset) {
alyssar2adf3ac2016-05-03 17:12:58419 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26420 packet_number, stream_id_, !kIncludeVersion, fin,
421 std::move(response_headers_), spdy_headers_frame_length, offset);
xunjieli34291fe12016-03-02 13:58:38422 }
423
danakjad1777e2016-04-16 00:56:42424 std::unique_ptr<QuicReceivedPacket> ConstructResponseTrailersPacket(
xunjieli34291fe12016-03-02 13:58:38425 QuicPacketNumber packet_number,
426 bool fin,
bnc086b39e12016-06-24 13:05:26427 SpdyHeaderBlock trailers,
xunjieli34291fe12016-03-02 13:58:38428 size_t* spdy_headers_frame_length,
429 QuicStreamOffset* offset) {
alyssar2adf3ac2016-05-03 17:12:58430 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26431 packet_number, stream_id_, !kIncludeVersion, fin, std::move(trailers),
alyssar2adf3ac2016-05-03 17:12:58432 spdy_headers_frame_length, offset);
xunjieli34291fe12016-03-02 13:58:38433 }
434
alyssar2adf3ac2016-05-03 17:12:58435 std::unique_ptr<QuicReceivedPacket> ConstructClientRstStreamPacket(
rtennetia004d332015-08-28 06:44:57436 QuicPacketNumber packet_number) {
alyssar2adf3ac2016-05-03 17:12:58437 return client_maker_.MakeRstPacket(
rtennetia004d332015-08-28 06:44:57438 packet_number, true, stream_id_,
rtenneti4a5df262014-11-07 00:43:58439 AdjustErrorForVersion(QUIC_RST_ACKNOWLEDGEMENT, GetParam()));
[email protected]06ff5152013-08-29 01:03:05440 }
441
alyssar2adf3ac2016-05-03 17:12:58442 std::unique_ptr<QuicReceivedPacket> ConstructClientRstStreamCancelledPacket(
rtennetia004d332015-08-28 06:44:57443 QuicPacketNumber packet_number) {
alyssar2adf3ac2016-05-03 17:12:58444 return client_maker_.MakeRstPacket(packet_number, !kIncludeVersion,
445 stream_id_, QUIC_STREAM_CANCELLED);
rtenneti6bd660b2015-07-18 00:19:53446 }
447
alyssar2adf3ac2016-05-03 17:12:58448 std::unique_ptr<QuicReceivedPacket>
449 ConstructClientRstStreamVaryMismatchPacket(QuicPacketNumber packet_number) {
450 return client_maker_.MakeRstPacket(packet_number, !kIncludeVersion,
451 promise_id_, QUIC_PROMISE_VARY_MISMATCH);
ckrasic3865ee0f2016-02-29 22:04:56452 }
453
danakjad1777e2016-04-16 00:56:42454 std::unique_ptr<QuicReceivedPacket> ConstructAckAndRstStreamPacket(
xunjieli34291fe12016-03-02 13:58:38455 QuicPacketNumber packet_number,
456 QuicPacketNumber largest_received,
457 QuicPacketNumber ack_least_unacked,
458 QuicPacketNumber stop_least_unacked) {
alyssar2adf3ac2016-05-03 17:12:58459 return client_maker_.MakeAckAndRstPacket(
xunjieli34291fe12016-03-02 13:58:38460 packet_number, !kIncludeVersion, stream_id_, QUIC_STREAM_CANCELLED,
461 largest_received, ack_least_unacked, stop_least_unacked,
462 !kIncludeCongestionFeedback);
463 }
464
maksim.sisov84e20c92016-06-23 08:49:34465 std::unique_ptr<QuicReceivedPacket> ConstructClientRstStreamErrorPacket(
466 QuicPacketNumber packet_number,
467 bool include_version) {
468 return client_maker_.MakeRstPacket(packet_number, include_version,
469 stream_id_,
470 QUIC_ERROR_PROCESSING_STREAM);
471 }
472
danakjad1777e2016-04-16 00:56:42473 std::unique_ptr<QuicReceivedPacket> ConstructAckAndRstStreamPacket(
rtennetia004d332015-08-28 06:44:57474 QuicPacketNumber packet_number) {
xunjieli34291fe12016-03-02 13:58:38475 return ConstructAckAndRstStreamPacket(packet_number, 2, 1, 1);
[email protected]c5e1aca2014-01-30 04:03:04476 }
477
alyssar2adf3ac2016-05-03 17:12:58478 std::unique_ptr<QuicReceivedPacket> ConstructClientAckPacket(
rtennetia004d332015-08-28 06:44:57479 QuicPacketNumber packet_number,
480 QuicPacketNumber largest_received,
481 QuicPacketNumber least_unacked) {
alyssar2adf3ac2016-05-03 17:12:58482 return client_maker_.MakeAckPacket(packet_number, largest_received,
483 least_unacked,
484 !kIncludeCongestionFeedback);
485 }
486
487 std::unique_ptr<QuicReceivedPacket> ConstructServerAckPacket(
488 QuicPacketNumber packet_number,
489 QuicPacketNumber largest_received,
490 QuicPacketNumber least_unacked) {
491 return server_maker_.MakeAckPacket(packet_number, largest_received,
492 least_unacked,
493 !kIncludeCongestionFeedback);
[email protected]63534512012-12-23 18:49:00494 }
495
ckrasic3865ee0f2016-02-29 22:04:56496 void ReceivePromise(QuicStreamId id) {
497 QuicChromiumClientStream* stream =
498 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
499 stream->OnStreamHeaders(serialized_push_promise_);
500
501 stream->OnPromiseHeadersComplete(id, serialized_push_promise_.size());
502 }
503
xunjieli5fafe142016-03-23 23:32:54504 BoundTestNetLog net_log_;
[email protected]63534512012-12-23 18:49:00505 bool use_closing_stream_;
[email protected]fee17f72013-02-03 07:47:41506 MockSendAlgorithm* send_algorithm_;
[email protected]f702d572012-12-04 15:56:20507 scoped_refptr<TestTaskRunner> runner_;
danakjad1777e2016-04-16 00:56:42508 std::unique_ptr<MockWrite[]> mock_writes_;
[email protected]f702d572012-12-04 15:56:20509 MockClock clock_;
510 TestQuicConnection* connection_;
danakjad1777e2016-04-16 00:56:42511 std::unique_ptr<QuicChromiumConnectionHelper> helper_;
rch16c74d1d2016-04-22 06:14:07512 std::unique_ptr<QuicChromiumAlarmFactory> alarm_factory_;
ckrasica7fd1242016-05-14 20:36:01513 testing::StrictMock<MockQuicConnectionVisitor> visitor_;
danakjad1777e2016-04-16 00:56:42514 std::unique_ptr<QuicHttpStream> stream_;
[email protected]5db452202014-08-19 05:22:15515 TransportSecurityState transport_security_state_;
danakjad1777e2016-04-16 00:56:42516 std::unique_ptr<QuicChromiumClientSession> session_;
[email protected]ef95114d2013-04-17 17:57:01517 QuicCryptoClientConfig crypto_config_;
[email protected]f702d572012-12-04 15:56:20518 TestCompletionCallback callback_;
519 HttpRequestInfo request_;
520 HttpRequestHeaders headers_;
521 HttpResponseInfo response_;
522 scoped_refptr<IOBufferWithSize> read_buffer_;
[email protected]1e960032013-12-20 19:00:20523 SpdyHeaderBlock request_headers_;
524 SpdyHeaderBlock response_headers_;
bnc614a92d32016-04-04 13:56:07525 string request_data_;
526 string response_data_;
ckrasic244375a32016-02-04 21:21:22527 QuicClientPushPromiseIndex push_promise_index_;
[email protected]f702d572012-12-04 15:56:20528
ckrasic3865ee0f2016-02-29 22:04:56529 // For server push testing
danakjad1777e2016-04-16 00:56:42530 std::unique_ptr<QuicHttpStream> promised_stream_;
ckrasic3865ee0f2016-02-29 22:04:56531 SpdyHeaderBlock push_promise_;
532 SpdyHeaderBlock promised_response_;
533 const QuicStreamId promise_id_;
534 string promise_url_;
535 string serialized_push_promise_;
536 const QuicStreamId stream_id_;
537
[email protected]3aa9ca72014-02-27 19:39:43538 const QuicConnectionId connection_id_;
alyssar2adf3ac2016-05-03 17:12:58539 QuicTestPacketMaker client_maker_;
540 QuicTestPacketMaker server_maker_;
[email protected]f702d572012-12-04 15:56:20541 IPEndPoint self_addr_;
542 IPEndPoint peer_addr_;
[email protected]457d6952013-12-13 09:24:58543 MockRandom random_generator_;
rch03b7a202016-02-05 00:54:20544 ProofVerifyDetailsChromium verify_details_;
[email protected]e8ff26842013-03-22 21:02:05545 MockCryptoClientStreamFactory crypto_client_stream_factory_;
danakjad1777e2016-04-16 00:56:42546 std::unique_ptr<StaticSocketDataProvider> socket_data_;
[email protected]f702d572012-12-04 15:56:20547 std::vector<PacketToWrite> writes_;
ckrasic3865ee0f2016-02-29 22:04:56548 QuicStreamOffset response_offset_;
[email protected]f702d572012-12-04 15:56:20549};
550
rjshaded5ced072015-12-18 19:26:02551INSTANTIATE_TEST_CASE_P(Version,
552 QuicHttpStreamTest,
[email protected]1e960032013-12-20 19:00:20553 ::testing::ValuesIn(QuicSupportedVersions()));
554
555TEST_P(QuicHttpStreamTest, RenewStreamForAuth) {
[email protected]ed3fc15d2013-03-08 18:37:44556 Initialize();
rtennetibe635732014-10-02 22:51:42557 EXPECT_EQ(nullptr, stream_->RenewStreamForAuth());
[email protected]f702d572012-12-04 15:56:20558}
559
mmenkebd84c392015-09-02 14:12:34560TEST_P(QuicHttpStreamTest, CanReuseConnection) {
[email protected]ed3fc15d2013-03-08 18:37:44561 Initialize();
mmenkebd84c392015-09-02 14:12:34562 EXPECT_FALSE(stream_->CanReuseConnection());
[email protected]f702d572012-12-04 15:56:20563}
564
jri231c2972016-03-08 19:50:11565TEST_P(QuicHttpStreamTest, DisableConnectionMigrationForStream) {
566 request_.load_flags |= LOAD_DISABLE_CONNECTION_MIGRATION;
567 Initialize();
xunjieli5fafe142016-03-23 23:32:54568 EXPECT_EQ(OK,
569 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
570 net_log_.bound(), callback_.callback()));
jri231c2972016-03-08 19:50:11571 QuicChromiumClientStream* client_stream =
572 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
573 EXPECT_FALSE(client_stream->can_migrate());
574}
575
[email protected]1e960032013-12-20 19:00:20576TEST_P(QuicHttpStreamTest, GetRequest) {
577 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:45578 size_t spdy_request_header_frame_length;
579 AddWrite(ConstructRequestHeadersPacket(1, kFin, DEFAULT_PRIORITY,
580 &spdy_request_header_frame_length));
[email protected]f702d572012-12-04 15:56:20581 Initialize();
582
583 request_.method = "GET";
rch9ae5b3b2016-02-11 00:36:29584 request_.url = GURL("http://www.example.org/");
[email protected]f702d572012-12-04 15:56:20585
xunjieli5fafe142016-03-23 23:32:54586 EXPECT_EQ(OK,
587 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
588 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:02589 EXPECT_EQ(OK,
590 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20591
592 // Ack the request.
alyssar2adf3ac2016-05-03 17:12:58593 ProcessPacket(ConstructServerAckPacket(1, 0, 0));
[email protected]f702d572012-12-04 15:56:20594
rjshaded5ced072015-12-18 19:26:02595 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadResponseHeaders(callback_.callback()));
[email protected]f702d572012-12-04 15:56:20596
bnc614a92d32016-04-04 13:56:07597 SetResponse("404 Not Found", string());
sclittlec4dc1a32015-09-24 00:15:45598 size_t spdy_response_header_frame_length;
599 ProcessPacket(ConstructResponseHeadersPacket(
600 2, kFin, &spdy_response_header_frame_length));
[email protected]f702d572012-12-04 15:56:20601
602 // Now that the headers have been processed, the callback will return.
603 EXPECT_EQ(OK, callback_.WaitForResult());
[email protected]cadac622013-06-11 16:46:36604 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:20605 EXPECT_EQ(404, response_.headers->response_code());
606 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
[email protected]6ed67432014-06-24 01:53:53607 EXPECT_FALSE(response_.response_time.is_null());
608 EXPECT_FALSE(response_.request_time.is_null());
[email protected]f702d572012-12-04 15:56:20609
610 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:02611 EXPECT_EQ(0,
612 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
613 callback_.callback()));
[email protected]f702d572012-12-04 15:56:20614 EXPECT_TRUE(stream_->IsResponseBodyComplete());
615 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:10616
617 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:45618 // headers and payload.
619 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
620 stream_->GetTotalSentBytes());
621 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length),
622 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:20623}
624
xunjieli34291fe12016-03-02 13:58:38625// QuicHttpStream does not currently support trailers. It should ignore
626// trailers upon receiving them.
627TEST_P(QuicHttpStreamTest, GetRequestWithTrailers) {
628 SetRequest("GET", "/", DEFAULT_PRIORITY);
629 size_t spdy_request_header_frame_length;
630 AddWrite(ConstructRequestHeadersPacket(1, kFin, DEFAULT_PRIORITY,
631 &spdy_request_header_frame_length));
alyssar2adf3ac2016-05-03 17:12:58632 AddWrite(ConstructClientAckPacket(2, 3, 1)); // Ack the data packet.
xunjieli34291fe12016-03-02 13:58:38633
634 Initialize();
635
636 request_.method = "GET";
637 request_.url = GURL("http://www.example.org/");
638
xunjieli5fafe142016-03-23 23:32:54639 EXPECT_EQ(OK,
640 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
641 net_log_.bound(), callback_.callback()));
642
xunjieli34291fe12016-03-02 13:58:38643 EXPECT_EQ(OK,
644 stream_->SendRequest(headers_, &response_, callback_.callback()));
xunjieli34291fe12016-03-02 13:58:38645 // Ack the request.
alyssar2adf3ac2016-05-03 17:12:58646 ProcessPacket(ConstructServerAckPacket(1, 0, 0));
xunjieli34291fe12016-03-02 13:58:38647
648 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadResponseHeaders(callback_.callback()));
649
bnc614a92d32016-04-04 13:56:07650 SetResponse("200 OK", string());
xunjieli34291fe12016-03-02 13:58:38651
652 // Send the response headers.
653 size_t spdy_response_header_frame_length;
654 QuicStreamOffset offset = 0;
655 ProcessPacket(ConstructResponseHeadersPacketWithOffset(
656 2, !kFin, &spdy_response_header_frame_length, &offset));
657 // Now that the headers have been processed, the callback will return.
658 EXPECT_EQ(OK, callback_.WaitForResult());
659 ASSERT_TRUE(response_.headers.get());
660 EXPECT_EQ(200, response_.headers->response_code());
661 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
662 EXPECT_FALSE(response_.response_time.is_null());
663 EXPECT_FALSE(response_.request_time.is_null());
664
665 // Send the response body.
666 const char kResponseBody[] = "Hello world!";
667 ProcessPacket(
alyssar2adf3ac2016-05-03 17:12:58668 ConstructServerDataPacket(3, false, !kFin, /*offset=*/0, kResponseBody));
xunjieli34291fe12016-03-02 13:58:38669 SpdyHeaderBlock trailers;
670 size_t spdy_trailers_frame_length;
671 trailers["foo"] = "bar";
xunjieli188bd402016-03-12 00:17:25672 trailers[kFinalOffsetHeaderKey] = base::IntToString(strlen(kResponseBody));
xunjieli34291fe12016-03-02 13:58:38673 ProcessPacket(ConstructResponseTrailersPacket(
bnc086b39e12016-06-24 13:05:26674 4, kFin, std::move(trailers), &spdy_trailers_frame_length, &offset));
xunjieli34291fe12016-03-02 13:58:38675
676 // Make sure trailers are processed.
fdoray92e35a72016-06-10 15:54:55677 base::RunLoop().RunUntilIdle();
xunjieli34291fe12016-03-02 13:58:38678
679 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
680 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
681 callback_.callback()));
682 EXPECT_TRUE(stream_->IsResponseBodyComplete());
683
684 EXPECT_EQ(OK,
685 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
686 callback_.callback()));
687
688 EXPECT_TRUE(stream_->IsResponseBodyComplete());
689 EXPECT_TRUE(AtEof());
690
691 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
692 // headers and payload.
693 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
694 stream_->GetTotalSentBytes());
695 EXPECT_EQ(
696 static_cast<int64_t>(spdy_response_header_frame_length +
697 strlen(kResponseBody) + +spdy_trailers_frame_length),
698 stream_->GetTotalReceivedBytes());
xunjieli5fafe142016-03-23 23:32:54699 // Check that NetLog was filled as expected.
700 TestNetLogEntry::List entries;
701 net_log_.GetEntries(&entries);
702 size_t pos = ExpectLogContainsSomewhere(
703 entries, /*min_offset=*/0,
704 NetLog::TYPE_QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
705 NetLog::PHASE_NONE);
706 pos = ExpectLogContainsSomewhere(
707 entries, /*min_offset=*/pos,
708 NetLog::TYPE_QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
709 NetLog::PHASE_NONE);
710 ExpectLogContainsSomewhere(
711 entries, /*min_offset=*/pos,
712 NetLog::TYPE_QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
713 NetLog::PHASE_NONE);
xunjieli34291fe12016-03-02 13:58:38714}
715
[email protected]3e7dca62013-09-10 16:14:23716// Regression test for http://crbug.com/288128
[email protected]1e960032013-12-20 19:00:20717TEST_P(QuicHttpStreamTest, GetRequestLargeResponse) {
718 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:45719 size_t spdy_request_headers_frame_length;
720 AddWrite(ConstructRequestHeadersPacket(1, kFin, DEFAULT_PRIORITY,
721 &spdy_request_headers_frame_length));
[email protected]3e7dca62013-09-10 16:14:23722 Initialize();
723
724 request_.method = "GET";
rch9ae5b3b2016-02-11 00:36:29725 request_.url = GURL("http://www.example.org/");
[email protected]3e7dca62013-09-10 16:14:23726
xunjieli5fafe142016-03-23 23:32:54727 EXPECT_EQ(OK,
728 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
729 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:02730 EXPECT_EQ(OK,
731 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:23732
733 // Ack the request.
alyssar2adf3ac2016-05-03 17:12:58734 ProcessPacket(ConstructServerAckPacket(1, 0, 0));
[email protected]3e7dca62013-09-10 16:14:23735
rjshaded5ced072015-12-18 19:26:02736 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadResponseHeaders(callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:23737
bnc086b39e12016-06-24 13:05:26738 response_headers_[":status"] = "200 OK";
739 response_headers_[":version"] = "HTTP/1.1";
740 response_headers_["content-type"] = "text/plain";
741 response_headers_["big6"] = string(1000, 'x'); // Lots of x's.
[email protected]3e7dca62013-09-10 16:14:23742
sclittlec4dc1a32015-09-24 00:15:45743 size_t spdy_response_headers_frame_length;
744 ProcessPacket(ConstructResponseHeadersPacket(
745 2, kFin, &spdy_response_headers_frame_length));
[email protected]3e7dca62013-09-10 16:14:23746
747 // Now that the headers have been processed, the callback will return.
748 EXPECT_EQ(OK, callback_.WaitForResult());
749 ASSERT_TRUE(response_.headers.get());
750 EXPECT_EQ(200, response_.headers->response_code());
751 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
752
753 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:02754 EXPECT_EQ(0,
755 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
756 callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:23757 EXPECT_TRUE(stream_->IsResponseBodyComplete());
758 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:10759
760 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:45761 // headers and payload.
762 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
763 stream_->GetTotalSentBytes());
764 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length),
765 stream_->GetTotalReceivedBytes());
[email protected]3e7dca62013-09-10 16:14:23766}
767
rchf9f103cbc2014-08-30 05:28:04768// Regression test for http://crbug.com/409101
769TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendRequest) {
770 SetRequest("GET", "/", DEFAULT_PRIORITY);
771 Initialize();
772
773 request_.method = "GET";
rch9ae5b3b2016-02-11 00:36:29774 request_.url = GURL("http://www.example.org/");
rchf9f103cbc2014-08-30 05:28:04775
xunjieli5fafe142016-03-23 23:32:54776 EXPECT_EQ(OK,
777 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
778 net_log_.bound(), callback_.callback()));
rchf9f103cbc2014-08-30 05:28:04779
jri78ec06a2016-03-31 18:19:40780 session_->connection()->CloseConnection(
781 QUIC_NO_ERROR, "test", ConnectionCloseBehavior::SILENT_CLOSE);
rchf9f103cbc2014-08-30 05:28:04782
783 EXPECT_EQ(ERR_CONNECTION_CLOSED,
rjshaded5ced072015-12-18 19:26:02784 stream_->SendRequest(headers_, &response_, callback_.callback()));
sclittle1edeeb22015-09-02 20:46:10785
786 EXPECT_EQ(0, stream_->GetTotalSentBytes());
787 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rchf9f103cbc2014-08-30 05:28:04788}
789
rch03b7a202016-02-05 00:54:20790// Regression test for http://crbug.com/584441
791TEST_P(QuicHttpStreamTest, GetSSLInfoAfterSessionClosed) {
792 SetRequest("GET", "/", DEFAULT_PRIORITY);
793 Initialize();
794
795 request_.method = "GET";
rch9ae5b3b2016-02-11 00:36:29796 request_.url = GURL("http://www.example.org/");
rch03b7a202016-02-05 00:54:20797
xunjieli5fafe142016-03-23 23:32:54798 EXPECT_EQ(OK,
799 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
800 net_log_.bound(), callback_.callback()));
rch03b7a202016-02-05 00:54:20801
802 SSLInfo ssl_info;
rch11565e02016-02-09 20:13:47803 EXPECT_FALSE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:20804 stream_->GetSSLInfo(&ssl_info);
rch11565e02016-02-09 20:13:47805 EXPECT_TRUE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:20806
jri78ec06a2016-03-31 18:19:40807 session_->connection()->CloseConnection(
808 QUIC_NO_ERROR, "test", ConnectionCloseBehavior::SILENT_CLOSE);
rch03b7a202016-02-05 00:54:20809
rch11565e02016-02-09 20:13:47810 SSLInfo ssl_info2;
811 stream_->GetSSLInfo(&ssl_info2);
812 EXPECT_TRUE(ssl_info2.is_valid());
rch03b7a202016-02-05 00:54:20813}
814
zhongyica364fbb2015-12-12 03:39:12815TEST_P(QuicHttpStreamTest, LogGranularQuicConnectionError) {
816 SetRequest("GET", "/", DEFAULT_PRIORITY);
817 size_t spdy_request_headers_frame_length;
818 AddWrite(ConstructRequestHeadersPacket(1, kFin, DEFAULT_PRIORITY,
819 &spdy_request_headers_frame_length));
820 AddWrite(ConstructAckAndRstStreamPacket(2));
821 use_closing_stream_ = true;
822 Initialize();
823
824 request_.method = "GET";
rch9ae5b3b2016-02-11 00:36:29825 request_.url = GURL("http://www.example.org/");
zhongyica364fbb2015-12-12 03:39:12826
xunjieli5fafe142016-03-23 23:32:54827 EXPECT_EQ(OK,
828 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
829 net_log_.bound(), callback_.callback()));
zhongyica364fbb2015-12-12 03:39:12830 EXPECT_EQ(OK,
831 stream_->SendRequest(headers_, &response_, callback_.callback()));
832
833 // Ack the request.
alyssar2adf3ac2016-05-03 17:12:58834 ProcessPacket(ConstructServerAckPacket(1, 0, 0));
zhongyica364fbb2015-12-12 03:39:12835 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadResponseHeaders(callback_.callback()));
836
837 EXPECT_TRUE(QuicHttpStreamPeer::WasHandshakeConfirmed(stream_.get()));
rch1c5b74a2016-06-23 22:10:55838
839 QuicConnectionCloseFrame frame;
840 frame.error_code = QUIC_PEER_GOING_AWAY;
841 session_->connection()->OnConnectionCloseFrame(frame);
zhongyica364fbb2015-12-12 03:39:12842
843 NetErrorDetails details;
844 EXPECT_EQ(QUIC_NO_ERROR, details.quic_connection_error);
845 stream_->PopulateNetErrorDetails(&details);
846 EXPECT_EQ(QUIC_PEER_GOING_AWAY, details.quic_connection_error);
847}
848
849TEST_P(QuicHttpStreamTest, DoNotLogGranularQuicErrorIfHandshakeNotConfirmed) {
850 SetRequest("GET", "/", DEFAULT_PRIORITY);
851 size_t spdy_request_headers_frame_length;
852 AddWrite(ConstructRequestHeadersPacket(1, kFin, DEFAULT_PRIORITY,
853 &spdy_request_headers_frame_length));
854 AddWrite(ConstructAckAndRstStreamPacket(2));
855 use_closing_stream_ = true;
856 Initialize();
857
858 request_.method = "GET";
rch9ae5b3b2016-02-11 00:36:29859 request_.url = GURL("http://www.example.org/");
zhongyica364fbb2015-12-12 03:39:12860
xunjieli5fafe142016-03-23 23:32:54861 EXPECT_EQ(OK,
862 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
863 net_log_.bound(), callback_.callback()));
zhongyica364fbb2015-12-12 03:39:12864 EXPECT_EQ(OK,
865 stream_->SendRequest(headers_, &response_, callback_.callback()));
866
867 // Ack the request.
alyssar2adf3ac2016-05-03 17:12:58868 ProcessPacket(ConstructServerAckPacket(1, 0, 0));
zhongyica364fbb2015-12-12 03:39:12869 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadResponseHeaders(callback_.callback()));
870
871 // The test setup defaults handshake to be confirmed. Manually set
872 // it to be not confirmed.
873 // Granular errors shouldn't be reported if handshake not confirmed.
874 QuicHttpStreamPeer::SetHandshakeConfirmed(stream_.get(), false);
875
876 EXPECT_FALSE(QuicHttpStreamPeer::WasHandshakeConfirmed(stream_.get()));
rch1c5b74a2016-06-23 22:10:55877 QuicConnectionCloseFrame frame;
878 frame.error_code = QUIC_PEER_GOING_AWAY;
879 session_->connection()->OnConnectionCloseFrame(frame);
zhongyica364fbb2015-12-12 03:39:12880
881 NetErrorDetails details;
882 EXPECT_EQ(QUIC_NO_ERROR, details.quic_connection_error);
883 stream_->PopulateNetErrorDetails(&details);
884 EXPECT_EQ(QUIC_NO_ERROR, details.quic_connection_error);
885}
886
rch11a114a2014-09-04 23:41:59887// Regression test for http://crbug.com/409871
888TEST_P(QuicHttpStreamTest, SessionClosedBeforeReadResponseHeaders) {
889 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:45890 size_t spdy_request_headers_frame_length;
891 AddWrite(ConstructRequestHeadersPacket(1, kFin, DEFAULT_PRIORITY,
892 &spdy_request_headers_frame_length));
rch11a114a2014-09-04 23:41:59893 Initialize();
894
895 request_.method = "GET";
rch9ae5b3b2016-02-11 00:36:29896 request_.url = GURL("http://www.example.org/");
rch11a114a2014-09-04 23:41:59897
xunjieli5fafe142016-03-23 23:32:54898 EXPECT_EQ(OK,
899 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
900 net_log_.bound(), callback_.callback()));
rch11a114a2014-09-04 23:41:59901
rjshaded5ced072015-12-18 19:26:02902 EXPECT_EQ(OK,
903 stream_->SendRequest(headers_, &response_, callback_.callback()));
rch11a114a2014-09-04 23:41:59904
jri78ec06a2016-03-31 18:19:40905 session_->connection()->CloseConnection(
906 QUIC_NO_ERROR, "test", ConnectionCloseBehavior::SILENT_CLOSE);
rch11a114a2014-09-04 23:41:59907
908 EXPECT_NE(OK, stream_->ReadResponseHeaders(callback_.callback()));
sclittle1edeeb22015-09-02 20:46:10909
910 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:45911 // headers and payload.
912 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
913 stream_->GetTotalSentBytes());
sclittle1edeeb22015-09-02 20:46:10914 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rch11a114a2014-09-04 23:41:59915}
916
[email protected]1e960032013-12-20 19:00:20917TEST_P(QuicHttpStreamTest, SendPostRequest) {
918 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:45919 size_t spdy_request_headers_frame_length;
920 AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY,
921 &spdy_request_headers_frame_length));
alyssar2adf3ac2016-05-03 17:12:58922 AddWrite(ConstructClientDataPacket(2, kIncludeVersion, kFin, 0, kUploadData));
923 AddWrite(ConstructClientAckPacket(3, 3, 1));
[email protected]f702d572012-12-04 15:56:20924
925 Initialize();
926
danakjad1777e2016-04-16 00:56:42927 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
928 element_readers.push_back(base::WrapUnique(
olli.raula6df48b2a2015-11-26 07:40:22929 new UploadBytesElementReader(kUploadData, strlen(kUploadData))));
930 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]f702d572012-12-04 15:56:20931 request_.method = "POST";
rch9ae5b3b2016-02-11 00:36:29932 request_.url = GURL("http://www.example.org/");
[email protected]f702d572012-12-04 15:56:20933 request_.upload_data_stream = &upload_data_stream;
[email protected]4db27d82012-12-20 11:50:24934 ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback()));
[email protected]f702d572012-12-04 15:56:20935
xunjieli5fafe142016-03-23 23:32:54936 EXPECT_EQ(OK,
937 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
938 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:02939 EXPECT_EQ(OK,
940 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20941
942 // Ack both packets in the request.
alyssar2adf3ac2016-05-03 17:12:58943 ProcessPacket(ConstructServerAckPacket(1, 0, 0));
[email protected]f702d572012-12-04 15:56:20944
945 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:07946 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:45947 size_t spdy_response_headers_frame_length;
948 ProcessPacket(ConstructResponseHeadersPacket(
949 2, !kFin, &spdy_response_headers_frame_length));
[email protected]f702d572012-12-04 15:56:20950
rchb27683c2015-07-29 23:53:50951 // The headers have arrived, but they are delivered asynchronously.
952 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadResponseHeaders(callback_.callback()));
953 EXPECT_EQ(OK, callback_.WaitForResult());
[email protected]cadac622013-06-11 16:46:36954 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:20955 EXPECT_EQ(200, response_.headers->response_code());
956 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
957
958 // Send the response body.
959 const char kResponseBody[] = "Hello world!";
alyssar2adf3ac2016-05-03 17:12:58960 ProcessPacket(ConstructServerDataPacket(3, false, kFin, 0, kResponseBody));
[email protected]f702d572012-12-04 15:56:20961 // Since the body has already arrived, this should return immediately.
962 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
963 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
964 callback_.callback()));
965
966 EXPECT_TRUE(stream_->IsResponseBodyComplete());
967 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:10968
969 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:45970 // headers and payload.
971 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
972 strlen(kUploadData)),
sclittle1edeeb22015-09-02 20:46:10973 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:45974 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
975 strlen(kResponseBody)),
sclittle1edeeb22015-09-02 20:46:10976 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:20977}
978
[email protected]1e960032013-12-20 19:00:20979TEST_P(QuicHttpStreamTest, SendChunkedPostRequest) {
980 SetRequest("POST", "/", DEFAULT_PRIORITY);
[email protected]c9e49a02013-02-26 05:56:47981 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:45982 size_t spdy_request_headers_frame_length;
983 AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY,
984 &spdy_request_headers_frame_length));
rjshaded5ced072015-12-18 19:26:02985 AddWrite(
alyssar2adf3ac2016-05-03 17:12:58986 ConstructClientDataPacket(2, kIncludeVersion, !kFin, 0, kUploadData));
987 AddWrite(ConstructClientDataPacket(3, kIncludeVersion, kFin, chunk_size,
988 kUploadData));
989 AddWrite(ConstructClientAckPacket(4, 3, 1));
[email protected]c9e49a02013-02-26 05:56:47990 Initialize();
991
mmenkecbc2b712014-10-09 20:29:07992 ChunkedUploadDataStream upload_data_stream(0);
993 upload_data_stream.AppendData(kUploadData, chunk_size, false);
[email protected]c9e49a02013-02-26 05:56:47994
995 request_.method = "POST";
rch9ae5b3b2016-02-11 00:36:29996 request_.url = GURL("http://www.example.org/");
[email protected]c9e49a02013-02-26 05:56:47997 request_.upload_data_stream = &upload_data_stream;
mmenkecbc2b712014-10-09 20:29:07998 ASSERT_EQ(OK, request_.upload_data_stream->Init(
rjshaded5ced072015-12-18 19:26:02999 TestCompletionCallback().callback()));
[email protected]c9e49a02013-02-26 05:56:471000
xunjieli5fafe142016-03-23 23:32:541001 ASSERT_EQ(OK,
1002 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1003 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021004 ASSERT_EQ(ERR_IO_PENDING,
1005 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]c9e49a02013-02-26 05:56:471006
mmenkecbc2b712014-10-09 20:29:071007 upload_data_stream.AppendData(kUploadData, chunk_size, true);
rchb27683c2015-07-29 23:53:501008 EXPECT_EQ(OK, callback_.WaitForResult());
[email protected]c9e49a02013-02-26 05:56:471009
1010 // Ack both packets in the request.
alyssar2adf3ac2016-05-03 17:12:581011 ProcessPacket(ConstructServerAckPacket(1, 0, 0));
[email protected]c9e49a02013-02-26 05:56:471012
1013 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071014 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451015 size_t spdy_response_headers_frame_length;
1016 ProcessPacket(ConstructResponseHeadersPacket(
1017 2, !kFin, &spdy_response_headers_frame_length));
[email protected]c9e49a02013-02-26 05:56:471018
rchb27683c2015-07-29 23:53:501019 // The headers have arrived, but they are delivered asynchronously
1020 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadResponseHeaders(callback_.callback()));
1021 EXPECT_EQ(OK, callback_.WaitForResult());
[email protected]cadac622013-06-11 16:46:361022 ASSERT_TRUE(response_.headers.get());
[email protected]c9e49a02013-02-26 05:56:471023 EXPECT_EQ(200, response_.headers->response_code());
1024 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1025
1026 // Send the response body.
1027 const char kResponseBody[] = "Hello world!";
alyssar2adf3ac2016-05-03 17:12:581028 ProcessPacket(ConstructServerDataPacket(
1029 3, false, kFin, response_data_.length(), kResponseBody));
[email protected]c9e49a02013-02-26 05:56:471030
1031 // Since the body has already arrived, this should return immediately.
1032 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1033 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1034 callback_.callback()));
1035
1036 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1037 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101038
1039 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451040 // headers and payload.
1041 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
1042 strlen(kUploadData) * 2),
sclittle1edeeb22015-09-02 20:46:101043 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451044 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1045 strlen(kResponseBody)),
sclittle1edeeb22015-09-02 20:46:101046 stream_->GetTotalReceivedBytes());
[email protected]c9e49a02013-02-26 05:56:471047}
1048
[email protected]16ba7742014-08-22 00:57:251049TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithFinalEmptyDataPacket) {
1050 SetRequest("POST", "/", DEFAULT_PRIORITY);
1051 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:451052 size_t spdy_request_headers_frame_length;
1053 AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY,
1054 &spdy_request_headers_frame_length));
alyssar2adf3ac2016-05-03 17:12:581055 AddWrite(
1056 ConstructClientDataPacket(2, kIncludeVersion, !kFin, 0, kUploadData));
1057 AddWrite(ConstructClientDataPacket(3, kIncludeVersion, kFin, chunk_size, ""));
1058 AddWrite(ConstructClientAckPacket(4, 3, 1));
[email protected]16ba7742014-08-22 00:57:251059 Initialize();
1060
mmenkecbc2b712014-10-09 20:29:071061 ChunkedUploadDataStream upload_data_stream(0);
1062 upload_data_stream.AppendData(kUploadData, chunk_size, false);
[email protected]16ba7742014-08-22 00:57:251063
1064 request_.method = "POST";
rch9ae5b3b2016-02-11 00:36:291065 request_.url = GURL("http://www.example.org/");
[email protected]16ba7742014-08-22 00:57:251066 request_.upload_data_stream = &upload_data_stream;
mmenkecbc2b712014-10-09 20:29:071067 ASSERT_EQ(OK, request_.upload_data_stream->Init(
rjshaded5ced072015-12-18 19:26:021068 TestCompletionCallback().callback()));
[email protected]16ba7742014-08-22 00:57:251069
xunjieli5fafe142016-03-23 23:32:541070 ASSERT_EQ(OK,
1071 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1072 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021073 ASSERT_EQ(ERR_IO_PENDING,
1074 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251075
mmenkecbc2b712014-10-09 20:29:071076 upload_data_stream.AppendData(nullptr, 0, true);
rchb27683c2015-07-29 23:53:501077 EXPECT_EQ(OK, callback_.WaitForResult());
[email protected]16ba7742014-08-22 00:57:251078
alyssar2adf3ac2016-05-03 17:12:581079 ProcessPacket(ConstructServerAckPacket(1, 0, 0));
[email protected]16ba7742014-08-22 00:57:251080
1081 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071082 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451083 size_t spdy_response_headers_frame_length;
1084 ProcessPacket(ConstructResponseHeadersPacket(
1085 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251086
rchb27683c2015-07-29 23:53:501087 // The headers have arrived, but they are delivered asynchronously
1088 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadResponseHeaders(callback_.callback()));
1089 EXPECT_EQ(OK, callback_.WaitForResult());
[email protected]16ba7742014-08-22 00:57:251090 ASSERT_TRUE(response_.headers.get());
1091 EXPECT_EQ(200, response_.headers->response_code());
1092 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1093
1094 // Send the response body.
1095 const char kResponseBody[] = "Hello world!";
alyssar2adf3ac2016-05-03 17:12:581096 ProcessPacket(ConstructServerDataPacket(
1097 3, false, kFin, response_data_.length(), kResponseBody));
[email protected]16ba7742014-08-22 00:57:251098
rchb27683c2015-07-29 23:53:501099 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251100 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1101 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1102 callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251103 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1104 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101105
1106 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451107 // headers and payload.
1108 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
1109 strlen(kUploadData)),
sclittle1edeeb22015-09-02 20:46:101110 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451111 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1112 strlen(kResponseBody)),
sclittle1edeeb22015-09-02 20:46:101113 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251114}
1115
1116TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithOneEmptyDataPacket) {
1117 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451118 size_t spdy_request_headers_frame_length;
1119 AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY,
1120 &spdy_request_headers_frame_length));
alyssar2adf3ac2016-05-03 17:12:581121 AddWrite(ConstructClientDataPacket(2, kIncludeVersion, kFin, 0, ""));
1122 AddWrite(ConstructClientAckPacket(3, 3, 1));
[email protected]16ba7742014-08-22 00:57:251123 Initialize();
1124
mmenkecbc2b712014-10-09 20:29:071125 ChunkedUploadDataStream upload_data_stream(0);
[email protected]16ba7742014-08-22 00:57:251126
1127 request_.method = "POST";
rch9ae5b3b2016-02-11 00:36:291128 request_.url = GURL("http://www.example.org/");
[email protected]16ba7742014-08-22 00:57:251129 request_.upload_data_stream = &upload_data_stream;
mmenkecbc2b712014-10-09 20:29:071130 ASSERT_EQ(OK, request_.upload_data_stream->Init(
rjshaded5ced072015-12-18 19:26:021131 TestCompletionCallback().callback()));
[email protected]16ba7742014-08-22 00:57:251132
xunjieli5fafe142016-03-23 23:32:541133 ASSERT_EQ(OK,
1134 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1135 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021136 ASSERT_EQ(ERR_IO_PENDING,
1137 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251138
mmenkecbc2b712014-10-09 20:29:071139 upload_data_stream.AppendData(nullptr, 0, true);
rchb27683c2015-07-29 23:53:501140 EXPECT_EQ(OK, callback_.WaitForResult());
[email protected]16ba7742014-08-22 00:57:251141
alyssar2adf3ac2016-05-03 17:12:581142 ProcessPacket(ConstructServerAckPacket(1, 0, 0));
[email protected]16ba7742014-08-22 00:57:251143
1144 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071145 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451146 size_t spdy_response_headers_frame_length;
1147 ProcessPacket(ConstructResponseHeadersPacket(
1148 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251149
rchb27683c2015-07-29 23:53:501150 // The headers have arrived, but they are delivered asynchronously
1151 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadResponseHeaders(callback_.callback()));
1152 EXPECT_EQ(OK, callback_.WaitForResult());
[email protected]16ba7742014-08-22 00:57:251153 ASSERT_TRUE(response_.headers.get());
1154 EXPECT_EQ(200, response_.headers->response_code());
1155 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1156
1157 // Send the response body.
1158 const char kResponseBody[] = "Hello world!";
alyssar2adf3ac2016-05-03 17:12:581159 ProcessPacket(ConstructServerDataPacket(
1160 3, false, kFin, response_data_.length(), kResponseBody));
[email protected]16ba7742014-08-22 00:57:251161
rchb27683c2015-07-29 23:53:501162 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251163 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1164 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1165 callback_.callback()));
1166
1167 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1168 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101169
1170 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451171 // headers and payload.
1172 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1173 stream_->GetTotalSentBytes());
1174 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1175 strlen(kResponseBody)),
sclittle1edeeb22015-09-02 20:46:101176 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251177}
1178
[email protected]1e960032013-12-20 19:00:201179TEST_P(QuicHttpStreamTest, DestroyedEarly) {
1180 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451181 size_t spdy_request_headers_frame_length;
1182 AddWrite(ConstructRequestHeadersPacket(1, kFin, DEFAULT_PRIORITY,
1183 &spdy_request_headers_frame_length));
rtenneti4efd55dd2015-09-18 01:12:041184 AddWrite(ConstructAckAndRstStreamPacket(2));
[email protected]63534512012-12-23 18:49:001185 use_closing_stream_ = true;
1186 Initialize();
1187
1188 request_.method = "GET";
rch9ae5b3b2016-02-11 00:36:291189 request_.url = GURL("http://www.example.org/");
[email protected]63534512012-12-23 18:49:001190
xunjieli5fafe142016-03-23 23:32:541191 EXPECT_EQ(OK,
1192 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1193 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021194 EXPECT_EQ(OK,
1195 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]63534512012-12-23 18:49:001196
1197 // Ack the request.
alyssar2adf3ac2016-05-03 17:12:581198 ProcessPacket(ConstructServerAckPacket(1, 0, 0));
rjshaded5ced072015-12-18 19:26:021199 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadResponseHeaders(callback_.callback()));
[email protected]63534512012-12-23 18:49:001200
1201 // Send the response with a body.
[email protected]1e960032013-12-20 19:00:201202 SetResponse("404 OK", "hello world!");
[email protected]63534512012-12-23 18:49:001203 // In the course of processing this packet, the QuicHttpStream close itself.
sclittlec4dc1a32015-09-24 00:15:451204 ProcessPacket(ConstructResponseHeadersPacket(2, kFin, nullptr));
[email protected]63534512012-12-23 18:49:001205
fdoray92e35a72016-06-10 15:54:551206 base::RunLoop().RunUntilIdle();
rchb27683c2015-07-29 23:53:501207
[email protected]63534512012-12-23 18:49:001208 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101209
1210 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451211 // headers and payload.
1212 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1213 stream_->GetTotalSentBytes());
1214 // Zero since the stream is closed before processing the headers.
sclittle1edeeb22015-09-02 20:46:101215 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
[email protected]63534512012-12-23 18:49:001216}
1217
[email protected]1e960032013-12-20 19:00:201218TEST_P(QuicHttpStreamTest, Priority) {
1219 SetRequest("GET", "/", MEDIUM);
sclittlec4dc1a32015-09-24 00:15:451220 size_t spdy_request_headers_frame_length;
1221 AddWrite(ConstructRequestHeadersPacket(1, kFin, MEDIUM,
1222 &spdy_request_headers_frame_length));
rtenneti4efd55dd2015-09-18 01:12:041223 AddWrite(ConstructAckAndRstStreamPacket(2));
[email protected]24e5bc52013-09-18 15:36:581224 use_closing_stream_ = true;
1225 Initialize();
1226
1227 request_.method = "GET";
rch9ae5b3b2016-02-11 00:36:291228 request_.url = GURL("http://www.example.org/");
[email protected]24e5bc52013-09-18 15:36:581229
xunjieli5fafe142016-03-23 23:32:541230 EXPECT_EQ(OK, stream_->InitializeStream(&request_, MEDIUM, net_log_.bound(),
rjshaded5ced072015-12-18 19:26:021231 callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581232
1233 // Check that priority is highest.
rch12fef552016-01-15 16:26:311234 QuicChromiumClientStream* reliable_stream =
1235 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
[email protected]24e5bc52013-09-18 15:36:581236 DCHECK(reliable_stream);
fayanga64c1a92016-02-13 01:55:581237 DCHECK_EQ(kV3HighestPriority, reliable_stream->priority());
[email protected]24e5bc52013-09-18 15:36:581238
rjshaded5ced072015-12-18 19:26:021239 EXPECT_EQ(OK,
1240 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581241
1242 // Check that priority has now dropped back to MEDIUM.
ianswett0888cff2015-11-24 17:42:161243 DCHECK_EQ(MEDIUM,
fayanga64c1a92016-02-13 01:55:581244 ConvertQuicPriorityToRequestPriority(reliable_stream->priority()));
[email protected]24e5bc52013-09-18 15:36:581245
1246 // Ack the request.
alyssar2adf3ac2016-05-03 17:12:581247 ProcessPacket(ConstructServerAckPacket(1, 0, 0));
rjshaded5ced072015-12-18 19:26:021248 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadResponseHeaders(callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581249
1250 // Send the response with a body.
[email protected]1e960032013-12-20 19:00:201251 SetResponse("404 OK", "hello world!");
[email protected]24e5bc52013-09-18 15:36:581252 // In the course of processing this packet, the QuicHttpStream close itself.
sclittlec4dc1a32015-09-24 00:15:451253 ProcessPacket(ConstructResponseHeadersPacket(2, kFin, nullptr));
[email protected]24e5bc52013-09-18 15:36:581254
fdoray92e35a72016-06-10 15:54:551255 base::RunLoop().RunUntilIdle();
rchb27683c2015-07-29 23:53:501256
[email protected]24e5bc52013-09-18 15:36:581257 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101258
1259 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451260 // headers and payload.
1261 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1262 stream_->GetTotalSentBytes());
1263 // Zero since the stream is closed before processing the headers.
sclittle1edeeb22015-09-02 20:46:101264 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
[email protected]24e5bc52013-09-18 15:36:581265}
1266
[email protected]e1cca9a2013-09-20 17:14:441267// Regression test for http://crbug.com/294870
[email protected]1e960032013-12-20 19:00:201268TEST_P(QuicHttpStreamTest, CheckPriorityWithNoDelegate) {
1269 SetRequest("GET", "/", MEDIUM);
[email protected]e1cca9a2013-09-20 17:14:441270 use_closing_stream_ = true;
[email protected]459a7402014-02-10 12:58:521271
alyssar2adf3ac2016-05-03 17:12:581272 AddWrite(ConstructClientRstStreamPacket(1));
[email protected]459a7402014-02-10 12:58:521273
[email protected]e1cca9a2013-09-20 17:14:441274 Initialize();
1275
1276 request_.method = "GET";
rch9ae5b3b2016-02-11 00:36:291277 request_.url = GURL("http://www.example.org/");
[email protected]e1cca9a2013-09-20 17:14:441278
xunjieli5fafe142016-03-23 23:32:541279 EXPECT_EQ(OK, stream_->InitializeStream(&request_, MEDIUM, net_log_.bound(),
rjshaded5ced072015-12-18 19:26:021280 callback_.callback()));
[email protected]e1cca9a2013-09-20 17:14:441281
1282 // Check that priority is highest.
rch12fef552016-01-15 16:26:311283 QuicChromiumClientStream* reliable_stream =
1284 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
[email protected]e1cca9a2013-09-20 17:14:441285 DCHECK(reliable_stream);
rch12fef552016-01-15 16:26:311286 QuicChromiumClientStream::Delegate* delegate = reliable_stream->GetDelegate();
[email protected]e1cca9a2013-09-20 17:14:441287 DCHECK(delegate);
fayanga64c1a92016-02-13 01:55:581288 DCHECK_EQ(kV3HighestPriority, reliable_stream->priority());
[email protected]e1cca9a2013-09-20 17:14:441289
ianswett0888cff2015-11-24 17:42:161290 // Set Delegate to nullptr and make sure Priority returns highest
[email protected]e1cca9a2013-09-20 17:14:441291 // priority.
rtennetibe635732014-10-02 22:51:421292 reliable_stream->SetDelegate(nullptr);
fayanga64c1a92016-02-13 01:55:581293 DCHECK_EQ(kV3HighestPriority, reliable_stream->priority());
[email protected]e1cca9a2013-09-20 17:14:441294 reliable_stream->SetDelegate(delegate);
sclittle1edeeb22015-09-02 20:46:101295
sclittle1edeeb22015-09-02 20:46:101296 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1297 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
[email protected]e1cca9a2013-09-20 17:14:441298}
1299
rtenneti15656ae2016-01-23 03:05:031300TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersComplete) {
1301 SetRequest("POST", "/", DEFAULT_PRIORITY);
1302 AddWrite(SYNCHRONOUS, ERR_FAILED);
1303 Initialize();
1304
1305 ChunkedUploadDataStream upload_data_stream(0);
1306
1307 request_.method = "POST";
rch9ae5b3b2016-02-11 00:36:291308 request_.url = GURL("http://www.example.org/");
rtenneti15656ae2016-01-23 03:05:031309 request_.upload_data_stream = &upload_data_stream;
1310 ASSERT_EQ(OK, request_.upload_data_stream->Init(
1311 TestCompletionCallback().callback()));
1312
xunjieli5fafe142016-03-23 23:32:541313 ASSERT_EQ(OK,
1314 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1315 net_log_.bound(), callback_.callback()));
rtenneti15656ae2016-01-23 03:05:031316 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1317 stream_->SendRequest(headers_, &response_, callback_.callback()));
1318}
1319
1320TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBodyComplete) {
1321 SetRequest("POST", "/", DEFAULT_PRIORITY);
1322 size_t spdy_request_headers_frame_length;
1323 AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY,
1324 &spdy_request_headers_frame_length));
1325 AddWrite(SYNCHRONOUS, ERR_FAILED);
1326 Initialize();
1327
1328 ChunkedUploadDataStream upload_data_stream(0);
1329 size_t chunk_size = strlen(kUploadData);
1330 upload_data_stream.AppendData(kUploadData, chunk_size, false);
1331
1332 request_.method = "POST";
rch9ae5b3b2016-02-11 00:36:291333 request_.url = GURL("http://www.example.org/");
rtenneti15656ae2016-01-23 03:05:031334 request_.upload_data_stream = &upload_data_stream;
1335 ASSERT_EQ(OK, request_.upload_data_stream->Init(
1336 TestCompletionCallback().callback()));
1337
xunjieli5fafe142016-03-23 23:32:541338 ASSERT_EQ(OK,
1339 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1340 net_log_.bound(), callback_.callback()));
rtenneti15656ae2016-01-23 03:05:031341 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1342 stream_->SendRequest(headers_, &response_, callback_.callback()));
1343}
1344
ckrasic3865ee0f2016-02-29 22:04:561345TEST_P(QuicHttpStreamTest, ServerPushGetRequest) {
1346 SetRequest("GET", "/", DEFAULT_PRIORITY);
1347 Initialize();
1348
1349 // Initialize the first stream, for receiving the promise on.
1350 request_.method = "GET";
1351 request_.url = GURL("http://www.example.org/");
1352
xunjieli5fafe142016-03-23 23:32:541353 EXPECT_EQ(OK,
1354 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1355 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561356
1357 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
1358 // packet, but does it matter?
1359 ReceivePromise(promise_id_);
1360 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
1361
1362 request_.url = GURL(promise_url_);
1363
1364 // Make the second stream that will exercise the first step of the
1365 // server push rendezvous mechanism.
xunjieli5fafe142016-03-23 23:32:541366 EXPECT_EQ(OK, promised_stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1367 net_log_.bound(),
1368 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561369
1370 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:251371 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:561372 size_t spdy_response_headers_frame_length;
1373 ProcessPacket(InnerConstructResponseHeadersPacket(
1374 1, promise_id_, false, &spdy_response_headers_frame_length));
1375
1376 // Receive the promised response body.
1377 const char kResponseBody[] = "Hello world!";
alyssar2adf3ac2016-05-03 17:12:581378 ProcessPacket(InnerConstructDataPacket(2, promise_id_, false, kFin, 0,
1379 kResponseBody, &server_maker_));
ckrasic3865ee0f2016-02-29 22:04:561380
1381 // Now sending a matching request will have successful rendezvous
1382 // with the promised stream.
1383 EXPECT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
1384 callback_.callback()));
1385
1386 EXPECT_EQ(
1387 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
1388 ->id(),
1389 promise_id_);
1390
1391 // The headers will be immediately available.
1392 EXPECT_EQ(OK, promised_stream_->ReadResponseHeaders(callback_.callback()));
1393
1394 // As will be the body.
1395 EXPECT_EQ(
1396 static_cast<int>(strlen(kResponseBody)),
1397 promised_stream_->ReadResponseBody(
1398 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
1399 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
1400 EXPECT_TRUE(AtEof());
1401
1402 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1403 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1404 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
1405 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1406 strlen(kResponseBody)),
1407 promised_stream_->GetTotalReceivedBytes());
1408}
1409
1410TEST_P(QuicHttpStreamTest, ServerPushGetRequestSlowResponse) {
1411 SetRequest("GET", "/", DEFAULT_PRIORITY);
1412 Initialize();
1413
1414 // Initialize the first stream, for receiving the promise on.
1415 request_.method = "GET";
1416 request_.url = GURL("http://www.example.org/");
1417
xunjieli5fafe142016-03-23 23:32:541418 EXPECT_EQ(OK,
1419 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1420 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561421
1422 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
1423 // packet, but does it matter?
1424 ReceivePromise(promise_id_);
1425 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
1426
1427 request_.url = GURL(promise_url_);
1428
1429 // Make the second stream that will exercise the first step of the
1430 // server push rendezvous mechanism.
xunjieli5fafe142016-03-23 23:32:541431 EXPECT_EQ(OK, promised_stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1432 net_log_.bound(),
1433 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561434
1435 // Now sending a matching request will rendezvous with the promised
1436 // stream, but pending secondary validation.
1437 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
1438 headers_, &response_, callback_.callback()));
1439
1440 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:251441 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:561442 size_t spdy_response_headers_frame_length;
1443 ProcessPacket(InnerConstructResponseHeadersPacket(
1444 1, promise_id_, false, &spdy_response_headers_frame_length));
1445
1446 // Receive the promised response body.
1447 const char kResponseBody[] = "Hello world!";
alyssar2adf3ac2016-05-03 17:12:581448 ProcessPacket(InnerConstructDataPacket(2, promise_id_, false, kFin, 0,
1449 kResponseBody, &server_maker_));
ckrasic3865ee0f2016-02-29 22:04:561450
fdoray92e35a72016-06-10 15:54:551451 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:561452
1453 // Rendezvous should have succeeded now, so the promised stream
1454 // should point at our push stream, and we should be able read
1455 // headers and data from it.
1456 EXPECT_EQ(OK, callback_.WaitForResult());
1457
1458 EXPECT_EQ(
1459 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
1460 ->id(),
1461 promise_id_);
1462
1463 EXPECT_EQ(OK, promised_stream_->ReadResponseHeaders(callback_.callback()));
1464
1465 EXPECT_EQ(
1466 static_cast<int>(strlen(kResponseBody)),
1467 promised_stream_->ReadResponseBody(
1468 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
1469
1470 // Callback should return
1471 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
1472 EXPECT_TRUE(AtEof());
1473
1474 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1475 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1476 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
1477 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1478 strlen(kResponseBody)),
1479 promised_stream_->GetTotalReceivedBytes());
1480}
1481
1482TEST_P(QuicHttpStreamTest, ServerPushCrossOriginOK) {
1483 SetRequest("GET", "/", DEFAULT_PRIORITY);
1484 Initialize();
1485
1486 // Initialize the first stream, for receiving the promise on.
1487 request_.method = "GET";
1488 request_.url = GURL("http://www.example.org/");
1489
xunjieli5fafe142016-03-23 23:32:541490 EXPECT_EQ(OK,
1491 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1492 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561493
1494 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
1495 // packet, but does it matter?
1496
1497 push_promise_[":authority"] = "mail.example.org";
1498 promise_url_ = SpdyUtils::GetUrlFromHeaderBlock(push_promise_);
1499 serialized_push_promise_ =
1500 SpdyUtils::SerializeUncompressedHeaders(push_promise_);
1501
1502 ReceivePromise(promise_id_);
1503 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
1504
1505 request_.url = GURL(promise_url_);
1506
1507 // Make the second stream that will exercise the first step of the
1508 // server push rendezvous mechanism.
xunjieli5fafe142016-03-23 23:32:541509 EXPECT_EQ(OK, promised_stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1510 net_log_.bound(),
1511 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561512
1513 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:251514 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:561515 size_t spdy_response_headers_frame_length;
1516 ProcessPacket(InnerConstructResponseHeadersPacket(
1517 1, promise_id_, false, &spdy_response_headers_frame_length));
1518
1519 // Receive the promised response body.
1520 const char kResponseBody[] = "Hello world!";
alyssar2adf3ac2016-05-03 17:12:581521 ProcessPacket(InnerConstructDataPacket(2, promise_id_, false, kFin, 0,
1522 kResponseBody, &server_maker_));
ckrasic3865ee0f2016-02-29 22:04:561523
1524 // Now sending a matching request will have successful rendezvous
1525 // with the promised stream.
1526 EXPECT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
1527 callback_.callback()));
1528
1529 EXPECT_EQ(
1530 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
1531 ->id(),
1532 promise_id_);
1533
1534 // The headers will be immediately available.
1535 EXPECT_EQ(OK, promised_stream_->ReadResponseHeaders(callback_.callback()));
1536
1537 // As will be the body.
1538 EXPECT_EQ(
1539 static_cast<int>(strlen(kResponseBody)),
1540 promised_stream_->ReadResponseBody(
1541 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
1542 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
1543 EXPECT_TRUE(AtEof());
1544
1545 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1546 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1547 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
1548 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1549 strlen(kResponseBody)),
1550 promised_stream_->GetTotalReceivedBytes());
1551}
1552
1553TEST_P(QuicHttpStreamTest, ServerPushCrossOriginFail) {
1554 SetRequest("GET", "/", DEFAULT_PRIORITY);
1555 Initialize();
1556
1557 // Initialize the first stream, for receiving the promise on.
1558 request_.method = "GET";
1559 request_.url = GURL("http://www.example.org/");
1560
xunjieli5fafe142016-03-23 23:32:541561 EXPECT_EQ(OK,
1562 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1563 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561564
1565 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
1566 // packet, but does it matter?
1567 push_promise_[":authority"] = "www.notexample.org";
1568 promise_url_ = SpdyUtils::GetUrlFromHeaderBlock(push_promise_);
1569 serialized_push_promise_ =
1570 SpdyUtils::SerializeUncompressedHeaders(push_promise_);
1571
1572 ReceivePromise(promise_id_);
1573 // The promise will have been rejected because the cert doesn't
1574 // match.
1575 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
1576}
1577
1578TEST_P(QuicHttpStreamTest, ServerPushVaryCheckOK) {
1579 SetRequest("GET", "/", DEFAULT_PRIORITY);
1580 Initialize();
1581
1582 // Initialize the first stream, for receiving the promise on.
1583 request_.method = "GET";
1584 request_.url = GURL("http://www.example.org/");
1585
xunjieli5fafe142016-03-23 23:32:541586 EXPECT_EQ(OK,
1587 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1588 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561589
1590 push_promise_["accept-encoding"] = "gzip";
1591 serialized_push_promise_ =
1592 SpdyUtils::SerializeUncompressedHeaders(push_promise_);
1593
1594 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
1595 // packet, but does it matter?
1596 ReceivePromise(promise_id_);
1597 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
1598
1599 request_.url = GURL(promise_url_);
1600
1601 // Make the second stream that will exercise the first step of the
1602 // server push rendezvous mechanism.
xunjieli5fafe142016-03-23 23:32:541603 EXPECT_EQ(OK, promised_stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1604 net_log_.bound(),
1605 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561606
1607 headers_.SetHeader("accept-encoding", "gzip");
1608
1609 // Now sending a matching request will rendezvous with the promised
1610 // stream, but pending secondary validation.
1611 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
1612 headers_, &response_, callback_.callback()));
1613
1614 // Receive the promised response headers.
1615 promised_response_["vary"] = "accept-encoding";
bnc94893a72016-06-30 13:45:251616 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:561617 size_t spdy_response_headers_frame_length;
1618 ProcessPacket(InnerConstructResponseHeadersPacket(
1619 1, promise_id_, false, &spdy_response_headers_frame_length));
1620
1621 // Receive the promised response body.
1622 const char kResponseBody[] = "Hello world!";
alyssar2adf3ac2016-05-03 17:12:581623 ProcessPacket(InnerConstructDataPacket(2, promise_id_, false, kFin, 0,
1624 kResponseBody, &server_maker_));
ckrasic3865ee0f2016-02-29 22:04:561625
fdoray92e35a72016-06-10 15:54:551626 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:561627
1628 // Rendezvous should have succeeded now, so the promised stream
1629 // should point at our push stream, and we should be able read
1630 // headers and data from it.
1631 EXPECT_EQ(OK, callback_.WaitForResult());
1632
1633 EXPECT_EQ(
1634 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
1635 ->id(),
1636 promise_id_);
1637
1638 EXPECT_EQ(OK, promised_stream_->ReadResponseHeaders(callback_.callback()));
1639
1640 EXPECT_EQ(
1641 static_cast<int>(strlen(kResponseBody)),
1642 promised_stream_->ReadResponseBody(
1643 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
1644
1645 // Callback should return
1646 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
1647 EXPECT_TRUE(AtEof());
1648
1649 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1650 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1651 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
1652 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1653 strlen(kResponseBody)),
1654 promised_stream_->GetTotalReceivedBytes());
1655}
1656
1657TEST_P(QuicHttpStreamTest, ServerPushVaryCheckFail) {
1658 SetRequest("GET", "/", DEFAULT_PRIORITY);
1659 request_headers_[":scheme"] = "https";
1660 request_headers_[":path"] = "/bar";
1661 request_headers_["accept-encoding"] = "sdch";
1662
1663 size_t spdy_request_header_frame_length;
alyssar2adf3ac2016-05-03 17:12:581664 AddWrite(ConstructClientRstStreamVaryMismatchPacket(1));
ckrasic3865ee0f2016-02-29 22:04:561665 AddWrite(InnerConstructRequestHeadersPacket(
1666 2, stream_id_ + 2, !kIncludeVersion, kFin, DEFAULT_PRIORITY,
1667 &spdy_request_header_frame_length));
alyssar2adf3ac2016-05-03 17:12:581668 AddWrite(ConstructClientAckPacket(3, 3, 1));
1669 AddWrite(ConstructClientRstStreamCancelledPacket(4));
ckrasic3865ee0f2016-02-29 22:04:561670 Initialize();
1671
1672 // Initialize the first stream, for receiving the promise on.
1673 request_.method = "GET";
1674 request_.url = GURL("http://www.example.org/");
1675
xunjieli5fafe142016-03-23 23:32:541676 EXPECT_EQ(OK,
1677 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1678 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561679
1680 push_promise_["accept-encoding"] = "gzip";
1681 serialized_push_promise_ =
1682 SpdyUtils::SerializeUncompressedHeaders(push_promise_);
1683
1684 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
1685 // packet, but does it matter?
1686 ReceivePromise(promise_id_);
1687 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
1688
1689 request_.url = GURL(promise_url_);
1690
1691 // Make the second stream that will exercise the first step of the
1692 // server push rendezvous mechanism.
xunjieli5fafe142016-03-23 23:32:541693 EXPECT_EQ(OK, promised_stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1694 net_log_.bound(),
1695 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561696
1697 headers_.SetHeader("accept-encoding", "sdch");
1698
1699 // Now sending a matching request will rendezvous with the promised
1700 // stream, but pending secondary validation.
1701 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
1702 headers_, &response_, callback_.callback()));
1703
1704 // Receive the promised response headers.
1705 promised_response_["vary"] = "accept-encoding";
bnc94893a72016-06-30 13:45:251706 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:561707 size_t spdy_response_headers_frame_length;
1708 ProcessPacket(InnerConstructResponseHeadersPacket(
1709 1, promise_id_, false, &spdy_response_headers_frame_length));
1710
fdoray92e35a72016-06-10 15:54:551711 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:561712
1713 // Rendezvous should have failed due to vary mismatch, so the
1714 // promised stream should have been aborted, and instead we have a
1715 // new, regular client initiated stream.
1716 EXPECT_EQ(OK, callback_.WaitForResult());
1717
1718 // Not a server-initiated stream.
1719 EXPECT_NE(
1720 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
1721 ->id(),
1722 promise_id_);
1723
1724 // Instead, a new client-initiated stream.
1725 EXPECT_EQ(
1726 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
1727 ->id(),
1728 stream_id_ + 2);
1729
1730 // After rendezvous failure, the push stream has been cancelled.
1731 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
1732
1733 // The rest of the test verifies that the retried as
1734 // client-initiated version of |promised_stream_| works as intended.
1735
1736 // Ack the request.
alyssar2adf3ac2016-05-03 17:12:581737 ProcessPacket(ConstructServerAckPacket(2, 0, 0));
ckrasic3865ee0f2016-02-29 22:04:561738
bnc614a92d32016-04-04 13:56:071739 SetResponse("404 Not Found", string());
ckrasic3865ee0f2016-02-29 22:04:561740 size_t spdy_response_header_frame_length;
1741 ProcessPacket(InnerConstructResponseHeadersPacket(
1742 3, stream_id_ + 2, kFin, &spdy_response_header_frame_length));
1743
fdoray92e35a72016-06-10 15:54:551744 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:561745
1746 EXPECT_EQ(OK, promised_stream_->ReadResponseHeaders(callback_.callback()));
1747 ASSERT_TRUE(response_.headers.get());
1748 EXPECT_EQ(404, response_.headers->response_code());
1749 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1750 EXPECT_FALSE(response_.response_time.is_null());
1751 EXPECT_FALSE(response_.request_time.is_null());
1752
1753 // There is no body, so this should return immediately.
1754 EXPECT_EQ(
1755 0, promised_stream_->ReadResponseBody(
1756 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
1757 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
1758
1759 stream_->Close(true);
1760
1761 EXPECT_TRUE(AtEof());
1762
1763 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
1764 // headers and payload.
1765 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
1766 promised_stream_->GetTotalSentBytes());
1767 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length),
1768 promised_stream_->GetTotalReceivedBytes());
1769}
1770
maksim.sisov84e20c92016-06-23 08:49:341771TEST_P(QuicHttpStreamTest, DataReadErrorSynchronous) {
1772 SetRequest("POST", "/", DEFAULT_PRIORITY);
1773 size_t spdy_request_headers_frame_length;
1774 AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY,
1775 &spdy_request_headers_frame_length));
1776 AddWrite(ConstructClientRstStreamErrorPacket(2, kIncludeVersion));
1777
1778 Initialize();
1779
1780 ReadErrorUploadDataStream upload_data_stream(
1781 ReadErrorUploadDataStream::FailureMode::SYNC);
1782 request_.method = "POST";
1783 request_.url = GURL("http://www.example.org/");
1784 request_.upload_data_stream = &upload_data_stream;
1785 ASSERT_EQ(OK, request_.upload_data_stream->Init(
1786 TestCompletionCallback().callback()));
1787
1788 EXPECT_EQ(OK,
1789 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1790 net_log_.bound(), callback_.callback()));
1791
1792 int result = stream_->SendRequest(headers_, &response_, callback_.callback());
1793 EXPECT_EQ(ERR_FAILED, result);
1794
1795 EXPECT_TRUE(AtEof());
1796
1797 // QuicHttpStream::GetTotalSent/ReceivedBytes includes only headers.
1798 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1799 stream_->GetTotalSentBytes());
1800 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1801}
1802
1803TEST_P(QuicHttpStreamTest, DataReadErrorAsynchronous) {
1804 SetRequest("POST", "/", DEFAULT_PRIORITY);
1805 size_t spdy_request_headers_frame_length;
1806 AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY,
1807 &spdy_request_headers_frame_length));
1808 AddWrite(ConstructClientRstStreamErrorPacket(2, !kIncludeVersion));
1809
1810 Initialize();
1811
1812 ReadErrorUploadDataStream upload_data_stream(
1813 ReadErrorUploadDataStream::FailureMode::ASYNC);
1814 request_.method = "POST";
1815 request_.url = GURL("http://www.example.org/");
1816 request_.upload_data_stream = &upload_data_stream;
1817 ASSERT_EQ(OK, request_.upload_data_stream->Init(
1818 TestCompletionCallback().callback()));
1819
1820 EXPECT_EQ(OK,
1821 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1822 net_log_.bound(), callback_.callback()));
1823
1824 int result = stream_->SendRequest(headers_, &response_, callback_.callback());
1825
1826 ProcessPacket(ConstructServerAckPacket(1, 0, 0));
1827 SetResponse("200 OK", string());
1828
1829 EXPECT_EQ(ERR_IO_PENDING, result);
1830 EXPECT_EQ(ERR_FAILED, callback_.GetResult(result));
1831
1832 EXPECT_TRUE(AtEof());
1833
1834 // QuicHttpStream::GetTotalSent/ReceivedBytes includes only headers.
1835 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1836 stream_->GetTotalSentBytes());
1837 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1838}
1839
[email protected]f702d572012-12-04 15:56:201840} // namespace test
[email protected]f702d572012-12-04 15:56:201841} // namespace net