blob: f553454b339d93773506e348b20d9a7d0ef0a240 [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
Ryan Hamiltona3ee93a72018-08-01 22:03:085#include "net/quic/quic_http_stream.h"
[email protected]f702d572012-12-04 15:56:206
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
Sebastien Marchand6d0558fd2019-01-25 16:49:3712#include "base/bind.h"
danakjad1777e2016-04-16 00:56:4213#include "base/memory/ptr_util.h"
fdoray92e35a72016-06-10 15:54:5514#include "base/run_loop.h"
Avi Drissman4365a4782018-12-28 19:26:2415#include "base/stl_util.h"
xunjieli188bd402016-03-12 00:17:2516#include "base/strings/string_number_conversions.h"
gabf767595f2016-05-11 18:50:3517#include "base/threading/thread_task_runner_handle.h"
Zhongyi Shic16b4102019-02-12 00:37:4018#include "base/time/default_tick_clock.h"
xunjieli84adaab2016-09-20 01:12:2819#include "base/time/time.h"
mmenkecbc2b712014-10-09 20:29:0720#include "net/base/chunked_upload_data_stream.h"
21#include "net/base/elements_upload_data_stream.h"
David Benjamin0288768a2019-07-22 15:00:2622#include "net/base/load_flags.h"
xunjieli84adaab2016-09-20 01:12:2823#include "net/base/load_timing_info.h"
24#include "net/base/load_timing_info_test_util.h"
[email protected]f702d572012-12-04 15:56:2025#include "net/base/net_errors.h"
26#include "net/base/test_completion_callback.h"
[email protected]b2d26cfd2012-12-11 10:36:0627#include "net/base/upload_bytes_element_reader.h"
[email protected]f702d572012-12-04 15:56:2028#include "net/http/http_response_headers.h"
[email protected]5db452202014-08-19 05:22:1529#include "net/http/transport_security_state.h"
mikecirone8b85c432016-09-08 19:11:0030#include "net/log/net_log_event_type.h"
xunjieli5fafe142016-03-23 23:32:5431#include "net/log/test_net_log.h"
32#include "net/log/test_net_log_util.h"
Victor Vasiliev4f6fb892019-05-31 16:58:3133#include "net/quic/address_utils.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0834#include "net/quic/crypto/proof_verifier_chromium.h"
35#include "net/quic/mock_crypto_client_stream_factory.h"
Ryan Hamiltona1d1f4a2019-06-26 14:43:0436#include "net/quic/platform/impl/quic_test_impl.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0837#include "net/quic/quic_chromium_alarm_factory.h"
38#include "net/quic/quic_chromium_connection_helper.h"
39#include "net/quic/quic_chromium_packet_reader.h"
40#include "net/quic/quic_chromium_packet_writer.h"
41#include "net/quic/quic_http_utils.h"
42#include "net/quic/quic_server_info.h"
43#include "net/quic/quic_stream_factory.h"
44#include "net/quic/quic_test_packet_maker.h"
Ryan Hamilton0d65a8c2019-06-07 00:46:0245#include "net/quic/quic_test_packet_printer.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0846#include "net/quic/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"
Bence Béky94658bf2018-05-11 19:22:5849#include "net/spdy/spdy_http_utils.h"
rch03b7a202016-02-05 00:54:2050#include "net/test/cert_test_util.h"
robpercival214763f2016-07-01 23:27:0151#include "net/test/gtest_util.h"
rsleevia69c79a2016-06-22 03:28:4352#include "net/test/test_data_directory.h"
Bence Béky98447b12018-05-08 03:14:0153#include "net/test/test_with_scoped_task_environment.h"
Victor Vasiliev6bb59d22019-03-08 21:34:5154#include "net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.h"
55#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
56#include "net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h"
57#include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
David Schinazi3f7465c2019-07-12 01:57:0558#include "net/third_party/quiche/src/quic/core/http/spdy_server_push_utils.h"
Victor Vasiliev6bb59d22019-03-08 21:34:5159#include "net/third_party/quiche/src/quic/core/quic_connection.h"
60#include "net/third_party/quiche/src/quic/core/quic_utils.h"
61#include "net/third_party/quiche/src/quic/core/quic_write_blocked_list.h"
Ryan Hamiltona1d1f4a2019-06-26 14:43:0462#include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h"
63#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
Victor Vasiliev6bb59d22019-03-08 21:34:5164#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
65#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
66#include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
67#include "net/third_party/quiche/src/quic/test_tools/mock_random.h"
68#include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
69#include "net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h"
70#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
Victor Vasiliev27cc7712019-01-24 11:50:1471#include "net/third_party/quiche/src/spdy/core/spdy_frame_builder.h"
72#include "net/third_party/quiche/src/spdy/core/spdy_framer.h"
73#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
Ramin Halavati683bcaa92018-02-14 08:42:3974#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
[email protected]f702d572012-12-04 15:56:2075#include "testing/gmock/include/gmock/gmock.h"
76#include "testing/gtest/include/gtest/gtest.h"
77
bnc614a92d32016-04-04 13:56:0778using std::string;
[email protected]f702d572012-12-04 15:56:2079using testing::_;
[email protected]06ff5152013-08-29 01:03:0580using testing::AnyNumber;
81using testing::Return;
[email protected]f702d572012-12-04 15:56:2082
83namespace net {
[email protected]f702d572012-12-04 15:56:2084namespace test {
[email protected]f702d572012-12-04 15:56:2085namespace {
86
[email protected]16ba7742014-08-22 00:57:2587const char kUploadData[] = "Really nifty data!";
rch9ae5b3b2016-02-11 00:36:2988const char kDefaultServerHostName[] = "www.example.org";
rchcd379012017-04-12 21:53:3289const uint16_t kDefaultServerPort = 443;
[email protected]f702d572012-12-04 15:56:2090
Ryan Hamilton8d9ee76e2018-05-29 23:52:5291class TestQuicConnection : public quic::QuicConnection {
[email protected]f702d572012-12-04 15:56:2092 public:
Ryan Hamilton8d9ee76e2018-05-29 23:52:5293 TestQuicConnection(const quic::ParsedQuicVersionVector& versions,
94 quic::QuicConnectionId connection_id,
[email protected]f702d572012-12-04 15:56:2095 IPEndPoint address,
rch12fef552016-01-15 16:26:3196 QuicChromiumConnectionHelper* helper,
rch16c74d1d2016-04-22 06:14:0797 QuicChromiumAlarmFactory* alarm_factory,
Ryan Hamilton8d9ee76e2018-05-29 23:52:5298 quic::QuicPacketWriter* writer)
Victor Vasiliev4f6fb892019-05-31 16:58:3199 : quic::QuicConnection(connection_id,
100 ToQuicSocketAddress(address),
101 helper,
102 alarm_factory,
103 writer,
104 true /* owns_writer */,
105 quic::Perspective::IS_CLIENT,
106 versions) {}
[email protected]f702d572012-12-04 15:56:20107
Ryan Hamilton8d9ee76e2018-05-29 23:52:52108 void SetSendAlgorithm(quic::SendAlgorithmInterface* send_algorithm) {
109 quic::test::QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
[email protected]f702d572012-12-04 15:56:20110 }
111};
112
maksim.sisov84e20c92016-06-23 08:49:34113// UploadDataStream that always returns errors on data read.
114class ReadErrorUploadDataStream : public UploadDataStream {
115 public:
116 enum class FailureMode { SYNC, ASYNC };
117
118 explicit ReadErrorUploadDataStream(FailureMode mode)
Jeremy Romand54000b22019-07-08 18:40:16119 : UploadDataStream(true, 0), async_(mode) {}
maksim.sisov84e20c92016-06-23 08:49:34120 ~ReadErrorUploadDataStream() override {}
121
122 private:
123 void CompleteRead() { UploadDataStream::OnReadCompleted(ERR_FAILED); }
124
125 // UploadDataStream implementation:
tfarina42834112016-09-22 13:38:20126 int InitInternal(const NetLogWithSource& net_log) override { return OK; }
maksim.sisov84e20c92016-06-23 08:49:34127
128 int ReadInternal(IOBuffer* buf, int buf_len) override {
129 if (async_ == FailureMode::ASYNC) {
130 base::ThreadTaskRunnerHandle::Get()->PostTask(
kylecharf4fe5172019-02-15 18:53:49131 FROM_HERE, base::BindOnce(&ReadErrorUploadDataStream::CompleteRead,
132 weak_factory_.GetWeakPtr()));
maksim.sisov84e20c92016-06-23 08:49:34133 return ERR_IO_PENDING;
134 }
135 return ERR_FAILED;
136 }
137
138 void ResetInternal() override {}
139
140 const FailureMode async_;
141
Jeremy Romand54000b22019-07-08 18:40:16142 base::WeakPtrFactory<ReadErrorUploadDataStream> weak_factory_{this};
maksim.sisov84e20c92016-06-23 08:49:34143
144 DISALLOW_COPY_AND_ASSIGN(ReadErrorUploadDataStream);
145};
146
Bence Béky8ddc2492018-06-13 01:02:04147// A helper class that will delete |stream| when the callback is invoked.
xunjieli8dff50b2016-07-22 14:19:06148class DeleteStreamCallback : public TestCompletionCallbackBase {
149 public:
Bence Béky8ddc2492018-06-13 01:02:04150 explicit DeleteStreamCallback(std::unique_ptr<QuicHttpStream> stream)
151 : stream_(std::move(stream)) {}
xunjieli8dff50b2016-07-22 14:19:06152
Bence Béky8ddc2492018-06-13 01:02:04153 CompletionOnceCallback callback() {
154 return base::BindOnce(&DeleteStreamCallback::DeleteStream,
155 base::Unretained(this));
156 }
xunjieli8dff50b2016-07-22 14:19:06157
158 private:
159 void DeleteStream(int result) {
160 stream_.reset();
161 SetResult(result);
162 }
163
164 std::unique_ptr<QuicHttpStream> stream_;
xunjieli8dff50b2016-07-22 14:19:06165};
166
[email protected]f702d572012-12-04 15:56:20167} // namespace
168
[email protected]24e5bc52013-09-18 15:36:58169class QuicHttpStreamPeer {
170 public:
rch08e198572017-05-09 16:56:55171 static QuicChromiumClientStream::Handle* GetQuicChromiumClientStream(
[email protected]24e5bc52013-09-18 15:36:58172 QuicHttpStream* stream) {
rch08e198572017-05-09 16:56:55173 return stream->stream_.get();
[email protected]24e5bc52013-09-18 15:36:58174 }
175};
176
Ryan Hamilton8d9ee76e2018-05-29 23:52:52177class QuicHttpStreamTest : public ::testing::TestWithParam<
Nick Harper23290b82019-05-02 00:02:56178 std::tuple<quic::ParsedQuicVersion, bool>>,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52179 public WithScopedTaskEnvironment {
rchfb47f712017-05-21 03:24:00180 public:
181 void CloseStream(QuicHttpStream* stream, int /*rv*/) { stream->Close(false); }
182
[email protected]f702d572012-12-04 15:56:20183 protected:
[email protected]1e960032013-12-20 19:00:20184 static const bool kFin = true;
185 static const bool kIncludeVersion = true;
186 static const bool kIncludeCongestionFeedback = true;
187
[email protected]f702d572012-12-04 15:56:20188 // Holds a packet to be written to the wire, and the IO mode that should
189 // be used by the mock socket when performing the write.
190 struct PacketToWrite {
Ryan Hamilton8d9ee76e2018-05-29 23:52:52191 PacketToWrite(IoMode mode, quic::QuicReceivedPacket* packet)
rjshaded5ced072015-12-18 19:26:02192 : mode(mode), packet(packet) {}
rtenneti15656ae2016-01-23 03:05:03193 PacketToWrite(IoMode mode, int rv) : mode(mode), packet(nullptr), rv(rv) {}
[email protected]f702d572012-12-04 15:56:20194 IoMode mode;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52195 quic::QuicReceivedPacket* packet;
rtenneti15656ae2016-01-23 03:05:03196 int rv;
[email protected]f702d572012-12-04 15:56:20197 };
198
199 QuicHttpStreamTest()
Yixin Wang079ad542018-01-11 04:06:05200 : version_(std::get<0>(GetParam())),
201 client_headers_include_h2_stream_dependency_(std::get<1>(GetParam())),
Nick Harpera598fc5f2019-06-21 08:46:50202 crypto_config_(
203 quic::test::crypto_test_utils::ProofVerifierForTesting()),
Victor Costan9c7302b2018-08-27 16:39:44204 read_buffer_(base::MakeRefCounted<IOBufferWithSize>(4096)),
Fan Yang32c5a112018-12-10 20:06:33205 promise_id_(GetNthServerInitiatedUnidirectionalStreamId(0)),
206 stream_id_(GetNthClientInitiatedBidirectionalStreamId(0)),
David Schinazic8281052019-01-24 06:14:17207 connection_id_(quic::test::TestConnectionId(2)),
Yixin Wang079ad542018-01-11 04:06:05208 client_maker_(version_,
alyssar2adf3ac2016-05-03 17:12:58209 connection_id_,
210 &clock_,
211 kDefaultServerHostName,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52212 quic::Perspective::IS_CLIENT,
Yixin Wang079ad542018-01-11 04:06:05213 client_headers_include_h2_stream_dependency_),
214 server_maker_(version_,
zhongyi5dbfdd42017-06-20 05:22:15215 connection_id_,
alyssar2adf3ac2016-05-03 17:12:58216 &clock_,
217 kDefaultServerHostName,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52218 quic::Perspective::IS_SERVER,
Yixin Wang079ad542018-01-11 04:06:05219 false),
ckrasic3865ee0f2016-02-29 22:04:56220 random_generator_(0),
Ryan Hamilton0d65a8c2019-06-07 00:46:02221 printer_(version_) {
Ryan Hamiltona1d1f4a2019-06-26 14:43:04222 SetQuicFlag(FLAGS_quic_supports_tls_handshake, true);
martijn21968ea2016-02-24 18:46:20223 IPAddress ip(192, 0, 2, 33);
[email protected]f702d572012-12-04 15:56:20224 peer_addr_ = IPEndPoint(ip, 443);
225 self_addr_ = IPEndPoint(ip, 8435);
Ryan Hamilton8d9ee76e2018-05-29 23:52:52226 clock_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(20));
Ramin Halavati683bcaa92018-02-14 08:42:39227 request_.traffic_annotation =
228 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f702d572012-12-04 15:56:20229 }
230
231 ~QuicHttpStreamTest() {
Renjieba55fae2018-09-20 03:05:16232 session_->CloseSessionOnError(ERR_ABORTED, quic::QUIC_INTERNAL_ERROR,
233 quic::ConnectionCloseBehavior::SILENT_CLOSE);
[email protected]f702d572012-12-04 15:56:20234 for (size_t i = 0; i < writes_.size(); i++) {
235 delete writes_[i].packet;
236 }
237 }
238
239 // Adds a packet to the list of expected writes.
Ryan Hamilton8d9ee76e2018-05-29 23:52:52240 void AddWrite(std::unique_ptr<quic::QuicReceivedPacket> packet) {
[email protected]1e960032013-12-20 19:00:20241 writes_.push_back(PacketToWrite(SYNCHRONOUS, packet.release()));
[email protected]f702d572012-12-04 15:56:20242 }
243
rtenneti15656ae2016-01-23 03:05:03244 void AddWrite(IoMode mode, int rv) {
245 writes_.push_back(PacketToWrite(mode, rv));
246 }
247
[email protected]f702d572012-12-04 15:56:20248 // Returns the packet to be written at position |pos|.
Ryan Hamilton8d9ee76e2018-05-29 23:52:52249 quic::QuicReceivedPacket* GetWrite(size_t pos) { return writes_[pos].packet; }
[email protected]f702d572012-12-04 15:56:20250
251 bool AtEof() {
rch37de576c2015-05-17 20:28:17252 return socket_data_->AllReadDataConsumed() &&
253 socket_data_->AllWriteDataConsumed();
[email protected]f702d572012-12-04 15:56:20254 }
255
Ryan Hamilton8d9ee76e2018-05-29 23:52:52256 void ProcessPacket(std::unique_ptr<quic::QuicReceivedPacket> packet) {
Victor Vasiliev4f6fb892019-05-31 16:58:31257 connection_->ProcessUdpPacket(ToQuicSocketAddress(self_addr_),
258 ToQuicSocketAddress(peer_addr_), *packet);
[email protected]f702d572012-12-04 15:56:20259 }
260
261 // Configures the test fixture to use the list of expected writes.
262 void Initialize() {
263 mock_writes_.reset(new MockWrite[writes_.size()]);
264 for (size_t i = 0; i < writes_.size(); i++) {
rtenneti15656ae2016-01-23 03:05:03265 if (writes_[i].packet == nullptr) {
266 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].rv, i);
267 } else {
268 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].packet->data(),
269 writes_[i].packet->length());
270 }
bnc614a92d32016-04-04 13:56:07271 }
[email protected]f702d572012-12-04 15:56:20272
rtennetibe635732014-10-02 22:51:42273 socket_data_.reset(new StaticSocketDataProvider(
Ryan Sleevib8d7ea02018-05-07 20:01:01274 base::span<MockRead>(),
275 base::make_span(mock_writes_.get(), writes_.size())));
Ryan Hamilton0d65a8c2019-06-07 00:46:02276 socket_data_->set_printer(&printer_);
[email protected]f702d572012-12-04 15:56:20277
danakjad1777e2016-04-16 00:56:42278 std::unique_ptr<MockUDPClientSocket> socket(new MockUDPClientSocket(
xunjielib53b38c2016-03-24 15:54:36279 socket_data_.get(), net_log_.bound().net_log()));
[email protected]e13201d82012-12-12 05:00:32280 socket->Connect(peer_addr_);
[email protected]f702d572012-12-04 15:56:20281 runner_ = new TestTaskRunner(&clock_);
Ryan Hamilton8d9ee76e2018-05-29 23:52:52282 send_algorithm_ = new quic::test::MockSendAlgorithm();
rch7dd15702015-07-01 18:57:57283 EXPECT_CALL(*send_algorithm_, InRecovery()).WillRepeatedly(Return(false));
284 EXPECT_CALL(*send_algorithm_, InSlowStart()).WillRepeatedly(Return(false));
rjshaded5ced072015-12-18 19:26:02285 EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
Dan Zhangf11470172017-09-18 22:02:09286 .Times(testing::AtLeast(1));
Ryan Hamiltona1d1f4a2019-06-26 14:43:04287 EXPECT_CALL(*send_algorithm_, OnCongestionEvent(_, _, _, _, _))
288 .Times(AnyNumber());
rtenneti44f4a2e2015-08-07 14:00:07289 EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
Zhongyi Shica576df2019-04-12 17:43:40290 .WillRepeatedly(Return(quic::kMaxOutgoingPacketSize));
jokulik0e0a00c32016-06-13 21:51:58291 EXPECT_CALL(*send_algorithm_, PacingRate(_))
Ryan Hamilton8d9ee76e2018-05-29 23:52:52292 .WillRepeatedly(Return(quic::QuicBandwidth::Zero()));
Michael Warres74ee3ce2017-10-09 15:26:37293 EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true));
rtenneti44f4a2e2015-08-07 14:00:07294 EXPECT_CALL(*send_algorithm_, BandwidthEstimate())
Ryan Hamilton8d9ee76e2018-05-29 23:52:52295 .WillRepeatedly(Return(quic::QuicBandwidth::Zero()));
rch1e543ec2015-03-29 07:04:40296 EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(AnyNumber());
rch08cae032017-03-29 00:59:15297 EXPECT_CALL(*send_algorithm_, OnApplicationLimited(_)).Times(AnyNumber());
rch0d5bcf62017-05-24 22:48:45298 EXPECT_CALL(*send_algorithm_, GetCongestionControlType())
299 .Times(AnyNumber());
rch16c74d1d2016-04-22 06:14:07300 helper_.reset(
301 new QuicChromiumConnectionHelper(&clock_, &random_generator_));
302 alarm_factory_.reset(new QuicChromiumAlarmFactory(runner_.get(), &clock_));
303
Michael Warres74ee3ce2017-10-09 15:26:37304 connection_ = new TestQuicConnection(
Nick Harper23290b82019-05-02 00:02:56305 quic::test::SupportedVersions(version_), connection_id_, peer_addr_,
306 helper_.get(), alarm_factory_.get(),
Ryan Hamilton9edcf1a2017-11-22 05:55:17307 new QuicChromiumPacketWriter(
308 socket.get(), base::ThreadTaskRunnerHandle::Get().get()));
[email protected]f702d572012-12-04 15:56:20309 connection_->set_visitor(&visitor_);
[email protected]fee17f72013-02-03 07:47:41310 connection_->SetSendAlgorithm(send_algorithm_);
rch03b7a202016-02-05 00:54:20311
312 // Load a certificate that is valid for *.example.org
313 scoped_refptr<X509Certificate> test_cert(
314 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
315 EXPECT_TRUE(test_cert.get());
316
317 verify_details_.cert_verify_result.verified_cert = test_cert;
318 verify_details_.cert_verify_result.is_issued_by_known_root = true;
319 crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details_);
320
xunjieli84adaab2016-09-20 01:12:28321 base::TimeTicks dns_end = base::TimeTicks::Now();
322 base::TimeTicks dns_start = dns_end - base::TimeDelta::FromMilliseconds(1);
ckrasic4f9d88d2015-07-22 22:23:16323 session_.reset(new QuicChromiumClientSession(
xunjielib53b38c2016-03-24 15:54:36324 connection_, std::move(socket),
rtenneti1cd3b162015-09-29 02:58:28325 /*stream_factory=*/nullptr, &crypto_client_stream_factory_, &clock_,
Nick Harper89bc7212018-07-31 19:07:57326 &transport_security_state_, /*ssl_config_service=*/nullptr,
danakjad1777e2016-04-16 00:56:42327 base::WrapUnique(static_cast<QuicServerInfo*>(nullptr)),
Paul Jensen8e3c5d32018-02-19 17:06:33328 QuicSessionKey(kDefaultServerHostName, kDefaultServerPort,
329 PRIVACY_MODE_DISABLED, SocketTag()),
Bence Béky1ceba552019-07-19 17:11:05330 /*require_confirmation=*/false,
331 /*max_allowed_push_id=*/0,
332 /*migrate_session_early_v2=*/false,
Zhongyi Shi757fcce2018-06-27 05:41:27333 /*migrate_session_on_network_change_v2=*/false,
334 /*default_network=*/NetworkChangeNotifier::kInvalidNetworkHandle,
Zhongyi Shie01f2db2019-02-22 19:53:23335 quic::QuicTime::Delta::FromMilliseconds(
Ryan Sleevi2e8255b2019-07-17 21:02:21336 kDefaultRetransmittableOnWireTimeout.InMilliseconds()),
337 /*migrate_idle_session=*/false, kDefaultIdleSessionMigrationPeriod,
338 kMaxTimeOnNonDefaultNetwork,
Zhongyi Shiee760762018-08-01 00:54:29339 kMaxMigrationsToNonDefaultNetworkOnWriteError,
Zhongyi Shi8b1e43f2017-12-13 20:46:30340 kMaxMigrationsToNonDefaultNetworkOnPathDegrading,
Zhongyi Shi5f587cc2017-11-21 23:24:17341 kQuicYieldAfterPacketsRead,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52342 quic::QuicTime::Delta::FromMilliseconds(
343 kQuicYieldAfterDurationMilliseconds),
Zhongyi Shidbce7f412019-02-01 23:16:29344 /*go_away_on_path_degrading*/ false,
Yixin Wang079ad542018-01-11 04:06:05345 client_headers_include_h2_stream_dependency_, /*cert_verify_flags=*/0,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52346 quic::test::DefaultQuicConfig(), &crypto_config_, "CONNECTION_UNKNOWN",
347 dns_start, dns_end, &push_promise_index_, nullptr,
Zhongyi Shic16b4102019-02-12 00:37:40348 base::DefaultTickClock::GetInstance(),
xunjieli84adaab2016-09-20 01:12:28349 base::ThreadTaskRunnerHandle::Get().get(),
xunjieli5fafe142016-03-23 23:32:54350 /*socket_performance_watcher=*/nullptr, net_log_.bound().net_log()));
rtennetid39bd762015-06-12 01:05:52351 session_->Initialize();
xunjieli100937eb52016-09-15 20:09:37352 TestCompletionCallback callback;
rchf0b18c8a2017-05-05 19:31:57353
rch433bf5f2017-02-14 04:10:47354 session_->CryptoConnect(callback.callback());
Ryan Hamilton6c2a2a82017-12-15 02:06:28355 stream_ = std::make_unique<QuicHttpStream>(
356 session_->CreateHandle(HostPortPair("www.example.org", 443)));
357 promised_stream_ = std::make_unique<QuicHttpStream>(
358 session_->CreateHandle(HostPortPair("www.example.org", 443)));
ckrasic3865ee0f2016-02-29 22:04:56359 push_promise_[":path"] = "/bar";
360 push_promise_[":authority"] = "www.example.org";
361 push_promise_[":version"] = "HTTP/1.1";
362 push_promise_[":method"] = "GET";
363 push_promise_[":scheme"] = "https";
364
365 promised_response_[":status"] = "200 OK";
366 promised_response_[":version"] = "HTTP/1.1";
367 promised_response_["content-type"] = "text/plain";
368
David Schinazi3f7465c2019-07-12 01:57:05369 promise_url_ =
370 quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
[email protected]6cca996b2013-01-25 07:43:36371 }
372
bnc614a92d32016-04-04 13:56:07373 void SetRequest(const string& method,
374 const string& path,
[email protected]1e960032013-12-20 19:00:20375 RequestPriority priority) {
rchcd379012017-04-12 21:53:32376 request_headers_ = client_maker_.GetRequestHeaders(method, "https", path);
[email protected]6cca996b2013-01-25 07:43:36377 }
378
bnc614a92d32016-04-04 13:56:07379 void SetResponse(const string& status, const string& body) {
alyssar2adf3ac2016-05-03 17:12:58380 response_headers_ = server_maker_.GetResponseHeaders(status);
[email protected]92bf17c2014-03-03 21:14:03381 response_data_ = body;
[email protected]6cca996b2013-01-25 07:43:36382 }
[email protected]f702d572012-12-04 15:56:20383
Ryan Hamilton8d9ee76e2018-05-29 23:52:52384 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructDataPacket(
Fan Yangac867502019-01-28 21:10:23385 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52386 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56387 bool should_include_version,
388 bool fin,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52389 quic::QuicStringPiece data,
alyssar2adf3ac2016-05-03 17:12:58390 QuicTestPacketMaker* maker) {
391 return maker->MakeDataPacket(packet_number, stream_id,
Ryan Hamilton7505eb92019-06-08 00:22:17392 should_include_version, fin, data);
ckrasic3865ee0f2016-02-29 22:04:56393 }
394
Ryan Hamilton8d9ee76e2018-05-29 23:52:52395 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientDataPacket(
Fan Yangac867502019-01-28 21:10:23396 uint64_t packet_number,
[email protected]e8ff26842013-03-22 21:02:05397 bool should_include_version,
[email protected]f702d572012-12-04 15:56:20398 bool fin,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52399 quic::QuicStringPiece data) {
Ryan Hamilton7505eb92019-06-08 00:22:17400 return client_maker_.MakeDataPacket(packet_number, stream_id_,
401 should_include_version, fin, data);
alyssar2adf3ac2016-05-03 17:12:58402 }
403
Renjief49758b2019-01-11 23:32:41404 std::unique_ptr<quic::QuicReceivedPacket>
405 ConstructClientMultipleDataFramesPacket(
Fan Yangac867502019-01-28 21:10:23406 uint64_t packet_number,
Renjief49758b2019-01-11 23:32:41407 bool should_include_version,
408 bool fin,
Renjief49758b2019-01-11 23:32:41409 const std::vector<std::string>& data) {
410 return client_maker_.MakeMultipleDataFramesPacket(
Ryan Hamilton7505eb92019-06-08 00:22:17411 packet_number, stream_id_, should_include_version, fin, data);
Renjief49758b2019-01-11 23:32:41412 }
413
Ryan Hamilton8d9ee76e2018-05-29 23:52:52414 std::unique_ptr<quic::QuicReceivedPacket> ConstructServerDataPacket(
Fan Yangac867502019-01-28 21:10:23415 uint64_t packet_number,
alyssar2adf3ac2016-05-03 17:12:58416 bool should_include_version,
417 bool fin,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52418 quic::QuicStringPiece data) {
Ryan Hamilton7505eb92019-06-08 00:22:17419 return server_maker_.MakeDataPacket(packet_number, stream_id_,
420 should_include_version, fin, data);
ckrasic3865ee0f2016-02-29 22:04:56421 }
422
Ryan Hamilton8d9ee76e2018-05-29 23:52:52423 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23424 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52425 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56426 bool should_include_version,
427 bool fin,
428 RequestPriority request_priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02429 size_t* spdy_headers_frame_length) {
Yixin Wang7a3f1b8d2018-01-17 21:40:48430 return InnerConstructRequestHeadersPacket(
431 packet_number, stream_id, should_include_version, fin, request_priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02432 0, spdy_headers_frame_length);
Yixin Wang7a3f1b8d2018-01-17 21:40:48433 }
434
Ryan Hamilton8d9ee76e2018-05-29 23:52:52435 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23436 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52437 quic::QuicStreamId stream_id,
Yixin Wang7a3f1b8d2018-01-17 21:40:48438 bool should_include_version,
439 bool fin,
440 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52441 quic::QuicStreamId parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02442 size_t* spdy_headers_frame_length) {
Ryan Hamilton0239aac2018-05-19 00:03:13443 spdy::SpdyPriority priority =
ckrasic3865ee0f2016-02-29 22:04:56444 ConvertRequestPriorityToQuicPriority(request_priority);
alyssar2adf3ac2016-05-03 17:12:58445 return client_maker_.MakeRequestHeadersPacket(
ckrasic3865ee0f2016-02-29 22:04:56446 packet_number, stream_id, should_include_version, fin, priority,
Yixin Wang7a3f1b8d2018-01-17 21:40:48447 std::move(request_headers_), parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02448 spdy_headers_frame_length);
[email protected]f702d572012-12-04 15:56:20449 }
450
Ryan Hamilton8d9ee76e2018-05-29 23:52:52451 std::unique_ptr<quic::QuicReceivedPacket>
Yixin Wange7ecc472018-03-06 19:00:25452 ConstructRequestHeadersAndDataFramesPacket(
Fan Yangac867502019-01-28 21:10:23453 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52454 quic::QuicStreamId stream_id,
Yixin Wange7ecc472018-03-06 19:00:25455 bool should_include_version,
456 bool fin,
457 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52458 quic::QuicStreamId parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25459 size_t* spdy_headers_frame_length,
460 const std::vector<std::string>& data_writes) {
Ryan Hamilton0239aac2018-05-19 00:03:13461 spdy::SpdyPriority priority =
Yixin Wange7ecc472018-03-06 19:00:25462 ConvertRequestPriorityToQuicPriority(request_priority);
463 return client_maker_.MakeRequestHeadersAndMultipleDataFramesPacket(
464 packet_number, stream_id, should_include_version, fin, priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02465 std::move(request_headers_), parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25466 spdy_headers_frame_length, data_writes);
467 }
468
Ryan Hamilton8d9ee76e2018-05-29 23:52:52469 std::unique_ptr<quic::QuicReceivedPacket> ConstructRequestAndRstPacket(
Fan Yangac867502019-01-28 21:10:23470 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52471 quic::QuicStreamId stream_id,
Yixin Wange7ecc472018-03-06 19:00:25472 bool should_include_version,
473 bool fin,
474 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52475 quic::QuicStreamId parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25476 size_t* spdy_headers_frame_length,
Ryan Hamiltonb5d4c5a2019-06-21 22:08:41477 quic::QuicRstStreamErrorCode error_code) {
Ryan Hamilton0239aac2018-05-19 00:03:13478 spdy::SpdyPriority priority =
Yixin Wange7ecc472018-03-06 19:00:25479 ConvertRequestPriorityToQuicPriority(request_priority);
480 return client_maker_.MakeRequestHeadersAndRstPacket(
481 packet_number, stream_id, should_include_version, fin, priority,
482 std::move(request_headers_), parent_stream_id,
Ryan Hamiltonb5d4c5a2019-06-21 22:08:41483 spdy_headers_frame_length, error_code);
Yixin Wange7ecc472018-03-06 19:00:25484 }
485
Ryan Hamilton8d9ee76e2018-05-29 23:52:52486 std::unique_ptr<quic::QuicReceivedPacket> ConstructRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23487 uint64_t packet_number,
rtennetif4bdb542015-01-21 14:33:05488 bool fin,
sclittlec4dc1a32015-09-24 00:15:45489 RequestPriority request_priority,
490 size_t* spdy_headers_frame_length) {
ckrasic3865ee0f2016-02-29 22:04:56491 return InnerConstructRequestHeadersPacket(
492 packet_number, stream_id_, kIncludeVersion, fin, request_priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02493 spdy_headers_frame_length);
ckrasic3865ee0f2016-02-29 22:04:56494 }
495
Ryan Hamilton8d9ee76e2018-05-29 23:52:52496 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructResponseHeadersPacket(
Fan Yangac867502019-01-28 21:10:23497 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52498 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56499 bool fin,
500 size_t* spdy_headers_frame_length) {
alyssar2adf3ac2016-05-03 17:12:58501 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26502 packet_number, stream_id, !kIncludeVersion, fin,
Ryan Hamilton0d65a8c2019-06-07 00:46:02503 std::move(response_headers_), spdy_headers_frame_length);
[email protected]1e960032013-12-20 19:00:20504 }
505
Ryan Hamilton8d9ee76e2018-05-29 23:52:52506 std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseHeadersPacket(
Fan Yangac867502019-01-28 21:10:23507 uint64_t packet_number,
sclittlec4dc1a32015-09-24 00:15:45508 bool fin,
509 size_t* spdy_headers_frame_length) {
ckrasic3865ee0f2016-02-29 22:04:56510 return InnerConstructResponseHeadersPacket(packet_number, stream_id_, fin,
511 spdy_headers_frame_length);
[email protected]1e960032013-12-20 19:00:20512 }
513
Ryan Hamilton8d9ee76e2018-05-29 23:52:52514 std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseTrailersPacket(
Fan Yangac867502019-01-28 21:10:23515 uint64_t packet_number,
xunjieli34291fe12016-03-02 13:58:38516 bool fin,
Ryan Hamilton0239aac2018-05-19 00:03:13517 spdy::SpdyHeaderBlock trailers,
Ryan Hamilton0d65a8c2019-06-07 00:46:02518 size_t* spdy_headers_frame_length) {
alyssar2adf3ac2016-05-03 17:12:58519 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26520 packet_number, stream_id_, !kIncludeVersion, fin, std::move(trailers),
Ryan Hamilton0d65a8c2019-06-07 00:46:02521 spdy_headers_frame_length);
xunjieli34291fe12016-03-02 13:58:38522 }
523
Ryan Hamilton8d9ee76e2018-05-29 23:52:52524 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientRstStreamPacket(
Fan Yangac867502019-01-28 21:10:23525 uint64_t packet_number) {
alyssara72f5352016-10-20 12:45:16526 return client_maker_.MakeRstPacket(packet_number, true, stream_id_,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52527 quic::QUIC_RST_ACKNOWLEDGEMENT);
[email protected]06ff5152013-08-29 01:03:05528 }
529
Ryan Hamilton8d9ee76e2018-05-29 23:52:52530 std::unique_ptr<quic::QuicReceivedPacket>
Fan Yangac867502019-01-28 21:10:23531 ConstructClientRstStreamCancelledPacket(uint64_t packet_number) {
alyssar2adf3ac2016-05-03 17:12:58532 return client_maker_.MakeRstPacket(packet_number, !kIncludeVersion,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52533 stream_id_, quic::QUIC_STREAM_CANCELLED);
rtenneti6bd660b2015-07-18 00:19:53534 }
535
Ryan Hamilton8d9ee76e2018-05-29 23:52:52536 std::unique_ptr<quic::QuicReceivedPacket>
Fan Yangac867502019-01-28 21:10:23537 ConstructClientRstStreamVaryMismatchPacket(uint64_t packet_number) {
alyssar2adf3ac2016-05-03 17:12:58538 return client_maker_.MakeRstPacket(packet_number, !kIncludeVersion,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52539 promise_id_,
540 quic::QUIC_PROMISE_VARY_MISMATCH);
ckrasic3865ee0f2016-02-29 22:04:56541 }
542
Fan Yang550c6282018-06-22 18:53:25543 std::unique_ptr<quic::QuicReceivedPacket>
544 ConstructClientRstStreamVaryMismatchAndRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23545 uint64_t packet_number,
Fan Yang550c6282018-06-22 18:53:25546 quic::QuicStreamId stream_id,
547 bool should_include_version,
548 bool fin,
549 RequestPriority request_priority,
550 quic::QuicStreamId parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02551 size_t* spdy_headers_frame_length) {
Fan Yang550c6282018-06-22 18:53:25552 spdy::SpdyPriority priority =
553 ConvertRequestPriorityToQuicPriority(request_priority);
554 return client_maker_.MakeRstAndRequestHeadersPacket(
555 packet_number, should_include_version, promise_id_,
556 quic::QUIC_PROMISE_VARY_MISMATCH, stream_id, fin, priority,
557 std::move(request_headers_), parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02558 spdy_headers_frame_length);
Fan Yang550c6282018-06-22 18:53:25559 }
560
Ryan Hamilton8d9ee76e2018-05-29 23:52:52561 std::unique_ptr<quic::QuicReceivedPacket> ConstructAckAndRstStreamPacket(
Fan Yangac867502019-01-28 21:10:23562 uint64_t packet_number,
563 uint64_t largest_received,
564 uint64_t smallest_received,
565 uint64_t least_unacked) {
alyssar2adf3ac2016-05-03 17:12:58566 return client_maker_.MakeAckAndRstPacket(
Ryan Hamilton8d9ee76e2018-05-29 23:52:52567 packet_number, !kIncludeVersion, stream_id_,
568 quic::QUIC_STREAM_CANCELLED, largest_received, smallest_received,
569 least_unacked, !kIncludeCongestionFeedback);
xunjieli34291fe12016-03-02 13:58:38570 }
571
Ryan Hamilton8d9ee76e2018-05-29 23:52:52572 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientRstStreamErrorPacket(
Fan Yangac867502019-01-28 21:10:23573 uint64_t packet_number,
maksim.sisov84e20c92016-06-23 08:49:34574 bool include_version) {
575 return client_maker_.MakeRstPacket(packet_number, include_version,
576 stream_id_,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52577 quic::QUIC_ERROR_PROCESSING_STREAM);
maksim.sisov84e20c92016-06-23 08:49:34578 }
579
Ryan Hamilton8d9ee76e2018-05-29 23:52:52580 std::unique_ptr<quic::QuicReceivedPacket> ConstructAckAndRstStreamPacket(
Fan Yangac867502019-01-28 21:10:23581 uint64_t packet_number) {
Renjie90e808e2019-01-24 07:24:04582 return ConstructAckAndRstStreamPacket(packet_number, 2, 1, 2);
[email protected]c5e1aca2014-01-30 04:03:04583 }
584
Ryan Hamilton8d9ee76e2018-05-29 23:52:52585 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientAckPacket(
Fan Yangac867502019-01-28 21:10:23586 uint64_t packet_number,
587 uint64_t largest_received,
588 uint64_t smallest_received,
589 uint64_t least_unacked) {
alyssar2adf3ac2016-05-03 17:12:58590 return client_maker_.MakeAckPacket(packet_number, largest_received,
wangyix6444ffe2017-04-25 17:49:49591 smallest_received, least_unacked,
alyssar2adf3ac2016-05-03 17:12:58592 !kIncludeCongestionFeedback);
593 }
594
Ryan Hamilton8d9ee76e2018-05-29 23:52:52595 std::unique_ptr<quic::QuicReceivedPacket> ConstructServerAckPacket(
Fan Yangac867502019-01-28 21:10:23596 uint64_t packet_number,
597 uint64_t largest_received,
598 uint64_t smallest_received,
599 uint64_t least_unacked) {
alyssar2adf3ac2016-05-03 17:12:58600 return server_maker_.MakeAckPacket(packet_number, largest_received,
wangyix6444ffe2017-04-25 17:49:49601 smallest_received, least_unacked,
alyssar2adf3ac2016-05-03 17:12:58602 !kIncludeCongestionFeedback);
[email protected]63534512012-12-23 18:49:00603 }
604
Ryan Hamilton8d9ee76e2018-05-29 23:52:52605 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientPriorityPacket(
Fan Yangac867502019-01-28 21:10:23606 uint64_t packet_number,
Yixin Wangb470bc882018-02-15 18:43:57607 bool should_include_version,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52608 quic::QuicStreamId id,
609 quic::QuicStreamId parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02610 RequestPriority request_priority) {
Yixin Wangb470bc882018-02-15 18:43:57611 return client_maker_.MakePriorityPacket(
612 packet_number, should_include_version, id, parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02613 ConvertRequestPriorityToQuicPriority(request_priority));
Yixin Wangb470bc882018-02-15 18:43:57614 }
615
Ryan Hamilton0d65a8c2019-06-07 00:46:02616 std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket() {
617 return client_maker_.MakeInitialSettingsPacket(1);
fayang3bcb8b502016-12-07 21:44:37618 }
619
Victor Vasiliev076657c2019-03-12 02:46:43620 std::string ConstructDataHeader(size_t body_len) {
Nick Harper23290b82019-05-02 00:02:56621 if (version_.transport_version != quic::QUIC_VERSION_99) {
Renjief49758b2019-01-11 23:32:41622 return "";
623 }
624 quic::HttpEncoder encoder;
625 std::unique_ptr<char[]> buffer;
626 auto header_length = encoder.SerializeDataFrameHeader(body_len, &buffer);
Victor Vasiliev076657c2019-03-12 02:46:43627 return std::string(buffer.get(), header_length);
Renjief49758b2019-01-11 23:32:41628 }
629
Ryan Hamilton8d9ee76e2018-05-29 23:52:52630 void ReceivePromise(quic::QuicStreamId id) {
631 auto headers = quic::test::AsHeaderList(push_promise_);
rch08e198572017-05-09 16:56:55632 QuicChromiumClientStream::Handle* stream =
ckrasic3865ee0f2016-02-29 22:04:56633 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
ckrasic32b17dcd2016-10-31 06:15:35634 stream->OnPromiseHeaderList(id, headers.uncompressed_header_bytes(),
635 headers);
ckrasic3865ee0f2016-02-29 22:04:56636 }
637
xunjieli84adaab2016-09-20 01:12:28638 void ExpectLoadTimingValid(const LoadTimingInfo& load_timing_info,
xunjieli100937eb52016-09-15 20:09:37639 bool session_reused) {
640 EXPECT_EQ(session_reused, load_timing_info.socket_reused);
xunjieli84adaab2016-09-20 01:12:28641 if (session_reused) {
642 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
643 } else {
644 ExpectConnectTimingHasTimes(
645 load_timing_info.connect_timing,
646 CONNECT_TIMING_HAS_SSL_TIMES | CONNECT_TIMING_HAS_DNS_TIMES);
647 }
648 ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info);
xunjieli100937eb52016-09-15 20:09:37649 }
650
Fan Yang32c5a112018-12-10 20:06:33651 quic::QuicStreamId GetNthClientInitiatedBidirectionalStreamId(int n) {
Nick Harper23290b82019-05-02 00:02:56652 return quic::test::GetNthClientInitiatedBidirectionalStreamId(
653 version_.transport_version, n);
ckrasicbf2f59c2017-05-04 23:54:36654 }
655
Fan Yang32c5a112018-12-10 20:06:33656 quic::QuicStreamId GetNthServerInitiatedUnidirectionalStreamId(int n) {
Nick Harper23290b82019-05-02 00:02:56657 return quic::test::GetNthServerInitiatedUnidirectionalStreamId(
658 version_.transport_version, n);
ckrasicbf2f59c2017-05-04 23:54:36659 }
660
Ryan Hamiltona1d1f4a2019-06-26 14:43:04661 QuicFlagSaver saver_;
662
Nick Harper23290b82019-05-02 00:02:56663 const quic::ParsedQuicVersion version_;
Yixin Wang079ad542018-01-11 04:06:05664 const bool client_headers_include_h2_stream_dependency_;
665
xunjieli5fafe142016-03-23 23:32:54666 BoundTestNetLog net_log_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52667 quic::test::MockSendAlgorithm* send_algorithm_;
[email protected]f702d572012-12-04 15:56:20668 scoped_refptr<TestTaskRunner> runner_;
danakjad1777e2016-04-16 00:56:42669 std::unique_ptr<MockWrite[]> mock_writes_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52670 quic::MockClock clock_;
[email protected]f702d572012-12-04 15:56:20671 TestQuicConnection* connection_;
danakjad1777e2016-04-16 00:56:42672 std::unique_ptr<QuicChromiumConnectionHelper> helper_;
rch16c74d1d2016-04-22 06:14:07673 std::unique_ptr<QuicChromiumAlarmFactory> alarm_factory_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52674 testing::StrictMock<quic::test::MockQuicConnectionVisitor> visitor_;
rch97827ee2017-05-24 23:49:12675 std::unique_ptr<UploadDataStream> upload_data_stream_;
danakjad1777e2016-04-16 00:56:42676 std::unique_ptr<QuicHttpStream> stream_;
[email protected]5db452202014-08-19 05:22:15677 TransportSecurityState transport_security_state_;
danakjad1777e2016-04-16 00:56:42678 std::unique_ptr<QuicChromiumClientSession> session_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52679 quic::QuicCryptoClientConfig crypto_config_;
[email protected]f702d572012-12-04 15:56:20680 TestCompletionCallback callback_;
681 HttpRequestInfo request_;
682 HttpRequestHeaders headers_;
683 HttpResponseInfo response_;
684 scoped_refptr<IOBufferWithSize> read_buffer_;
Ryan Hamilton0239aac2018-05-19 00:03:13685 spdy::SpdyHeaderBlock request_headers_;
686 spdy::SpdyHeaderBlock response_headers_;
bnc614a92d32016-04-04 13:56:07687 string request_data_;
688 string response_data_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52689 quic::QuicClientPushPromiseIndex push_promise_index_;
[email protected]f702d572012-12-04 15:56:20690
ckrasic3865ee0f2016-02-29 22:04:56691 // For server push testing
danakjad1777e2016-04-16 00:56:42692 std::unique_ptr<QuicHttpStream> promised_stream_;
Ryan Hamilton0239aac2018-05-19 00:03:13693 spdy::SpdyHeaderBlock push_promise_;
694 spdy::SpdyHeaderBlock promised_response_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52695 const quic::QuicStreamId promise_id_;
ckrasic3865ee0f2016-02-29 22:04:56696 string promise_url_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52697 const quic::QuicStreamId stream_id_;
ckrasic3865ee0f2016-02-29 22:04:56698
Ryan Hamilton8d9ee76e2018-05-29 23:52:52699 const quic::QuicConnectionId connection_id_;
alyssar2adf3ac2016-05-03 17:12:58700 QuicTestPacketMaker client_maker_;
701 QuicTestPacketMaker server_maker_;
[email protected]f702d572012-12-04 15:56:20702 IPEndPoint self_addr_;
703 IPEndPoint peer_addr_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52704 quic::test::MockRandom random_generator_;
rch03b7a202016-02-05 00:54:20705 ProofVerifyDetailsChromium verify_details_;
[email protected]e8ff26842013-03-22 21:02:05706 MockCryptoClientStreamFactory crypto_client_stream_factory_;
danakjad1777e2016-04-16 00:56:42707 std::unique_ptr<StaticSocketDataProvider> socket_data_;
Ryan Hamilton0d65a8c2019-06-07 00:46:02708 QuicPacketPrinter printer_;
[email protected]f702d572012-12-04 15:56:20709 std::vector<PacketToWrite> writes_;
710};
711
Victor Costane635086f2019-01-27 05:20:30712INSTANTIATE_TEST_SUITE_P(
Bence Békyce380cb2018-04-26 23:39:55713 VersionIncludeStreamDependencySequence,
Yixin Wang079ad542018-01-11 04:06:05714 QuicHttpStreamTest,
Ryan Hamiltona1d1f4a2019-06-26 14:43:04715 ::testing::Combine(::testing::ValuesIn(quic::AllSupportedVersions()),
Nick Harper23290b82019-05-02 00:02:56716 ::testing::Bool()));
[email protected]1e960032013-12-20 19:00:20717
718TEST_P(QuicHttpStreamTest, RenewStreamForAuth) {
[email protected]ed3fc15d2013-03-08 18:37:44719 Initialize();
rtennetibe635732014-10-02 22:51:42720 EXPECT_EQ(nullptr, stream_->RenewStreamForAuth());
[email protected]f702d572012-12-04 15:56:20721}
722
mmenkebd84c392015-09-02 14:12:34723TEST_P(QuicHttpStreamTest, CanReuseConnection) {
[email protected]ed3fc15d2013-03-08 18:37:44724 Initialize();
mmenkebd84c392015-09-02 14:12:34725 EXPECT_FALSE(stream_->CanReuseConnection());
[email protected]f702d572012-12-04 15:56:20726}
727
jri231c2972016-03-08 19:50:11728TEST_P(QuicHttpStreamTest, DisableConnectionMigrationForStream) {
Zhongyi Shibb28b1f2018-07-18 02:41:26729 request_.load_flags |= LOAD_DISABLE_CONNECTION_MIGRATION_TO_CELLULAR;
jri231c2972016-03-08 19:50:11730 Initialize();
xunjieli5fafe142016-03-23 23:32:54731 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27732 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:54733 net_log_.bound(), callback_.callback()));
rch08e198572017-05-09 16:56:55734 QuicChromiumClientStream::Handle* client_stream =
jri231c2972016-03-08 19:50:11735 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
Zhongyi Shibb28b1f2018-07-18 02:41:26736 EXPECT_FALSE(client_stream->can_migrate_to_cellular_network());
jri231c2972016-03-08 19:50:11737}
738
[email protected]1e960032013-12-20 19:00:20739TEST_P(QuicHttpStreamTest, GetRequest) {
740 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:45741 size_t spdy_request_header_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:02742 AddWrite(ConstructInitialSettingsPacket());
fayang3bcb8b502016-12-07 21:44:37743 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33744 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:02745 DEFAULT_PRIORITY, &spdy_request_header_frame_length));
fayang3bcb8b502016-12-07 21:44:37746
[email protected]f702d572012-12-04 15:56:20747 Initialize();
748
749 request_.method = "GET";
rchcd379012017-04-12 21:53:32750 request_.url = GURL("https://www.example.org/");
[email protected]f702d572012-12-04 15:56:20751
xunjieli100937eb52016-09-15 20:09:37752 // Make sure getting load timing from the stream early does not crash.
753 LoadTimingInfo load_timing_info;
754 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
755
xunjieli5fafe142016-03-23 23:32:54756 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27757 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:54758 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:02759 EXPECT_EQ(OK,
760 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20761
762 // Ack the request.
Renjie90e808e2019-01-24 07:24:04763 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]f702d572012-12-04 15:56:20764
robpercival214763f2016-07-01 23:27:01765 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
766 IsError(ERR_IO_PENDING));
[email protected]f702d572012-12-04 15:56:20767
bnc614a92d32016-04-04 13:56:07768 SetResponse("404 Not Found", string());
sclittlec4dc1a32015-09-24 00:15:45769 size_t spdy_response_header_frame_length;
770 ProcessPacket(ConstructResponseHeadersPacket(
771 2, kFin, &spdy_response_header_frame_length));
[email protected]f702d572012-12-04 15:56:20772
773 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:01774 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]cadac622013-06-11 16:46:36775 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:20776 EXPECT_EQ(404, response_.headers->response_code());
777 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
[email protected]6ed67432014-06-24 01:53:53778 EXPECT_FALSE(response_.response_time.is_null());
779 EXPECT_FALSE(response_.request_time.is_null());
[email protected]f702d572012-12-04 15:56:20780
781 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:02782 EXPECT_EQ(0,
783 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
784 callback_.callback()));
[email protected]f702d572012-12-04 15:56:20785 EXPECT_TRUE(stream_->IsResponseBodyComplete());
786 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:10787
xunjieli100937eb52016-09-15 20:09:37788 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
xunjieli84adaab2016-09-20 01:12:28789 ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
xunjieli100937eb52016-09-15 20:09:37790
sclittle1edeeb22015-09-02 20:46:10791 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:45792 // headers and payload.
793 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
794 stream_->GetTotalSentBytes());
795 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length),
796 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:20797}
798
xunjieli100937eb52016-09-15 20:09:37799TEST_P(QuicHttpStreamTest, LoadTimingTwoRequests) {
800 SetRequest("GET", "/", DEFAULT_PRIORITY);
801 size_t spdy_request_header_frame_length;
802
Ryan Hamilton0d65a8c2019-06-07 00:46:02803 AddWrite(ConstructInitialSettingsPacket());
xunjieli100937eb52016-09-15 20:09:37804 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33805 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:02806 DEFAULT_PRIORITY, &spdy_request_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37807
808 // SetRequest() again for second request as |request_headers_| was moved.
809 SetRequest("GET", "/", DEFAULT_PRIORITY);
810 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33811 3, GetNthClientInitiatedBidirectionalStreamId(1), kIncludeVersion, kFin,
812 DEFAULT_PRIORITY, GetNthClientInitiatedBidirectionalStreamId(0),
Ryan Hamilton0d65a8c2019-06-07 00:46:02813 &spdy_request_header_frame_length));
Renjie90e808e2019-01-24 07:24:04814 AddWrite(ConstructClientAckPacket(4, 3, 1, 2)); // Ack the responses.
xunjieli100937eb52016-09-15 20:09:37815
816 Initialize();
817
818 request_.method = "GET";
rchcd379012017-04-12 21:53:32819 request_.url = GURL("https://www.example.org/");
xunjieli100937eb52016-09-15 20:09:37820 // Start first request.
821 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27822 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli100937eb52016-09-15 20:09:37823 net_log_.bound(), callback_.callback()));
824 EXPECT_EQ(OK,
825 stream_->SendRequest(headers_, &response_, callback_.callback()));
826
827 // Start a second request.
Ryan Hamilton6c2a2a82017-12-15 02:06:28828 QuicHttpStream stream2(
829 session_->CreateHandle(HostPortPair("www.example.org", 443)));
xunjieli100937eb52016-09-15 20:09:37830 TestCompletionCallback callback2;
831 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27832 stream2.InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli100937eb52016-09-15 20:09:37833 net_log_.bound(), callback2.callback()));
834 EXPECT_EQ(OK,
835 stream2.SendRequest(headers_, &response_, callback2.callback()));
836
837 // Ack both requests.
Renjie90e808e2019-01-24 07:24:04838 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
xunjieli100937eb52016-09-15 20:09:37839
840 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
841 IsError(ERR_IO_PENDING));
842 size_t spdy_response_header_frame_length;
843 SetResponse("200 OK", string());
844 ProcessPacket(InnerConstructResponseHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33845 2, GetNthClientInitiatedBidirectionalStreamId(0), kFin,
ckrasicbf2f59c2017-05-04 23:54:36846 &spdy_response_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37847
848 // Now that the headers have been processed, the callback will return.
849 EXPECT_THAT(callback_.WaitForResult(), IsOk());
850 EXPECT_EQ(200, response_.headers->response_code());
851
852 // There is no body, so this should return immediately.
853 EXPECT_EQ(0,
854 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
855 callback_.callback()));
856 EXPECT_TRUE(stream_->IsResponseBodyComplete());
857
858 LoadTimingInfo load_timing_info;
859 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
xunjieli84adaab2016-09-20 01:12:28860 ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
xunjieli100937eb52016-09-15 20:09:37861
862 // SetResponse() again for second request as |response_headers_| was moved.
863 SetResponse("200 OK", string());
864 EXPECT_THAT(stream2.ReadResponseHeaders(callback2.callback()),
865 IsError(ERR_IO_PENDING));
866
867 ProcessPacket(InnerConstructResponseHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33868 3, GetNthClientInitiatedBidirectionalStreamId(1), kFin,
ckrasicbf2f59c2017-05-04 23:54:36869 &spdy_response_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37870
871 EXPECT_THAT(callback2.WaitForResult(), IsOk());
872
873 // There is no body, so this should return immediately.
874 EXPECT_EQ(0,
875 stream2.ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
876 callback2.callback()));
877 EXPECT_TRUE(stream2.IsResponseBodyComplete());
878
879 LoadTimingInfo load_timing_info2;
880 EXPECT_TRUE(stream2.GetLoadTimingInfo(&load_timing_info2));
xunjieli84adaab2016-09-20 01:12:28881 ExpectLoadTimingValid(load_timing_info2, /*session_reused=*/true);
xunjieli100937eb52016-09-15 20:09:37882}
883
xunjieli34291fe12016-03-02 13:58:38884// QuicHttpStream does not currently support trailers. It should ignore
885// trailers upon receiving them.
886TEST_P(QuicHttpStreamTest, GetRequestWithTrailers) {
887 SetRequest("GET", "/", DEFAULT_PRIORITY);
888 size_t spdy_request_header_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:02889 AddWrite(ConstructInitialSettingsPacket());
fayang3bcb8b502016-12-07 21:44:37890 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33891 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:02892 DEFAULT_PRIORITY, &spdy_request_header_frame_length));
Renjie90e808e2019-01-24 07:24:04893 AddWrite(ConstructClientAckPacket(3, 3, 1, 2)); // Ack the data packet.
xunjieli34291fe12016-03-02 13:58:38894
895 Initialize();
896
897 request_.method = "GET";
rchcd379012017-04-12 21:53:32898 request_.url = GURL("https://www.example.org/");
xunjieli34291fe12016-03-02 13:58:38899
xunjieli5fafe142016-03-23 23:32:54900 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27901 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:54902 net_log_.bound(), callback_.callback()));
903
xunjieli34291fe12016-03-02 13:58:38904 EXPECT_EQ(OK,
905 stream_->SendRequest(headers_, &response_, callback_.callback()));
xunjieli34291fe12016-03-02 13:58:38906 // Ack the request.
Renjie90e808e2019-01-24 07:24:04907 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
xunjieli34291fe12016-03-02 13:58:38908
robpercival214763f2016-07-01 23:27:01909 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
910 IsError(ERR_IO_PENDING));
xunjieli34291fe12016-03-02 13:58:38911
bnc614a92d32016-04-04 13:56:07912 SetResponse("200 OK", string());
xunjieli34291fe12016-03-02 13:58:38913
914 // Send the response headers.
915 size_t spdy_response_header_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:02916 ProcessPacket(ConstructResponseHeadersPacket(
917 2, !kFin, &spdy_response_header_frame_length));
xunjieli34291fe12016-03-02 13:58:38918 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:01919 EXPECT_THAT(callback_.WaitForResult(), IsOk());
xunjieli34291fe12016-03-02 13:58:38920 ASSERT_TRUE(response_.headers.get());
921 EXPECT_EQ(200, response_.headers->response_code());
922 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
923 EXPECT_FALSE(response_.response_time.is_null());
924 EXPECT_FALSE(response_.request_time.is_null());
925
926 // Send the response body.
927 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:43928 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:17929 ProcessPacket(
930 ConstructServerDataPacket(3, false, !kFin, header + kResponseBody));
Ryan Hamilton0239aac2018-05-19 00:03:13931 spdy::SpdyHeaderBlock trailers;
xunjieli34291fe12016-03-02 13:58:38932 size_t spdy_trailers_frame_length;
933 trailers["foo"] = "bar";
Ryan Hamiltona1d1f4a2019-06-26 14:43:04934 if (!quic::VersionUsesQpack(version_.transport_version)) {
935 trailers[quic::kFinalOffsetHeaderKey] =
936 base::NumberToString(strlen(kResponseBody) + header.length());
937 }
Ryan Hamilton0d65a8c2019-06-07 00:46:02938 ProcessPacket(ConstructResponseTrailersPacket(4, kFin, std::move(trailers),
939 &spdy_trailers_frame_length));
xunjieli34291fe12016-03-02 13:58:38940
941 // Make sure trailers are processed.
fdoray92e35a72016-06-10 15:54:55942 base::RunLoop().RunUntilIdle();
xunjieli34291fe12016-03-02 13:58:38943
944 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
945 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
946 callback_.callback()));
947 EXPECT_TRUE(stream_->IsResponseBodyComplete());
948
949 EXPECT_EQ(OK,
950 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
951 callback_.callback()));
952
953 EXPECT_TRUE(stream_->IsResponseBodyComplete());
954 EXPECT_TRUE(AtEof());
955
956 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
957 // headers and payload.
958 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
959 stream_->GetTotalSentBytes());
Renjief49758b2019-01-11 23:32:41960 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length +
961 strlen(kResponseBody) + header.length() +
962 +spdy_trailers_frame_length),
963 stream_->GetTotalReceivedBytes());
xunjieli5fafe142016-03-23 23:32:54964 // Check that NetLog was filled as expected.
Eric Roman79cc7552019-07-19 02:17:54965 auto entries = net_log_.GetEntries();
xunjieli5fafe142016-03-23 23:32:54966 size_t pos = ExpectLogContainsSomewhere(
967 entries, /*min_offset=*/0,
mikecirone8b85c432016-09-08 19:11:00968 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
969 NetLogEventPhase::NONE);
xunjieli5fafe142016-03-23 23:32:54970 pos = ExpectLogContainsSomewhere(
971 entries, /*min_offset=*/pos,
mikecirone8b85c432016-09-08 19:11:00972 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
973 NetLogEventPhase::NONE);
xunjieli5fafe142016-03-23 23:32:54974 ExpectLogContainsSomewhere(
975 entries, /*min_offset=*/pos,
mikecirone8b85c432016-09-08 19:11:00976 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
977 NetLogEventPhase::NONE);
xunjieli34291fe12016-03-02 13:58:38978}
979
[email protected]3e7dca62013-09-10 16:14:23980// Regression test for http://crbug.com/288128
[email protected]1e960032013-12-20 19:00:20981TEST_P(QuicHttpStreamTest, GetRequestLargeResponse) {
982 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:45983 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:02984 AddWrite(ConstructInitialSettingsPacket());
fayang3bcb8b502016-12-07 21:44:37985 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33986 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:02987 DEFAULT_PRIORITY, &spdy_request_headers_frame_length));
[email protected]3e7dca62013-09-10 16:14:23988 Initialize();
989
990 request_.method = "GET";
rchcd379012017-04-12 21:53:32991 request_.url = GURL("https://www.example.org/");
[email protected]3e7dca62013-09-10 16:14:23992
xunjieli5fafe142016-03-23 23:32:54993 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27994 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:54995 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:02996 EXPECT_EQ(OK,
997 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:23998
999 // Ack the request.
Renjie90e808e2019-01-24 07:24:041000 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]3e7dca62013-09-10 16:14:231001
robpercival214763f2016-07-01 23:27:011002 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1003 IsError(ERR_IO_PENDING));
[email protected]3e7dca62013-09-10 16:14:231004
bnc086b39e12016-06-24 13:05:261005 response_headers_[":status"] = "200 OK";
1006 response_headers_[":version"] = "HTTP/1.1";
1007 response_headers_["content-type"] = "text/plain";
1008 response_headers_["big6"] = string(1000, 'x'); // Lots of x's.
[email protected]3e7dca62013-09-10 16:14:231009
sclittlec4dc1a32015-09-24 00:15:451010 size_t spdy_response_headers_frame_length;
1011 ProcessPacket(ConstructResponseHeadersPacket(
1012 2, kFin, &spdy_response_headers_frame_length));
[email protected]3e7dca62013-09-10 16:14:231013
1014 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:011015 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]3e7dca62013-09-10 16:14:231016 ASSERT_TRUE(response_.headers.get());
1017 EXPECT_EQ(200, response_.headers->response_code());
1018 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1019
1020 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:021021 EXPECT_EQ(0,
1022 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1023 callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:231024 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1025 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101026
1027 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451028 // headers and payload.
1029 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1030 stream_->GetTotalSentBytes());
1031 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length),
1032 stream_->GetTotalReceivedBytes());
[email protected]3e7dca62013-09-10 16:14:231033}
1034
rchf9f103cbc2014-08-30 05:28:041035// Regression test for http://crbug.com/409101
1036TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendRequest) {
1037 SetRequest("GET", "/", DEFAULT_PRIORITY);
1038 Initialize();
1039
1040 request_.method = "GET";
rchcd379012017-04-12 21:53:321041 request_.url = GURL("https://www.example.org/");
rchf9f103cbc2014-08-30 05:28:041042
xunjieli5fafe142016-03-23 23:32:541043 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271044 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541045 net_log_.bound(), callback_.callback()));
rchf9f103cbc2014-08-30 05:28:041046
jri78ec06a2016-03-31 18:19:401047 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521048 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rchf9f103cbc2014-08-30 05:28:041049
1050 EXPECT_EQ(ERR_CONNECTION_CLOSED,
rjshaded5ced072015-12-18 19:26:021051 stream_->SendRequest(headers_, &response_, callback_.callback()));
sclittle1edeeb22015-09-02 20:46:101052
1053 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1054 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rchf9f103cbc2014-08-30 05:28:041055}
1056
rch03b7a202016-02-05 00:54:201057// Regression test for http://crbug.com/584441
1058TEST_P(QuicHttpStreamTest, GetSSLInfoAfterSessionClosed) {
1059 SetRequest("GET", "/", DEFAULT_PRIORITY);
1060 Initialize();
1061
1062 request_.method = "GET";
rchcd379012017-04-12 21:53:321063 request_.url = GURL("https://www.example.org/");
rch03b7a202016-02-05 00:54:201064
xunjieli5fafe142016-03-23 23:32:541065 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271066 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541067 net_log_.bound(), callback_.callback()));
rch03b7a202016-02-05 00:54:201068
1069 SSLInfo ssl_info;
rch11565e02016-02-09 20:13:471070 EXPECT_FALSE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:201071 stream_->GetSSLInfo(&ssl_info);
rch11565e02016-02-09 20:13:471072 EXPECT_TRUE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:201073
jri78ec06a2016-03-31 18:19:401074 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521075 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rch03b7a202016-02-05 00:54:201076
rch11565e02016-02-09 20:13:471077 SSLInfo ssl_info2;
1078 stream_->GetSSLInfo(&ssl_info2);
1079 EXPECT_TRUE(ssl_info2.is_valid());
rch03b7a202016-02-05 00:54:201080}
1081
rchcd379012017-04-12 21:53:321082TEST_P(QuicHttpStreamTest, GetAlternativeService) {
1083 SetRequest("GET", "/", DEFAULT_PRIORITY);
1084 Initialize();
1085
1086 request_.method = "GET";
1087 request_.url = GURL("https://www.example.org/");
1088
1089 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271090 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
rchcd379012017-04-12 21:53:321091 net_log_.bound(), callback_.callback()));
1092
1093 AlternativeService alternative_service;
1094 EXPECT_TRUE(stream_->GetAlternativeService(&alternative_service));
1095 EXPECT_EQ(AlternativeService(kProtoQUIC, "www.example.org", 443),
1096 alternative_service);
1097
1098 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521099 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rchcd379012017-04-12 21:53:321100
1101 AlternativeService alternative_service2;
1102 EXPECT_TRUE(stream_->GetAlternativeService(&alternative_service2));
1103 EXPECT_EQ(AlternativeService(kProtoQUIC, "www.example.org", 443),
1104 alternative_service2);
1105}
1106
zhongyica364fbb2015-12-12 03:39:121107TEST_P(QuicHttpStreamTest, LogGranularQuicConnectionError) {
1108 SetRequest("GET", "/", DEFAULT_PRIORITY);
1109 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:021110 AddWrite(ConstructInitialSettingsPacket());
fayang3bcb8b502016-12-07 21:44:371111 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:331112 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:021113 DEFAULT_PRIORITY, &spdy_request_headers_frame_length));
fayang3bcb8b502016-12-07 21:44:371114 AddWrite(ConstructAckAndRstStreamPacket(3));
zhongyica364fbb2015-12-12 03:39:121115 Initialize();
1116
1117 request_.method = "GET";
rchcd379012017-04-12 21:53:321118 request_.url = GURL("https://www.example.org/");
zhongyica364fbb2015-12-12 03:39:121119
xunjieli5fafe142016-03-23 23:32:541120 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271121 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541122 net_log_.bound(), callback_.callback()));
zhongyica364fbb2015-12-12 03:39:121123 EXPECT_EQ(OK,
1124 stream_->SendRequest(headers_, &response_, callback_.callback()));
1125
1126 // Ack the request.
Renjie90e808e2019-01-24 07:24:041127 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011128 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1129 IsError(ERR_IO_PENDING));
zhongyica364fbb2015-12-12 03:39:121130
Ryan Hamilton8d9ee76e2018-05-29 23:52:521131 quic::QuicConnectionCloseFrame frame;
Zhongyi Shica576df2019-04-12 17:43:401132 frame.quic_error_code = quic::QUIC_PEER_GOING_AWAY;
rch1c5b74a2016-06-23 22:10:551133 session_->connection()->OnConnectionCloseFrame(frame);
zhongyica364fbb2015-12-12 03:39:121134
1135 NetErrorDetails details;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521136 EXPECT_EQ(quic::QUIC_NO_ERROR, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121137 stream_->PopulateNetErrorDetails(&details);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521138 EXPECT_EQ(quic::QUIC_PEER_GOING_AWAY, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121139}
1140
Ryan Hamiltone316e482017-08-17 02:48:531141TEST_P(QuicHttpStreamTest, LogGranularQuicErrorIfHandshakeNotConfirmed) {
Ryan Hamiltona1d1f4a2019-06-26 14:43:041142 // TODO(nharper): Figure out why this test does not send packets
1143 // when TLS is used.
1144 if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
1145 Initialize();
1146
1147 return;
1148 }
1149
rch617e0652017-04-26 17:57:511150 // By default the test setup defaults handshake to be confirmed. Manually set
1151 // it to be not confirmed.
rch617e0652017-04-26 17:57:511152 crypto_client_stream_factory_.set_handshake_mode(
Ryan Hamilton9835e662018-08-02 05:36:271153 MockCryptoClientStream::ZERO_RTT);
rch617e0652017-04-26 17:57:511154
zhongyica364fbb2015-12-12 03:39:121155 SetRequest("GET", "/", DEFAULT_PRIORITY);
1156 size_t spdy_request_headers_frame_length;
Michael Warres167db3e2019-03-01 21:38:031157 client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
fayang3bcb8b502016-12-07 21:44:371158 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:331159 1, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:021160 DEFAULT_PRIORITY, &spdy_request_headers_frame_length));
zhongyica364fbb2015-12-12 03:39:121161 Initialize();
1162
1163 request_.method = "GET";
rchcd379012017-04-12 21:53:321164 request_.url = GURL("https://www.example.org/");
zhongyica364fbb2015-12-12 03:39:121165
xunjieli5fafe142016-03-23 23:32:541166 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271167 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541168 net_log_.bound(), callback_.callback()));
zhongyica364fbb2015-12-12 03:39:121169 EXPECT_EQ(OK,
1170 stream_->SendRequest(headers_, &response_, callback_.callback()));
1171
1172 // Ack the request.
Renjie90e808e2019-01-24 07:24:041173 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011174 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1175 IsError(ERR_IO_PENDING));
zhongyica364fbb2015-12-12 03:39:121176
Ryan Hamilton8d9ee76e2018-05-29 23:52:521177 quic::QuicConnectionCloseFrame frame;
Zhongyi Shica576df2019-04-12 17:43:401178 frame.quic_error_code = quic::QUIC_PEER_GOING_AWAY;
rch1c5b74a2016-06-23 22:10:551179 session_->connection()->OnConnectionCloseFrame(frame);
zhongyica364fbb2015-12-12 03:39:121180
1181 NetErrorDetails details;
zhongyica364fbb2015-12-12 03:39:121182 stream_->PopulateNetErrorDetails(&details);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521183 EXPECT_EQ(quic::QUIC_PEER_GOING_AWAY, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121184}
1185
rch11a114a2014-09-04 23:41:591186// Regression test for http://crbug.com/409871
1187TEST_P(QuicHttpStreamTest, SessionClosedBeforeReadResponseHeaders) {
1188 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451189 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:021190 AddWrite(ConstructInitialSettingsPacket());
fayang3bcb8b502016-12-07 21:44:371191 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:331192 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:021193 DEFAULT_PRIORITY, &spdy_request_headers_frame_length));
rch11a114a2014-09-04 23:41:591194 Initialize();
1195
1196 request_.method = "GET";
rchcd379012017-04-12 21:53:321197 request_.url = GURL("https://www.example.org/");
rch11a114a2014-09-04 23:41:591198
xunjieli5fafe142016-03-23 23:32:541199 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271200 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541201 net_log_.bound(), callback_.callback()));
rch11a114a2014-09-04 23:41:591202
rjshaded5ced072015-12-18 19:26:021203 EXPECT_EQ(OK,
1204 stream_->SendRequest(headers_, &response_, callback_.callback()));
rch11a114a2014-09-04 23:41:591205
jri78ec06a2016-03-31 18:19:401206 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521207 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rch11a114a2014-09-04 23:41:591208
1209 EXPECT_NE(OK, stream_->ReadResponseHeaders(callback_.callback()));
sclittle1edeeb22015-09-02 20:46:101210
1211 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451212 // headers and payload.
1213 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1214 stream_->GetTotalSentBytes());
sclittle1edeeb22015-09-02 20:46:101215 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rch11a114a2014-09-04 23:41:591216}
1217
[email protected]1e960032013-12-20 19:00:201218TEST_P(QuicHttpStreamTest, SendPostRequest) {
1219 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451220 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:021221 AddWrite(ConstructInitialSettingsPacket());
Yixin Wange7ecc472018-03-06 19:00:251222
Victor Vasiliev076657c2019-03-12 02:46:431223 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harper23290b82019-05-02 00:02:561224 if (version_.transport_version != quic::QUIC_VERSION_99) {
Renjief49758b2019-01-11 23:32:411225 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1226 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:021227 DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
1228 {kUploadData}));
Renjief49758b2019-01-11 23:32:411229 } else {
1230 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1231 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:021232 DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
1233 {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411234 }
Yixin Wange7ecc472018-03-06 19:00:251235
Renjie90e808e2019-01-24 07:24:041236 AddWrite(ConstructClientAckPacket(3, 3, 1, 2));
[email protected]f702d572012-12-04 15:56:201237
1238 Initialize();
1239
danakjad1777e2016-04-16 00:56:421240 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:191241 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
ricea2deef682016-09-09 08:04:071242 kUploadData, strlen(kUploadData)));
rch97827ee2017-05-24 23:49:121243 upload_data_stream_ =
Jeremy Roman0579ed62017-08-29 15:56:191244 std::make_unique<ElementsUploadDataStream>(std::move(element_readers), 0);
[email protected]f702d572012-12-04 15:56:201245 request_.method = "POST";
rchcd379012017-04-12 21:53:321246 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121247 request_.upload_data_stream = upload_data_stream_.get();
Bence Békyd8a21fc32018-06-27 18:29:581248 ASSERT_THAT(request_.upload_data_stream->Init(CompletionOnceCallback(),
tfarina42834112016-09-22 13:38:201249 NetLogWithSource()),
1250 IsOk());
[email protected]f702d572012-12-04 15:56:201251
xunjieli5fafe142016-03-23 23:32:541252 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271253 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541254 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021255 EXPECT_EQ(OK,
1256 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:201257
1258 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041259 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]f702d572012-12-04 15:56:201260
1261 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071262 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451263 size_t spdy_response_headers_frame_length;
1264 ProcessPacket(ConstructResponseHeadersPacket(
1265 2, !kFin, &spdy_response_headers_frame_length));
[email protected]f702d572012-12-04 15:56:201266
rchfb47f712017-05-21 03:24:001267 // The headers have already arrived.
1268 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]cadac622013-06-11 16:46:361269 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:201270 EXPECT_EQ(200, response_.headers->response_code());
1271 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1272
1273 // Send the response body.
1274 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431275 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:411276 ProcessPacket(
Ryan Hamilton7505eb92019-06-08 00:22:171277 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
[email protected]f702d572012-12-04 15:56:201278 // Since the body has already arrived, this should return immediately.
1279 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
1280 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1281 callback_.callback()));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291282 EXPECT_EQ(0,
1283 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1284 callback_.callback()));
1285
1286 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1287 EXPECT_TRUE(AtEof());
1288
1289 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
1290 // headers and payload.
1291 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411292 strlen(kUploadData) + header.length()),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291293 stream_->GetTotalSentBytes());
1294 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411295 strlen(kResponseBody) + header2.length()),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291296 stream_->GetTotalReceivedBytes());
1297}
1298
1299TEST_P(QuicHttpStreamTest, SendPostRequestAndReceiveSoloFin) {
1300 SetRequest("POST", "/", DEFAULT_PRIORITY);
1301 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:021302 AddWrite(ConstructInitialSettingsPacket());
Victor Vasiliev076657c2019-03-12 02:46:431303 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harper23290b82019-05-02 00:02:561304 if (version_.transport_version != quic::QUIC_VERSION_99) {
Renjief49758b2019-01-11 23:32:411305 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1306 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:021307 DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
1308 {kUploadData}));
Renjief49758b2019-01-11 23:32:411309 } else {
1310 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1311 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:021312 DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
1313 {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411314 }
1315
Renjie90e808e2019-01-24 07:24:041316 AddWrite(ConstructClientAckPacket(3, 3, 1, 2));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291317
1318 Initialize();
1319
1320 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:191321 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
Ryan Hamilton2ef0a9c2017-07-25 03:18:291322 kUploadData, strlen(kUploadData)));
1323 upload_data_stream_ =
Jeremy Roman0579ed62017-08-29 15:56:191324 std::make_unique<ElementsUploadDataStream>(std::move(element_readers), 0);
Ryan Hamilton2ef0a9c2017-07-25 03:18:291325 request_.method = "POST";
1326 request_.url = GURL("https://www.example.org/");
1327 request_.upload_data_stream = upload_data_stream_.get();
Bence Békyd8a21fc32018-06-27 18:29:581328 ASSERT_THAT(request_.upload_data_stream->Init(CompletionOnceCallback(),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291329 NetLogWithSource()),
1330 IsOk());
1331
1332 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271333 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
Ryan Hamilton2ef0a9c2017-07-25 03:18:291334 net_log_.bound(), callback_.callback()));
1335 EXPECT_EQ(OK,
1336 stream_->SendRequest(headers_, &response_, callback_.callback()));
1337
1338 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041339 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291340
1341 // Send the response headers (but not the body).
1342 SetResponse("200 OK", string());
1343 size_t spdy_response_headers_frame_length;
1344 ProcessPacket(ConstructResponseHeadersPacket(
1345 2, !kFin, &spdy_response_headers_frame_length));
1346
1347 // The headers have already arrived.
1348 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
1349 ASSERT_TRUE(response_.headers.get());
1350 EXPECT_EQ(200, response_.headers->response_code());
1351 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1352
1353 // Send the response body.
1354 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431355 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:411356 ProcessPacket(
Ryan Hamilton7505eb92019-06-08 00:22:171357 ConstructServerDataPacket(3, false, !kFin, header2 + kResponseBody));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291358 // Since the body has already arrived, this should return immediately.
1359 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
1360 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1361 callback_.callback()));
Ryan Hamilton7505eb92019-06-08 00:22:171362 ProcessPacket(ConstructServerDataPacket(4, false, kFin, ""));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291363 EXPECT_EQ(0,
1364 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1365 callback_.callback()));
[email protected]f702d572012-12-04 15:56:201366
1367 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1368 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101369
1370 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451371 // headers and payload.
1372 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411373 strlen(kUploadData) + header.length()),
sclittle1edeeb22015-09-02 20:46:101374 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451375 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411376 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101377 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:201378}
1379
[email protected]1e960032013-12-20 19:00:201380TEST_P(QuicHttpStreamTest, SendChunkedPostRequest) {
1381 SetRequest("POST", "/", DEFAULT_PRIORITY);
[email protected]c9e49a02013-02-26 05:56:471382 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:451383 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:021384 AddWrite(ConstructInitialSettingsPacket());
Victor Vasiliev076657c2019-03-12 02:46:431385 std::string header = ConstructDataHeader(chunk_size);
Nick Harper23290b82019-05-02 00:02:561386 if (version_.transport_version == quic::QUIC_VERSION_99) {
Renjief49758b2019-01-11 23:32:411387 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1388 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
Ryan Hamilton0d65a8c2019-06-07 00:46:021389 !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
1390 {header, kUploadData}));
Ryan Hamilton7505eb92019-06-08 00:22:171391 AddWrite(ConstructClientMultipleDataFramesPacket(3, kIncludeVersion, kFin,
1392 {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411393 } else {
1394 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1395 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
Ryan Hamilton0d65a8c2019-06-07 00:46:021396 !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
1397 {kUploadData}));
Ryan Hamilton7505eb92019-06-08 00:22:171398 AddWrite(ConstructClientDataPacket(3, kIncludeVersion, kFin, kUploadData));
Renjief49758b2019-01-11 23:32:411399 }
1400
Renjie90e808e2019-01-24 07:24:041401 AddWrite(ConstructClientAckPacket(4, 3, 1, 2));
[email protected]c9e49a02013-02-26 05:56:471402 Initialize();
1403
Jeremy Roman0579ed62017-08-29 15:56:191404 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121405 auto* chunked_upload_stream =
1406 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1407 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
[email protected]c9e49a02013-02-26 05:56:471408
1409 request_.method = "POST";
rchcd379012017-04-12 21:53:321410 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121411 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071412 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201413 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]c9e49a02013-02-26 05:56:471414
xunjieli5fafe142016-03-23 23:32:541415 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271416 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541417 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021418 ASSERT_EQ(ERR_IO_PENDING,
1419 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]c9e49a02013-02-26 05:56:471420
rch97827ee2017-05-24 23:49:121421 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
robpercival214763f2016-07-01 23:27:011422 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]c9e49a02013-02-26 05:56:471423
1424 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041425 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]c9e49a02013-02-26 05:56:471426
1427 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071428 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451429 size_t spdy_response_headers_frame_length;
1430 ProcessPacket(ConstructResponseHeadersPacket(
1431 2, !kFin, &spdy_response_headers_frame_length));
[email protected]c9e49a02013-02-26 05:56:471432
rchfb47f712017-05-21 03:24:001433 // The headers have already arrived.
1434 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]cadac622013-06-11 16:46:361435 ASSERT_TRUE(response_.headers.get());
[email protected]c9e49a02013-02-26 05:56:471436 EXPECT_EQ(200, response_.headers->response_code());
1437 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1438
1439 // Send the response body.
1440 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431441 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171442 ProcessPacket(
1443 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
[email protected]c9e49a02013-02-26 05:56:471444
1445 // Since the body has already arrived, this should return immediately.
1446 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1447 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1448 callback_.callback()));
1449
1450 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1451 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101452
1453 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451454 // headers and payload.
1455 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411456 strlen(kUploadData) * 2 + header.length() * 2),
sclittle1edeeb22015-09-02 20:46:101457 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451458 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411459 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101460 stream_->GetTotalReceivedBytes());
[email protected]c9e49a02013-02-26 05:56:471461}
1462
[email protected]16ba7742014-08-22 00:57:251463TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithFinalEmptyDataPacket) {
1464 SetRequest("POST", "/", DEFAULT_PRIORITY);
1465 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:451466 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:021467 AddWrite(ConstructInitialSettingsPacket());
Victor Vasiliev076657c2019-03-12 02:46:431468 std::string header = ConstructDataHeader(chunk_size);
Renjief49758b2019-01-11 23:32:411469
Nick Harper23290b82019-05-02 00:02:561470 if (version_.transport_version != quic::QUIC_VERSION_99) {
Renjief49758b2019-01-11 23:32:411471 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1472 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
Ryan Hamilton0d65a8c2019-06-07 00:46:021473 !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
1474 {kUploadData}));
Renjief49758b2019-01-11 23:32:411475 } else {
1476 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1477 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
Ryan Hamilton0d65a8c2019-06-07 00:46:021478 !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
1479 {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411480 }
Ryan Hamilton7505eb92019-06-08 00:22:171481 AddWrite(ConstructClientDataPacket(3, kIncludeVersion, kFin, ""));
Renjie90e808e2019-01-24 07:24:041482 AddWrite(ConstructClientAckPacket(4, 3, 1, 2));
[email protected]16ba7742014-08-22 00:57:251483 Initialize();
1484
Jeremy Roman0579ed62017-08-29 15:56:191485 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121486 auto* chunked_upload_stream =
1487 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1488 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
[email protected]16ba7742014-08-22 00:57:251489
1490 request_.method = "POST";
rchcd379012017-04-12 21:53:321491 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121492 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071493 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201494 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]16ba7742014-08-22 00:57:251495
xunjieli5fafe142016-03-23 23:32:541496 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271497 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541498 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021499 ASSERT_EQ(ERR_IO_PENDING,
1500 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251501
rch97827ee2017-05-24 23:49:121502 chunked_upload_stream->AppendData(nullptr, 0, true);
robpercival214763f2016-07-01 23:27:011503 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]16ba7742014-08-22 00:57:251504
Renjie90e808e2019-01-24 07:24:041505 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]16ba7742014-08-22 00:57:251506
1507 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071508 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451509 size_t spdy_response_headers_frame_length;
1510 ProcessPacket(ConstructResponseHeadersPacket(
1511 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251512
rchfb47f712017-05-21 03:24:001513 // The headers have already arrived.
1514 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]16ba7742014-08-22 00:57:251515 ASSERT_TRUE(response_.headers.get());
1516 EXPECT_EQ(200, response_.headers->response_code());
1517 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1518
1519 // Send the response body.
1520 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431521 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171522 ProcessPacket(
1523 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
[email protected]16ba7742014-08-22 00:57:251524
rchb27683c2015-07-29 23:53:501525 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251526 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1527 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1528 callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251529 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1530 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101531
1532 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451533 // headers and payload.
1534 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411535 strlen(kUploadData) + header.length()),
sclittle1edeeb22015-09-02 20:46:101536 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451537 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411538 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101539 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251540}
1541
1542TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithOneEmptyDataPacket) {
1543 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451544 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:021545 AddWrite(ConstructInitialSettingsPacket());
fayang3bcb8b502016-12-07 21:44:371546 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:331547 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, !kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:021548 DEFAULT_PRIORITY, &spdy_request_headers_frame_length));
Ryan Hamilton7505eb92019-06-08 00:22:171549 AddWrite(ConstructClientDataPacket(3, kIncludeVersion, kFin, ""));
Renjie90e808e2019-01-24 07:24:041550 AddWrite(ConstructClientAckPacket(4, 3, 1, 2));
[email protected]16ba7742014-08-22 00:57:251551 Initialize();
1552
Jeremy Roman0579ed62017-08-29 15:56:191553 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121554 auto* chunked_upload_stream =
1555 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
[email protected]16ba7742014-08-22 00:57:251556
1557 request_.method = "POST";
rchcd379012017-04-12 21:53:321558 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121559 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071560 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201561 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]16ba7742014-08-22 00:57:251562
xunjieli5fafe142016-03-23 23:32:541563 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271564 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541565 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021566 ASSERT_EQ(ERR_IO_PENDING,
1567 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251568
rch97827ee2017-05-24 23:49:121569 chunked_upload_stream->AppendData(nullptr, 0, true);
robpercival214763f2016-07-01 23:27:011570 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]16ba7742014-08-22 00:57:251571
Renjie90e808e2019-01-24 07:24:041572 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]16ba7742014-08-22 00:57:251573
1574 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071575 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451576 size_t spdy_response_headers_frame_length;
1577 ProcessPacket(ConstructResponseHeadersPacket(
1578 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251579
rchfb47f712017-05-21 03:24:001580 // The headers have already arrived.
1581 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]16ba7742014-08-22 00:57:251582 ASSERT_TRUE(response_.headers.get());
1583 EXPECT_EQ(200, response_.headers->response_code());
1584 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1585
1586 // Send the response body.
1587 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431588 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171589 ProcessPacket(
1590 ConstructServerDataPacket(3, false, kFin, header + kResponseBody));
[email protected]16ba7742014-08-22 00:57:251591
rchb27683c2015-07-29 23:53:501592 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251593 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1594 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1595 callback_.callback()));
1596
1597 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1598 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101599
1600 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451601 // headers and payload.
1602 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1603 stream_->GetTotalSentBytes());
1604 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411605 strlen(kResponseBody) + header.length()),
sclittle1edeeb22015-09-02 20:46:101606 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251607}
1608
[email protected]1e960032013-12-20 19:00:201609TEST_P(QuicHttpStreamTest, DestroyedEarly) {
1610 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451611 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:021612 AddWrite(ConstructInitialSettingsPacket());
fayang3bcb8b502016-12-07 21:44:371613 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:331614 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:021615 DEFAULT_PRIORITY, &spdy_request_headers_frame_length));
fayang3bcb8b502016-12-07 21:44:371616 AddWrite(ConstructAckAndRstStreamPacket(3));
[email protected]63534512012-12-23 18:49:001617 Initialize();
1618
1619 request_.method = "GET";
rchcd379012017-04-12 21:53:321620 request_.url = GURL("https://www.example.org/");
[email protected]63534512012-12-23 18:49:001621
xunjieli5fafe142016-03-23 23:32:541622 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271623 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541624 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021625 EXPECT_EQ(OK,
1626 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]63534512012-12-23 18:49:001627
1628 // Ack the request.
Renjie90e808e2019-01-24 07:24:041629 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
rchfb47f712017-05-21 03:24:001630 EXPECT_THAT(stream_->ReadResponseHeaders(
1631 base::Bind(&QuicHttpStreamTest::CloseStream,
1632 base::Unretained(this), stream_.get())),
robpercival214763f2016-07-01 23:27:011633 IsError(ERR_IO_PENDING));
[email protected]63534512012-12-23 18:49:001634
1635 // Send the response with a body.
[email protected]1e960032013-12-20 19:00:201636 SetResponse("404 OK", "hello world!");
[email protected]63534512012-12-23 18:49:001637 // In the course of processing this packet, the QuicHttpStream close itself.
rchfb47f712017-05-21 03:24:001638 size_t response_size = 0;
rch1bcfddf22017-06-03 00:26:291639 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin, &response_size));
[email protected]63534512012-12-23 18:49:001640
fdoray92e35a72016-06-10 15:54:551641 base::RunLoop().RunUntilIdle();
rchb27683c2015-07-29 23:53:501642
[email protected]63534512012-12-23 18:49:001643 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101644
1645 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451646 // headers and payload.
1647 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1648 stream_->GetTotalSentBytes());
rchfb47f712017-05-21 03:24:001649 // The stream was closed after receiving the headers.
1650 EXPECT_EQ(static_cast<int64_t>(response_size),
1651 stream_->GetTotalReceivedBytes());
[email protected]63534512012-12-23 18:49:001652}
1653
[email protected]1e960032013-12-20 19:00:201654TEST_P(QuicHttpStreamTest, Priority) {
1655 SetRequest("GET", "/", MEDIUM);
sclittlec4dc1a32015-09-24 00:15:451656 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:021657 AddWrite(ConstructInitialSettingsPacket());
fayang3bcb8b502016-12-07 21:44:371658 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:331659 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:021660 MEDIUM, &spdy_request_headers_frame_length));
[email protected]24e5bc52013-09-18 15:36:581661 Initialize();
1662
1663 request_.method = "GET";
rchcd379012017-04-12 21:53:321664 request_.url = GURL("https://www.example.org/");
[email protected]24e5bc52013-09-18 15:36:581665
Steven Valdezb4ff0412018-01-18 22:39:271666 EXPECT_EQ(OK,
1667 stream_->InitializeStream(&request_, true, MEDIUM, net_log_.bound(),
1668 callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581669
rjshaded5ced072015-12-18 19:26:021670 EXPECT_EQ(OK,
1671 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581672
[email protected]24e5bc52013-09-18 15:36:581673 // Ack the request.
Renjie90e808e2019-01-24 07:24:041674 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011675 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1676 IsError(ERR_IO_PENDING));
[email protected]24e5bc52013-09-18 15:36:581677
1678 // Send the response with a body.
[email protected]1e960032013-12-20 19:00:201679 SetResponse("404 OK", "hello world!");
rchfb47f712017-05-21 03:24:001680 size_t response_size = 0;
1681 ProcessPacket(ConstructResponseHeadersPacket(2, kFin, &response_size));
[email protected]24e5bc52013-09-18 15:36:581682
rchfb47f712017-05-21 03:24:001683 EXPECT_EQ(OK, callback_.WaitForResult());
rchb27683c2015-07-29 23:53:501684
[email protected]24e5bc52013-09-18 15:36:581685 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101686
1687 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451688 // headers and payload.
1689 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1690 stream_->GetTotalSentBytes());
rchfb47f712017-05-21 03:24:001691 EXPECT_EQ(static_cast<int64_t>(response_size),
1692 stream_->GetTotalReceivedBytes());
[email protected]24e5bc52013-09-18 15:36:581693}
1694
xunjieli8dff50b2016-07-22 14:19:061695TEST_P(QuicHttpStreamTest, SessionClosedDuringDoLoop) {
1696 SetRequest("POST", "/", DEFAULT_PRIORITY);
1697 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:021698 AddWrite(ConstructInitialSettingsPacket());
Victor Vasiliev076657c2019-03-12 02:46:431699 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harper23290b82019-05-02 00:02:561700 if (version_.transport_version != quic::QUIC_VERSION_99) {
Renjief49758b2019-01-11 23:32:411701 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1702 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
Ryan Hamilton0d65a8c2019-06-07 00:46:021703 !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
1704 {kUploadData}));
Renjief49758b2019-01-11 23:32:411705 } else {
1706 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1707 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
Ryan Hamilton0d65a8c2019-06-07 00:46:021708 !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
1709 {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411710 }
1711
xunjieli8dff50b2016-07-22 14:19:061712 // Second data write will result in a synchronous failure which will close
1713 // the session.
1714 AddWrite(SYNCHRONOUS, ERR_FAILED);
1715 Initialize();
1716
Jeremy Roman0579ed62017-08-29 15:56:191717 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121718 auto* chunked_upload_stream =
1719 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
xunjieli8dff50b2016-07-22 14:19:061720
1721 request_.method = "POST";
rchcd379012017-04-12 21:53:321722 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121723 request_.upload_data_stream = upload_data_stream_.get();
xunjieli8dff50b2016-07-22 14:19:061724 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201725 TestCompletionCallback().callback(), NetLogWithSource()));
xunjieli8dff50b2016-07-22 14:19:061726
1727 size_t chunk_size = strlen(kUploadData);
rch97827ee2017-05-24 23:49:121728 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
xunjieli8dff50b2016-07-22 14:19:061729 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271730 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli8dff50b2016-07-22 14:19:061731 net_log_.bound(), callback_.callback()));
1732 QuicHttpStream* stream = stream_.get();
1733 DeleteStreamCallback delete_stream_callback(std::move(stream_));
1734 // SendRequest() completes asynchronously after the final chunk is added.
Yixin Wange7ecc472018-03-06 19:00:251735 // Error does not surface yet since packet write is triggered by a packet
1736 // flusher that tries to bundle request body writes.
xunjieli8dff50b2016-07-22 14:19:061737 ASSERT_EQ(ERR_IO_PENDING,
1738 stream->SendRequest(headers_, &response_, callback_.callback()));
rch97827ee2017-05-24 23:49:121739 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
xunjieli8dff50b2016-07-22 14:19:061740 int rv = callback_.WaitForResult();
Yixin Wange7ecc472018-03-06 19:00:251741 EXPECT_EQ(OK, rv);
1742 // Error will be surfaced once an attempt to read the response occurs.
1743 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1744 stream->ReadResponseHeaders(callback_.callback()));
xunjieli8dff50b2016-07-22 14:19:061745}
1746
rtenneti15656ae2016-01-23 03:05:031747TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersComplete) {
1748 SetRequest("POST", "/", DEFAULT_PRIORITY);
Ryan Hamilton0d65a8c2019-06-07 00:46:021749 AddWrite(ConstructInitialSettingsPacket());
rtenneti15656ae2016-01-23 03:05:031750 AddWrite(SYNCHRONOUS, ERR_FAILED);
1751 Initialize();
1752
Jeremy Roman0579ed62017-08-29 15:56:191753 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
Yixin Wange7ecc472018-03-06 19:00:251754 auto* chunked_upload_stream =
1755 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
rtenneti15656ae2016-01-23 03:05:031756
1757 request_.method = "POST";
rchcd379012017-04-12 21:53:321758 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121759 request_.upload_data_stream = upload_data_stream_.get();
rtenneti15656ae2016-01-23 03:05:031760 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201761 TestCompletionCallback().callback(), NetLogWithSource()));
rtenneti15656ae2016-01-23 03:05:031762
xunjieli5fafe142016-03-23 23:32:541763 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271764 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541765 net_log_.bound(), callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:251766 ASSERT_EQ(ERR_IO_PENDING,
rtenneti15656ae2016-01-23 03:05:031767 stream_->SendRequest(headers_, &response_, callback_.callback()));
mmenkeffff3642017-06-15 17:37:241768
Yixin Wange7ecc472018-03-06 19:00:251769 // Error will be surfaced once |upload_data_stream| triggers the next write.
1770 size_t chunk_size = strlen(kUploadData);
1771 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1772 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR, callback_.WaitForResult());
1773
1774 EXPECT_LE(0, stream_->GetTotalSentBytes());
1775 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1776}
1777
1778TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersCompleteReadResponse) {
1779 SetRequest("POST", "/", DEFAULT_PRIORITY);
Ryan Hamilton0d65a8c2019-06-07 00:46:021780 AddWrite(ConstructInitialSettingsPacket());
Yixin Wange7ecc472018-03-06 19:00:251781 AddWrite(SYNCHRONOUS, ERR_FAILED);
1782 Initialize();
1783
1784 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
1785 auto* chunked_upload_stream =
1786 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1787
1788 request_.method = "POST";
1789 request_.url = GURL("https://www.example.org/");
1790 request_.upload_data_stream = upload_data_stream_.get();
1791
1792 size_t chunk_size = strlen(kUploadData);
1793 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1794
1795 ASSERT_EQ(OK, request_.upload_data_stream->Init(
1796 TestCompletionCallback().callback(), NetLogWithSource()));
1797
1798 ASSERT_EQ(OK,
1799 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1800 net_log_.bound(), callback_.callback()));
1801 ASSERT_EQ(OK,
1802 stream_->SendRequest(headers_, &response_, callback_.callback()));
1803
1804 // Error will be surfaced once an attempt to read the response occurs.
1805 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1806 stream_->ReadResponseHeaders(callback_.callback()));
1807
mmenkeffff3642017-06-15 17:37:241808 EXPECT_LE(0, stream_->GetTotalSentBytes());
1809 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rtenneti15656ae2016-01-23 03:05:031810}
1811
1812TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBodyComplete) {
1813 SetRequest("POST", "/", DEFAULT_PRIORITY);
1814 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:021815 AddWrite(ConstructInitialSettingsPacket());
fayang3bcb8b502016-12-07 21:44:371816 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:331817 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, !kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:021818 DEFAULT_PRIORITY, &spdy_request_headers_frame_length));
rtenneti15656ae2016-01-23 03:05:031819 AddWrite(SYNCHRONOUS, ERR_FAILED);
1820 Initialize();
1821
Jeremy Roman0579ed62017-08-29 15:56:191822 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121823 auto* chunked_upload_stream =
1824 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
rtenneti15656ae2016-01-23 03:05:031825
1826 request_.method = "POST";
rchcd379012017-04-12 21:53:321827 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121828 request_.upload_data_stream = upload_data_stream_.get();
rtenneti15656ae2016-01-23 03:05:031829 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201830 TestCompletionCallback().callback(), NetLogWithSource()));
rtenneti15656ae2016-01-23 03:05:031831
xunjieli5fafe142016-03-23 23:32:541832 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271833 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541834 net_log_.bound(), callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:251835 ASSERT_EQ(ERR_IO_PENDING,
rtenneti15656ae2016-01-23 03:05:031836 stream_->SendRequest(headers_, &response_, callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:251837
1838 size_t chunk_size = strlen(kUploadData);
1839 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1840 // Error does not surface yet since packet write is triggered by a packet
1841 // flusher that tries to bundle request body writes.
1842 ASSERT_EQ(OK, callback_.WaitForResult());
1843 // Error will be surfaced once an attempt to read the response occurs.
1844 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1845 stream_->ReadResponseHeaders(callback_.callback()));
1846
1847 EXPECT_LE(0, stream_->GetTotalSentBytes());
1848 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1849}
1850
1851TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBundledBodyComplete) {
1852 SetRequest("POST", "/", DEFAULT_PRIORITY);
1853 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:021854 AddWrite(ConstructInitialSettingsPacket());
Victor Vasiliev076657c2019-03-12 02:46:431855 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harper23290b82019-05-02 00:02:561856 if (version_.transport_version != quic::QUIC_VERSION_99) {
Renjief49758b2019-01-11 23:32:411857 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1858 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
Ryan Hamilton0d65a8c2019-06-07 00:46:021859 !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
1860 {kUploadData}));
Renjief49758b2019-01-11 23:32:411861 } else {
1862 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1863 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
Ryan Hamilton0d65a8c2019-06-07 00:46:021864 !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
1865 {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411866 }
1867
Yixin Wange7ecc472018-03-06 19:00:251868 AddWrite(SYNCHRONOUS, ERR_FAILED);
1869 Initialize();
1870
1871 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
1872 auto* chunked_upload_stream =
1873 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1874
1875 request_.method = "POST";
1876 request_.url = GURL("https://www.example.org/");
1877 request_.upload_data_stream = upload_data_stream_.get();
1878
1879 size_t chunk_size = strlen(kUploadData);
1880 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
1881
1882 ASSERT_EQ(OK, request_.upload_data_stream->Init(
1883 TestCompletionCallback().callback(), NetLogWithSource()));
1884
1885 ASSERT_EQ(OK,
1886 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1887 net_log_.bound(), callback_.callback()));
1888 ASSERT_EQ(ERR_IO_PENDING,
1889 stream_->SendRequest(headers_, &response_, callback_.callback()));
1890
1891 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1892
1893 // Error does not surface yet since packet write is triggered by a packet
1894 // flusher that tries to bundle request body writes.
1895 ASSERT_EQ(OK, callback_.WaitForResult());
1896 // Error will be surfaced once an attempt to read the response occurs.
1897 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1898 stream_->ReadResponseHeaders(callback_.callback()));
1899
1900 EXPECT_LE(0, stream_->GetTotalSentBytes());
1901 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rtenneti15656ae2016-01-23 03:05:031902}
1903
ckrasic3865ee0f2016-02-29 22:04:561904TEST_P(QuicHttpStreamTest, ServerPushGetRequest) {
1905 SetRequest("GET", "/", DEFAULT_PRIORITY);
1906 Initialize();
1907
1908 // Initialize the first stream, for receiving the promise on.
1909 request_.method = "GET";
rchcd379012017-04-12 21:53:321910 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:561911
xunjieli5fafe142016-03-23 23:32:541912 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271913 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541914 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561915
1916 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
1917 // packet, but does it matter?
1918 ReceivePromise(promise_id_);
1919 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
1920
1921 request_.url = GURL(promise_url_);
1922
1923 // Make the second stream that will exercise the first step of the
1924 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:271925 EXPECT_EQ(OK, promised_stream_->InitializeStream(
1926 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
1927 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561928
1929 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:251930 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:561931 size_t spdy_response_headers_frame_length;
1932 ProcessPacket(InnerConstructResponseHeadersPacket(
1933 1, promise_id_, false, &spdy_response_headers_frame_length));
1934
1935 // Receive the promised response body.
1936 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431937 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171938 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
1939 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:561940
1941 // Now sending a matching request will have successful rendezvous
1942 // with the promised stream.
Ryan Hamiltona1d1f4a2019-06-26 14:43:041943 ASSERT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
ckrasic3865ee0f2016-02-29 22:04:561944 callback_.callback()));
1945
1946 EXPECT_EQ(
1947 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
1948 ->id(),
1949 promise_id_);
1950
1951 // The headers will be immediately available.
robpercival214763f2016-07-01 23:27:011952 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
1953 IsOk());
ckrasic3865ee0f2016-02-29 22:04:561954
1955 // As will be the body.
1956 EXPECT_EQ(
1957 static_cast<int>(strlen(kResponseBody)),
1958 promised_stream_->ReadResponseBody(
1959 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
1960 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
1961 EXPECT_TRUE(AtEof());
1962
1963 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1964 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1965 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
1966 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411967 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:561968 promised_stream_->GetTotalReceivedBytes());
1969}
1970
1971TEST_P(QuicHttpStreamTest, ServerPushGetRequestSlowResponse) {
1972 SetRequest("GET", "/", DEFAULT_PRIORITY);
1973 Initialize();
1974
1975 // Initialize the first stream, for receiving the promise on.
1976 request_.method = "GET";
rchcd379012017-04-12 21:53:321977 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:561978
xunjieli5fafe142016-03-23 23:32:541979 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271980 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541981 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561982
1983 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
1984 // packet, but does it matter?
1985 ReceivePromise(promise_id_);
1986 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
1987
1988 request_.url = GURL(promise_url_);
1989
1990 // Make the second stream that will exercise the first step of the
1991 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:271992 EXPECT_EQ(OK, promised_stream_->InitializeStream(
1993 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
1994 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561995
1996 // Now sending a matching request will rendezvous with the promised
1997 // stream, but pending secondary validation.
1998 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
1999 headers_, &response_, callback_.callback()));
2000
2001 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252002 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562003 size_t spdy_response_headers_frame_length;
2004 ProcessPacket(InnerConstructResponseHeadersPacket(
2005 1, promise_id_, false, &spdy_response_headers_frame_length));
2006
2007 // Receive the promised response body.
2008 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432009 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172010 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2011 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562012
fdoray92e35a72016-06-10 15:54:552013 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562014
2015 // Rendezvous should have succeeded now, so the promised stream
2016 // should point at our push stream, and we should be able read
2017 // headers and data from it.
robpercival214763f2016-07-01 23:27:012018 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562019
2020 EXPECT_EQ(
2021 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2022 ->id(),
2023 promise_id_);
2024
robpercival214763f2016-07-01 23:27:012025 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2026 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562027
2028 EXPECT_EQ(
2029 static_cast<int>(strlen(kResponseBody)),
2030 promised_stream_->ReadResponseBody(
2031 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2032
2033 // Callback should return
2034 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2035 EXPECT_TRUE(AtEof());
2036
2037 EXPECT_EQ(0, stream_->GetTotalSentBytes());
2038 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2039 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2040 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412041 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562042 promised_stream_->GetTotalReceivedBytes());
2043}
2044
ckrasic2c63f9b2016-08-16 23:54:072045// Verify fix for crbug.com/637349
2046TEST_P(QuicHttpStreamTest, ServerPushCancelHttpStreamBeforeResponse) {
2047 SetRequest("GET", "/", DEFAULT_PRIORITY);
2048 Initialize();
2049
2050 // Initialize the first stream, for receiving the promise on.
2051 request_.method = "GET";
rchcd379012017-04-12 21:53:322052 request_.url = GURL("https://www.example.org/");
ckrasic2c63f9b2016-08-16 23:54:072053
2054 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272055 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
ckrasic2c63f9b2016-08-16 23:54:072056 net_log_.bound(), callback_.callback()));
2057
2058 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2059 // packet, but does it matter?
2060 ReceivePromise(promise_id_);
2061 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2062
2063 request_.url = GURL(promise_url_);
2064
2065 // Make the second stream that will exercise the first step of the
2066 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272067 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2068 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2069 callback_.callback()));
ckrasic2c63f9b2016-08-16 23:54:072070
2071 // Now sending a matching request will rendezvous with the promised
2072 // stream, but pending secondary validation.
2073 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2074 headers_, &response_, callback_.callback()));
2075
2076 base::RunLoop().RunUntilIdle();
2077
2078 // Cause of FinalValidation() crash as per bug.
2079 promised_stream_.reset();
2080
2081 // Receive the promised response headers.
2082 response_headers_ = promised_response_.Clone();
2083 size_t spdy_response_headers_frame_length;
2084 ProcessPacket(InnerConstructResponseHeadersPacket(
2085 1, promise_id_, false, &spdy_response_headers_frame_length));
2086}
2087
ckrasic3865ee0f2016-02-29 22:04:562088TEST_P(QuicHttpStreamTest, ServerPushCrossOriginOK) {
2089 SetRequest("GET", "/", DEFAULT_PRIORITY);
2090 Initialize();
2091
2092 // Initialize the first stream, for receiving the promise on.
2093 request_.method = "GET";
rchcd379012017-04-12 21:53:322094 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562095
xunjieli5fafe142016-03-23 23:32:542096 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272097 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542098 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562099
2100 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2101 // packet, but does it matter?
2102
2103 push_promise_[":authority"] = "mail.example.org";
David Schinazi3f7465c2019-07-12 01:57:052104 promise_url_ =
2105 quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
ckrasic3865ee0f2016-02-29 22:04:562106
2107 ReceivePromise(promise_id_);
2108 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2109
2110 request_.url = GURL(promise_url_);
2111
2112 // Make the second stream that will exercise the first step of the
2113 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272114 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2115 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2116 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562117
2118 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252119 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562120 size_t spdy_response_headers_frame_length;
2121 ProcessPacket(InnerConstructResponseHeadersPacket(
2122 1, promise_id_, false, &spdy_response_headers_frame_length));
2123
2124 // Receive the promised response body.
2125 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432126 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172127 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2128 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562129
2130 // Now sending a matching request will have successful rendezvous
2131 // with the promised stream.
2132 EXPECT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
2133 callback_.callback()));
2134
2135 EXPECT_EQ(
2136 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2137 ->id(),
2138 promise_id_);
2139
2140 // The headers will be immediately available.
robpercival214763f2016-07-01 23:27:012141 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2142 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562143
2144 // As will be the body.
2145 EXPECT_EQ(
2146 static_cast<int>(strlen(kResponseBody)),
2147 promised_stream_->ReadResponseBody(
2148 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2149 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2150 EXPECT_TRUE(AtEof());
2151
2152 EXPECT_EQ(0, stream_->GetTotalSentBytes());
2153 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2154 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2155 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412156 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562157 promised_stream_->GetTotalReceivedBytes());
2158}
2159
2160TEST_P(QuicHttpStreamTest, ServerPushCrossOriginFail) {
2161 SetRequest("GET", "/", DEFAULT_PRIORITY);
2162 Initialize();
2163
2164 // Initialize the first stream, for receiving the promise on.
2165 request_.method = "GET";
rchcd379012017-04-12 21:53:322166 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562167
xunjieli5fafe142016-03-23 23:32:542168 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272169 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542170 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562171
2172 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2173 // packet, but does it matter?
2174 push_promise_[":authority"] = "www.notexample.org";
David Schinazi3f7465c2019-07-12 01:57:052175 promise_url_ =
2176 quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
ckrasic3865ee0f2016-02-29 22:04:562177
2178 ReceivePromise(promise_id_);
2179 // The promise will have been rejected because the cert doesn't
2180 // match.
2181 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
2182}
2183
2184TEST_P(QuicHttpStreamTest, ServerPushVaryCheckOK) {
2185 SetRequest("GET", "/", DEFAULT_PRIORITY);
2186 Initialize();
2187
2188 // Initialize the first stream, for receiving the promise on.
2189 request_.method = "GET";
rchcd379012017-04-12 21:53:322190 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562191
xunjieli5fafe142016-03-23 23:32:542192 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272193 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542194 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562195
2196 push_promise_["accept-encoding"] = "gzip";
ckrasic3865ee0f2016-02-29 22:04:562197
2198 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2199 // packet, but does it matter?
2200 ReceivePromise(promise_id_);
2201 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2202
2203 request_.url = GURL(promise_url_);
2204
2205 // Make the second stream that will exercise the first step of the
2206 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272207 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2208 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2209 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562210
2211 headers_.SetHeader("accept-encoding", "gzip");
2212
2213 // Now sending a matching request will rendezvous with the promised
2214 // stream, but pending secondary validation.
2215 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2216 headers_, &response_, callback_.callback()));
2217
2218 // Receive the promised response headers.
2219 promised_response_["vary"] = "accept-encoding";
bnc94893a72016-06-30 13:45:252220 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562221 size_t spdy_response_headers_frame_length;
2222 ProcessPacket(InnerConstructResponseHeadersPacket(
2223 1, promise_id_, false, &spdy_response_headers_frame_length));
2224
2225 // Receive the promised response body.
2226 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432227 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172228 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2229 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562230
fdoray92e35a72016-06-10 15:54:552231 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562232
2233 // Rendezvous should have succeeded now, so the promised stream
2234 // should point at our push stream, and we should be able read
2235 // headers and data from it.
robpercival214763f2016-07-01 23:27:012236 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562237
2238 EXPECT_EQ(
2239 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2240 ->id(),
2241 promise_id_);
2242
robpercival214763f2016-07-01 23:27:012243 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2244 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562245
2246 EXPECT_EQ(
2247 static_cast<int>(strlen(kResponseBody)),
2248 promised_stream_->ReadResponseBody(
2249 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2250
2251 // Callback should return
2252 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2253 EXPECT_TRUE(AtEof());
2254
2255 EXPECT_EQ(0, stream_->GetTotalSentBytes());
2256 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2257 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2258 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412259 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562260 promised_stream_->GetTotalReceivedBytes());
2261}
2262
2263TEST_P(QuicHttpStreamTest, ServerPushVaryCheckFail) {
2264 SetRequest("GET", "/", DEFAULT_PRIORITY);
2265 request_headers_[":scheme"] = "https";
2266 request_headers_[":path"] = "/bar";
2267 request_headers_["accept-encoding"] = "sdch";
2268
2269 size_t spdy_request_header_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:022270 AddWrite(ConstructInitialSettingsPacket());
Yixin Wangb470bc882018-02-15 18:43:572271
Fan Yangac867502019-01-28 21:10:232272 uint64_t client_packet_number = 2;
Yixin Wangb470bc882018-02-15 18:43:572273 if (client_headers_include_h2_stream_dependency_ &&
Nick Harper23290b82019-05-02 00:02:562274 version_.transport_version >= quic::QUIC_VERSION_43) {
Ryan Hamilton0d65a8c2019-06-07 00:46:022275 AddWrite(ConstructClientPriorityPacket(client_packet_number++,
2276 kIncludeVersion, promise_id_, 0,
2277 DEFAULT_PRIORITY));
Yixin Wangb470bc882018-02-15 18:43:572278 }
Michael Warresabba8b7d2018-07-20 22:50:272279 AddWrite(ConstructClientRstStreamVaryMismatchAndRequestHeadersPacket(
Victor Vasiliev4a6798e2019-03-06 02:26:092280 client_packet_number++,
Nick Harper23290b82019-05-02 00:02:562281 stream_id_ + quic::QuicUtils::StreamIdDelta(version_.transport_version),
2282 !kIncludeVersion, kFin, DEFAULT_PRIORITY, promise_id_,
Ryan Hamilton0d65a8c2019-06-07 00:46:022283 &spdy_request_header_frame_length));
Renjie90e808e2019-01-24 07:24:042284 AddWrite(ConstructClientAckPacket(client_packet_number++, 3, 1, 2));
Yixin Wangb470bc882018-02-15 18:43:572285 AddWrite(ConstructClientRstStreamCancelledPacket(client_packet_number++));
2286
ckrasic3865ee0f2016-02-29 22:04:562287 Initialize();
2288
2289 // Initialize the first stream, for receiving the promise on.
2290 request_.method = "GET";
rchcd379012017-04-12 21:53:322291 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562292
xunjieli5fafe142016-03-23 23:32:542293 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272294 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542295 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562296
2297 push_promise_["accept-encoding"] = "gzip";
ckrasic3865ee0f2016-02-29 22:04:562298
2299 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2300 // packet, but does it matter?
2301 ReceivePromise(promise_id_);
2302 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2303
2304 request_.url = GURL(promise_url_);
2305
2306 // Make the second stream that will exercise the first step of the
2307 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272308 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2309 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2310 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562311
2312 headers_.SetHeader("accept-encoding", "sdch");
2313
2314 // Now sending a matching request will rendezvous with the promised
2315 // stream, but pending secondary validation.
2316 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2317 headers_, &response_, callback_.callback()));
2318
2319 // Receive the promised response headers.
2320 promised_response_["vary"] = "accept-encoding";
bnc94893a72016-06-30 13:45:252321 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562322 size_t spdy_response_headers_frame_length;
2323 ProcessPacket(InnerConstructResponseHeadersPacket(
2324 1, promise_id_, false, &spdy_response_headers_frame_length));
2325
fdoray92e35a72016-06-10 15:54:552326 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562327
2328 // Rendezvous should have failed due to vary mismatch, so the
2329 // promised stream should have been aborted, and instead we have a
2330 // new, regular client initiated stream.
robpercival214763f2016-07-01 23:27:012331 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562332
2333 // Not a server-initiated stream.
2334 EXPECT_NE(
2335 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2336 ->id(),
2337 promise_id_);
2338
2339 // Instead, a new client-initiated stream.
2340 EXPECT_EQ(
2341 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2342 ->id(),
Nick Harper23290b82019-05-02 00:02:562343 stream_id_ + quic::QuicUtils::StreamIdDelta(version_.transport_version));
ckrasic3865ee0f2016-02-29 22:04:562344
2345 // After rendezvous failure, the push stream has been cancelled.
2346 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
2347
2348 // The rest of the test verifies that the retried as
2349 // client-initiated version of |promised_stream_| works as intended.
2350
2351 // Ack the request.
Renjie90e808e2019-01-24 07:24:042352 ProcessPacket(ConstructServerAckPacket(2, 1, 1, 1));
ckrasic3865ee0f2016-02-29 22:04:562353
bnc614a92d32016-04-04 13:56:072354 SetResponse("404 Not Found", string());
ckrasic3865ee0f2016-02-29 22:04:562355 size_t spdy_response_header_frame_length;
2356 ProcessPacket(InnerConstructResponseHeadersPacket(
Nick Harper23290b82019-05-02 00:02:562357 3,
2358 stream_id_ + quic::QuicUtils::StreamIdDelta(version_.transport_version),
2359 kFin, &spdy_response_header_frame_length));
ckrasic3865ee0f2016-02-29 22:04:562360
fdoray92e35a72016-06-10 15:54:552361 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562362
robpercival214763f2016-07-01 23:27:012363 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2364 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562365 ASSERT_TRUE(response_.headers.get());
2366 EXPECT_EQ(404, response_.headers->response_code());
2367 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
2368 EXPECT_FALSE(response_.response_time.is_null());
2369 EXPECT_FALSE(response_.request_time.is_null());
2370
2371 // There is no body, so this should return immediately.
2372 EXPECT_EQ(
2373 0, promised_stream_->ReadResponseBody(
2374 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2375 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2376
2377 stream_->Close(true);
2378
2379 EXPECT_TRUE(AtEof());
2380
2381 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
2382 // headers and payload.
2383 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
2384 promised_stream_->GetTotalSentBytes());
2385 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length),
2386 promised_stream_->GetTotalReceivedBytes());
2387}
2388
maksim.sisov84e20c92016-06-23 08:49:342389TEST_P(QuicHttpStreamTest, DataReadErrorSynchronous) {
2390 SetRequest("POST", "/", DEFAULT_PRIORITY);
2391 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:022392 AddWrite(ConstructInitialSettingsPacket());
Yixin Wange7ecc472018-03-06 19:00:252393 AddWrite(ConstructRequestAndRstPacket(
Fan Yang32c5a112018-12-10 20:06:332394 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, !kFin,
Yixin Wange7ecc472018-03-06 19:00:252395 DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
Ryan Hamiltonb5d4c5a2019-06-21 22:08:412396 quic::QUIC_ERROR_PROCESSING_STREAM));
maksim.sisov84e20c92016-06-23 08:49:342397
2398 Initialize();
2399
Jeremy Roman0579ed62017-08-29 15:56:192400 upload_data_stream_ = std::make_unique<ReadErrorUploadDataStream>(
maksim.sisov84e20c92016-06-23 08:49:342401 ReadErrorUploadDataStream::FailureMode::SYNC);
2402 request_.method = "POST";
rchcd379012017-04-12 21:53:322403 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122404 request_.upload_data_stream = upload_data_stream_.get();
maksim.sisov84e20c92016-06-23 08:49:342405 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202406 TestCompletionCallback().callback(), NetLogWithSource()));
maksim.sisov84e20c92016-06-23 08:49:342407
2408 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272409 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
maksim.sisov84e20c92016-06-23 08:49:342410 net_log_.bound(), callback_.callback()));
2411
2412 int result = stream_->SendRequest(headers_, &response_, callback_.callback());
robpercival214763f2016-07-01 23:27:012413 EXPECT_THAT(result, IsError(ERR_FAILED));
maksim.sisov84e20c92016-06-23 08:49:342414
2415 EXPECT_TRUE(AtEof());
2416
2417 // QuicHttpStream::GetTotalSent/ReceivedBytes includes only headers.
2418 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
2419 stream_->GetTotalSentBytes());
2420 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2421}
2422
2423TEST_P(QuicHttpStreamTest, DataReadErrorAsynchronous) {
2424 SetRequest("POST", "/", DEFAULT_PRIORITY);
2425 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:022426 AddWrite(ConstructInitialSettingsPacket());
fayang3bcb8b502016-12-07 21:44:372427 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:332428 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, !kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:022429 DEFAULT_PRIORITY, &spdy_request_headers_frame_length));
fayang3bcb8b502016-12-07 21:44:372430 AddWrite(ConstructClientRstStreamErrorPacket(3, !kIncludeVersion));
maksim.sisov84e20c92016-06-23 08:49:342431
2432 Initialize();
2433
Jeremy Roman0579ed62017-08-29 15:56:192434 upload_data_stream_ = std::make_unique<ReadErrorUploadDataStream>(
maksim.sisov84e20c92016-06-23 08:49:342435 ReadErrorUploadDataStream::FailureMode::ASYNC);
2436 request_.method = "POST";
rchcd379012017-04-12 21:53:322437 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122438 request_.upload_data_stream = upload_data_stream_.get();
maksim.sisov84e20c92016-06-23 08:49:342439 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202440 TestCompletionCallback().callback(), NetLogWithSource()));
maksim.sisov84e20c92016-06-23 08:49:342441
2442 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272443 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
maksim.sisov84e20c92016-06-23 08:49:342444 net_log_.bound(), callback_.callback()));
2445
2446 int result = stream_->SendRequest(headers_, &response_, callback_.callback());
2447
Renjie90e808e2019-01-24 07:24:042448 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
maksim.sisov84e20c92016-06-23 08:49:342449 SetResponse("200 OK", string());
2450
robpercival214763f2016-07-01 23:27:012451 EXPECT_THAT(result, IsError(ERR_IO_PENDING));
2452 EXPECT_THAT(callback_.GetResult(result), IsError(ERR_FAILED));
maksim.sisov84e20c92016-06-23 08:49:342453
2454 EXPECT_TRUE(AtEof());
2455
2456 // QuicHttpStream::GetTotalSent/ReceivedBytes includes only headers.
2457 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
2458 stream_->GetTotalSentBytes());
2459 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2460}
2461
[email protected]f702d572012-12-04 15:56:202462} // namespace test
[email protected]f702d572012-12-04 15:56:202463} // namespace net