blob: 4bf09a63ac1c074e9751139025c1c1c9d451616b [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"
xunjieli84adaab2016-09-20 01:12:2822#include "net/base/load_timing_info.h"
23#include "net/base/load_timing_info_test_util.h"
[email protected]f702d572012-12-04 15:56:2024#include "net/base/net_errors.h"
25#include "net/base/test_completion_callback.h"
[email protected]b2d26cfd2012-12-11 10:36:0626#include "net/base/upload_bytes_element_reader.h"
[email protected]f702d572012-12-04 15:56:2027#include "net/http/http_response_headers.h"
[email protected]5db452202014-08-19 05:22:1528#include "net/http/transport_security_state.h"
mikecirone8b85c432016-09-08 19:11:0029#include "net/log/net_log_event_type.h"
xunjieli5fafe142016-03-23 23:32:5430#include "net/log/test_net_log.h"
31#include "net/log/test_net_log_util.h"
Victor Vasiliev4f6fb892019-05-31 16:58:3132#include "net/quic/address_utils.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0833#include "net/quic/crypto/proof_verifier_chromium.h"
34#include "net/quic/mock_crypto_client_stream_factory.h"
35#include "net/quic/quic_chromium_alarm_factory.h"
36#include "net/quic/quic_chromium_connection_helper.h"
37#include "net/quic/quic_chromium_packet_reader.h"
38#include "net/quic/quic_chromium_packet_writer.h"
39#include "net/quic/quic_http_utils.h"
40#include "net/quic/quic_server_info.h"
41#include "net/quic/quic_stream_factory.h"
42#include "net/quic/quic_test_packet_maker.h"
Ryan Hamilton0d65a8c2019-06-07 00:46:0243#include "net/quic/quic_test_packet_printer.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0844#include "net/quic/test_task_runner.h"
tbansalca83c002016-04-28 20:56:2845#include "net/socket/socket_performance_watcher.h"
[email protected]f702d572012-12-04 15:56:2046#include "net/socket/socket_test_util.h"
Bence Béky94658bf2018-05-11 19:22:5847#include "net/spdy/spdy_http_utils.h"
rch03b7a202016-02-05 00:54:2048#include "net/test/cert_test_util.h"
robpercival214763f2016-07-01 23:27:0149#include "net/test/gtest_util.h"
rsleevia69c79a2016-06-22 03:28:4350#include "net/test/test_data_directory.h"
Bence Béky98447b12018-05-08 03:14:0151#include "net/test/test_with_scoped_task_environment.h"
Victor Vasiliev6bb59d22019-03-08 21:34:5152#include "net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.h"
53#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
54#include "net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h"
55#include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
56#include "net/third_party/quiche/src/quic/core/http/spdy_utils.h"
57#include "net/third_party/quiche/src/quic/core/quic_connection.h"
58#include "net/third_party/quiche/src/quic/core/quic_utils.h"
59#include "net/third_party/quiche/src/quic/core/quic_write_blocked_list.h"
60#include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h"
61#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
62#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
63#include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
64#include "net/third_party/quiche/src/quic/test_tools/mock_random.h"
65#include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
66#include "net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h"
67#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
Victor Vasiliev27cc7712019-01-24 11:50:1468#include "net/third_party/quiche/src/spdy/core/spdy_frame_builder.h"
69#include "net/third_party/quiche/src/spdy/core/spdy_framer.h"
70#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
Ramin Halavati683bcaa92018-02-14 08:42:3971#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
[email protected]f702d572012-12-04 15:56:2072#include "testing/gmock/include/gmock/gmock.h"
73#include "testing/gtest/include/gtest/gtest.h"
74
bnc614a92d32016-04-04 13:56:0775using std::string;
[email protected]f702d572012-12-04 15:56:2076using testing::_;
[email protected]06ff5152013-08-29 01:03:0577using testing::AnyNumber;
78using testing::Return;
[email protected]f702d572012-12-04 15:56:2079
80namespace net {
[email protected]f702d572012-12-04 15:56:2081namespace test {
[email protected]f702d572012-12-04 15:56:2082namespace {
83
[email protected]16ba7742014-08-22 00:57:2584const char kUploadData[] = "Really nifty data!";
rch9ae5b3b2016-02-11 00:36:2985const char kDefaultServerHostName[] = "www.example.org";
rchcd379012017-04-12 21:53:3286const uint16_t kDefaultServerPort = 443;
[email protected]f702d572012-12-04 15:56:2087
Ryan Hamilton8d9ee76e2018-05-29 23:52:5288class TestQuicConnection : public quic::QuicConnection {
[email protected]f702d572012-12-04 15:56:2089 public:
Ryan Hamilton8d9ee76e2018-05-29 23:52:5290 TestQuicConnection(const quic::ParsedQuicVersionVector& versions,
91 quic::QuicConnectionId connection_id,
[email protected]f702d572012-12-04 15:56:2092 IPEndPoint address,
rch12fef552016-01-15 16:26:3193 QuicChromiumConnectionHelper* helper,
rch16c74d1d2016-04-22 06:14:0794 QuicChromiumAlarmFactory* alarm_factory,
Ryan Hamilton8d9ee76e2018-05-29 23:52:5295 quic::QuicPacketWriter* writer)
Victor Vasiliev4f6fb892019-05-31 16:58:3196 : quic::QuicConnection(connection_id,
97 ToQuicSocketAddress(address),
98 helper,
99 alarm_factory,
100 writer,
101 true /* owns_writer */,
102 quic::Perspective::IS_CLIENT,
103 versions) {}
[email protected]f702d572012-12-04 15:56:20104
Ryan Hamilton8d9ee76e2018-05-29 23:52:52105 void SetSendAlgorithm(quic::SendAlgorithmInterface* send_algorithm) {
106 quic::test::QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
[email protected]f702d572012-12-04 15:56:20107 }
108};
109
maksim.sisov84e20c92016-06-23 08:49:34110// UploadDataStream that always returns errors on data read.
111class ReadErrorUploadDataStream : public UploadDataStream {
112 public:
113 enum class FailureMode { SYNC, ASYNC };
114
115 explicit ReadErrorUploadDataStream(FailureMode mode)
116 : UploadDataStream(true, 0), async_(mode), weak_factory_(this) {}
117 ~ReadErrorUploadDataStream() override {}
118
119 private:
120 void CompleteRead() { UploadDataStream::OnReadCompleted(ERR_FAILED); }
121
122 // UploadDataStream implementation:
tfarina42834112016-09-22 13:38:20123 int InitInternal(const NetLogWithSource& net_log) override { return OK; }
maksim.sisov84e20c92016-06-23 08:49:34124
125 int ReadInternal(IOBuffer* buf, int buf_len) override {
126 if (async_ == FailureMode::ASYNC) {
127 base::ThreadTaskRunnerHandle::Get()->PostTask(
kylecharf4fe5172019-02-15 18:53:49128 FROM_HERE, base::BindOnce(&ReadErrorUploadDataStream::CompleteRead,
129 weak_factory_.GetWeakPtr()));
maksim.sisov84e20c92016-06-23 08:49:34130 return ERR_IO_PENDING;
131 }
132 return ERR_FAILED;
133 }
134
135 void ResetInternal() override {}
136
137 const FailureMode async_;
138
139 base::WeakPtrFactory<ReadErrorUploadDataStream> weak_factory_;
140
141 DISALLOW_COPY_AND_ASSIGN(ReadErrorUploadDataStream);
142};
143
Bence Béky8ddc2492018-06-13 01:02:04144// A helper class that will delete |stream| when the callback is invoked.
xunjieli8dff50b2016-07-22 14:19:06145class DeleteStreamCallback : public TestCompletionCallbackBase {
146 public:
Bence Béky8ddc2492018-06-13 01:02:04147 explicit DeleteStreamCallback(std::unique_ptr<QuicHttpStream> stream)
148 : stream_(std::move(stream)) {}
xunjieli8dff50b2016-07-22 14:19:06149
Bence Béky8ddc2492018-06-13 01:02:04150 CompletionOnceCallback callback() {
151 return base::BindOnce(&DeleteStreamCallback::DeleteStream,
152 base::Unretained(this));
153 }
xunjieli8dff50b2016-07-22 14:19:06154
155 private:
156 void DeleteStream(int result) {
157 stream_.reset();
158 SetResult(result);
159 }
160
161 std::unique_ptr<QuicHttpStream> stream_;
xunjieli8dff50b2016-07-22 14:19:06162};
163
[email protected]f702d572012-12-04 15:56:20164} // namespace
165
[email protected]24e5bc52013-09-18 15:36:58166class QuicHttpStreamPeer {
167 public:
rch08e198572017-05-09 16:56:55168 static QuicChromiumClientStream::Handle* GetQuicChromiumClientStream(
[email protected]24e5bc52013-09-18 15:36:58169 QuicHttpStream* stream) {
rch08e198572017-05-09 16:56:55170 return stream->stream_.get();
[email protected]24e5bc52013-09-18 15:36:58171 }
172};
173
Ryan Hamilton8d9ee76e2018-05-29 23:52:52174class QuicHttpStreamTest : public ::testing::TestWithParam<
Nick Harper23290b82019-05-02 00:02:56175 std::tuple<quic::ParsedQuicVersion, bool>>,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52176 public WithScopedTaskEnvironment {
rchfb47f712017-05-21 03:24:00177 public:
178 void CloseStream(QuicHttpStream* stream, int /*rv*/) { stream->Close(false); }
179
[email protected]f702d572012-12-04 15:56:20180 protected:
[email protected]1e960032013-12-20 19:00:20181 static const bool kFin = true;
182 static const bool kIncludeVersion = true;
183 static const bool kIncludeCongestionFeedback = true;
184
[email protected]f702d572012-12-04 15:56:20185 // Holds a packet to be written to the wire, and the IO mode that should
186 // be used by the mock socket when performing the write.
187 struct PacketToWrite {
Ryan Hamilton8d9ee76e2018-05-29 23:52:52188 PacketToWrite(IoMode mode, quic::QuicReceivedPacket* packet)
rjshaded5ced072015-12-18 19:26:02189 : mode(mode), packet(packet) {}
rtenneti15656ae2016-01-23 03:05:03190 PacketToWrite(IoMode mode, int rv) : mode(mode), packet(nullptr), rv(rv) {}
[email protected]f702d572012-12-04 15:56:20191 IoMode mode;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52192 quic::QuicReceivedPacket* packet;
rtenneti15656ae2016-01-23 03:05:03193 int rv;
[email protected]f702d572012-12-04 15:56:20194 };
195
196 QuicHttpStreamTest()
Yixin Wang079ad542018-01-11 04:06:05197 : version_(std::get<0>(GetParam())),
198 client_headers_include_h2_stream_dependency_(std::get<1>(GetParam())),
Ryan Hamilton8d9ee76e2018-05-29 23:52:52199 crypto_config_(quic::test::crypto_test_utils::ProofVerifierForTesting(),
200 quic::TlsClientHandshaker::CreateSslCtx()),
Victor Costan9c7302b2018-08-27 16:39:44201 read_buffer_(base::MakeRefCounted<IOBufferWithSize>(4096)),
Fan Yang32c5a112018-12-10 20:06:33202 promise_id_(GetNthServerInitiatedUnidirectionalStreamId(0)),
203 stream_id_(GetNthClientInitiatedBidirectionalStreamId(0)),
David Schinazic8281052019-01-24 06:14:17204 connection_id_(quic::test::TestConnectionId(2)),
Yixin Wang079ad542018-01-11 04:06:05205 client_maker_(version_,
alyssar2adf3ac2016-05-03 17:12:58206 connection_id_,
207 &clock_,
208 kDefaultServerHostName,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52209 quic::Perspective::IS_CLIENT,
Yixin Wang079ad542018-01-11 04:06:05210 client_headers_include_h2_stream_dependency_),
211 server_maker_(version_,
zhongyi5dbfdd42017-06-20 05:22:15212 connection_id_,
alyssar2adf3ac2016-05-03 17:12:58213 &clock_,
214 kDefaultServerHostName,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52215 quic::Perspective::IS_SERVER,
Yixin Wang079ad542018-01-11 04:06:05216 false),
ckrasic3865ee0f2016-02-29 22:04:56217 random_generator_(0),
Ryan Hamilton0d65a8c2019-06-07 00:46:02218 printer_(version_) {
martijn21968ea2016-02-24 18:46:20219 IPAddress ip(192, 0, 2, 33);
[email protected]f702d572012-12-04 15:56:20220 peer_addr_ = IPEndPoint(ip, 443);
221 self_addr_ = IPEndPoint(ip, 8435);
Ryan Hamilton8d9ee76e2018-05-29 23:52:52222 clock_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(20));
Ramin Halavati683bcaa92018-02-14 08:42:39223 request_.traffic_annotation =
224 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f702d572012-12-04 15:56:20225 }
226
227 ~QuicHttpStreamTest() {
Renjieba55fae2018-09-20 03:05:16228 session_->CloseSessionOnError(ERR_ABORTED, quic::QUIC_INTERNAL_ERROR,
229 quic::ConnectionCloseBehavior::SILENT_CLOSE);
[email protected]f702d572012-12-04 15:56:20230 for (size_t i = 0; i < writes_.size(); i++) {
231 delete writes_[i].packet;
232 }
233 }
234
235 // Adds a packet to the list of expected writes.
Ryan Hamilton8d9ee76e2018-05-29 23:52:52236 void AddWrite(std::unique_ptr<quic::QuicReceivedPacket> packet) {
[email protected]1e960032013-12-20 19:00:20237 writes_.push_back(PacketToWrite(SYNCHRONOUS, packet.release()));
[email protected]f702d572012-12-04 15:56:20238 }
239
rtenneti15656ae2016-01-23 03:05:03240 void AddWrite(IoMode mode, int rv) {
241 writes_.push_back(PacketToWrite(mode, rv));
242 }
243
[email protected]f702d572012-12-04 15:56:20244 // Returns the packet to be written at position |pos|.
Ryan Hamilton8d9ee76e2018-05-29 23:52:52245 quic::QuicReceivedPacket* GetWrite(size_t pos) { return writes_[pos].packet; }
[email protected]f702d572012-12-04 15:56:20246
247 bool AtEof() {
rch37de576c2015-05-17 20:28:17248 return socket_data_->AllReadDataConsumed() &&
249 socket_data_->AllWriteDataConsumed();
[email protected]f702d572012-12-04 15:56:20250 }
251
Ryan Hamilton8d9ee76e2018-05-29 23:52:52252 void ProcessPacket(std::unique_ptr<quic::QuicReceivedPacket> packet) {
Victor Vasiliev4f6fb892019-05-31 16:58:31253 connection_->ProcessUdpPacket(ToQuicSocketAddress(self_addr_),
254 ToQuicSocketAddress(peer_addr_), *packet);
[email protected]f702d572012-12-04 15:56:20255 }
256
257 // Configures the test fixture to use the list of expected writes.
258 void Initialize() {
259 mock_writes_.reset(new MockWrite[writes_.size()]);
260 for (size_t i = 0; i < writes_.size(); i++) {
rtenneti15656ae2016-01-23 03:05:03261 if (writes_[i].packet == nullptr) {
262 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].rv, i);
263 } else {
264 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].packet->data(),
265 writes_[i].packet->length());
266 }
bnc614a92d32016-04-04 13:56:07267 }
[email protected]f702d572012-12-04 15:56:20268
rtennetibe635732014-10-02 22:51:42269 socket_data_.reset(new StaticSocketDataProvider(
Ryan Sleevib8d7ea02018-05-07 20:01:01270 base::span<MockRead>(),
271 base::make_span(mock_writes_.get(), writes_.size())));
Ryan Hamilton0d65a8c2019-06-07 00:46:02272 socket_data_->set_printer(&printer_);
[email protected]f702d572012-12-04 15:56:20273
danakjad1777e2016-04-16 00:56:42274 std::unique_ptr<MockUDPClientSocket> socket(new MockUDPClientSocket(
xunjielib53b38c2016-03-24 15:54:36275 socket_data_.get(), net_log_.bound().net_log()));
[email protected]e13201d82012-12-12 05:00:32276 socket->Connect(peer_addr_);
[email protected]f702d572012-12-04 15:56:20277 runner_ = new TestTaskRunner(&clock_);
Ryan Hamilton8d9ee76e2018-05-29 23:52:52278 send_algorithm_ = new quic::test::MockSendAlgorithm();
rch7dd15702015-07-01 18:57:57279 EXPECT_CALL(*send_algorithm_, InRecovery()).WillRepeatedly(Return(false));
280 EXPECT_CALL(*send_algorithm_, InSlowStart()).WillRepeatedly(Return(false));
rjshaded5ced072015-12-18 19:26:02281 EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
Dan Zhangf11470172017-09-18 22:02:09282 .Times(testing::AtLeast(1));
rtenneti44f4a2e2015-08-07 14:00:07283 EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
Zhongyi Shica576df2019-04-12 17:43:40284 .WillRepeatedly(Return(quic::kMaxOutgoingPacketSize));
jokulik0e0a00c32016-06-13 21:51:58285 EXPECT_CALL(*send_algorithm_, PacingRate(_))
Ryan Hamilton8d9ee76e2018-05-29 23:52:52286 .WillRepeatedly(Return(quic::QuicBandwidth::Zero()));
Michael Warres74ee3ce2017-10-09 15:26:37287 EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true));
rtenneti44f4a2e2015-08-07 14:00:07288 EXPECT_CALL(*send_algorithm_, BandwidthEstimate())
Ryan Hamilton8d9ee76e2018-05-29 23:52:52289 .WillRepeatedly(Return(quic::QuicBandwidth::Zero()));
rch1e543ec2015-03-29 07:04:40290 EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(AnyNumber());
rch08cae032017-03-29 00:59:15291 EXPECT_CALL(*send_algorithm_, OnApplicationLimited(_)).Times(AnyNumber());
rch0d5bcf62017-05-24 22:48:45292 EXPECT_CALL(*send_algorithm_, GetCongestionControlType())
293 .Times(AnyNumber());
rch16c74d1d2016-04-22 06:14:07294 helper_.reset(
295 new QuicChromiumConnectionHelper(&clock_, &random_generator_));
296 alarm_factory_.reset(new QuicChromiumAlarmFactory(runner_.get(), &clock_));
297
Michael Warres74ee3ce2017-10-09 15:26:37298 connection_ = new TestQuicConnection(
Nick Harper23290b82019-05-02 00:02:56299 quic::test::SupportedVersions(version_), connection_id_, peer_addr_,
300 helper_.get(), alarm_factory_.get(),
Ryan Hamilton9edcf1a2017-11-22 05:55:17301 new QuicChromiumPacketWriter(
302 socket.get(), base::ThreadTaskRunnerHandle::Get().get()));
[email protected]f702d572012-12-04 15:56:20303 connection_->set_visitor(&visitor_);
[email protected]fee17f72013-02-03 07:47:41304 connection_->SetSendAlgorithm(send_algorithm_);
rch03b7a202016-02-05 00:54:20305
306 // Load a certificate that is valid for *.example.org
307 scoped_refptr<X509Certificate> test_cert(
308 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
309 EXPECT_TRUE(test_cert.get());
310
311 verify_details_.cert_verify_result.verified_cert = test_cert;
312 verify_details_.cert_verify_result.is_issued_by_known_root = true;
313 crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details_);
314
xunjieli84adaab2016-09-20 01:12:28315 base::TimeTicks dns_end = base::TimeTicks::Now();
316 base::TimeTicks dns_start = dns_end - base::TimeDelta::FromMilliseconds(1);
ckrasic4f9d88d2015-07-22 22:23:16317 session_.reset(new QuicChromiumClientSession(
xunjielib53b38c2016-03-24 15:54:36318 connection_, std::move(socket),
rtenneti1cd3b162015-09-29 02:58:28319 /*stream_factory=*/nullptr, &crypto_client_stream_factory_, &clock_,
Nick Harper89bc7212018-07-31 19:07:57320 &transport_security_state_, /*ssl_config_service=*/nullptr,
danakjad1777e2016-04-16 00:56:42321 base::WrapUnique(static_cast<QuicServerInfo*>(nullptr)),
Paul Jensen8e3c5d32018-02-19 17:06:33322 QuicSessionKey(kDefaultServerHostName, kDefaultServerPort,
323 PRIVACY_MODE_DISABLED, SocketTag()),
Zhongyi Shi757fcce2018-06-27 05:41:27324 /*require_confirmation=*/false, /*migrate_session_early_v2=*/false,
325 /*migrate_session_on_network_change_v2=*/false,
326 /*default_network=*/NetworkChangeNotifier::kInvalidNetworkHandle,
Zhongyi Shie01f2db2019-02-22 19:53:23327 quic::QuicTime::Delta::FromMilliseconds(
328 kDefaultRetransmittableOnWireTimeoutMillisecs),
Zhongyi Shi32fe14d42019-02-28 00:25:36329 /*migrate_idle_session=*/false,
Zhongyi Shic16b4102019-02-12 00:37:40330 base::TimeDelta::FromSeconds(kDefaultIdleSessionMigrationPeriodSeconds),
Zhongyi Shi73f23ca872017-12-13 18:37:13331 base::TimeDelta::FromSeconds(kMaxTimeOnNonDefaultNetworkSecs),
Zhongyi Shiee760762018-08-01 00:54:29332 kMaxMigrationsToNonDefaultNetworkOnWriteError,
Zhongyi Shi8b1e43f2017-12-13 20:46:30333 kMaxMigrationsToNonDefaultNetworkOnPathDegrading,
Zhongyi Shi5f587cc2017-11-21 23:24:17334 kQuicYieldAfterPacketsRead,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52335 quic::QuicTime::Delta::FromMilliseconds(
336 kQuicYieldAfterDurationMilliseconds),
Zhongyi Shidbce7f412019-02-01 23:16:29337 /*go_away_on_path_degrading*/ false,
Yixin Wang079ad542018-01-11 04:06:05338 client_headers_include_h2_stream_dependency_, /*cert_verify_flags=*/0,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52339 quic::test::DefaultQuicConfig(), &crypto_config_, "CONNECTION_UNKNOWN",
340 dns_start, dns_end, &push_promise_index_, nullptr,
Zhongyi Shic16b4102019-02-12 00:37:40341 base::DefaultTickClock::GetInstance(),
xunjieli84adaab2016-09-20 01:12:28342 base::ThreadTaskRunnerHandle::Get().get(),
xunjieli5fafe142016-03-23 23:32:54343 /*socket_performance_watcher=*/nullptr, net_log_.bound().net_log()));
rtennetid39bd762015-06-12 01:05:52344 session_->Initialize();
xunjieli100937eb52016-09-15 20:09:37345 TestCompletionCallback callback;
rchf0b18c8a2017-05-05 19:31:57346
rch433bf5f2017-02-14 04:10:47347 session_->CryptoConnect(callback.callback());
Ryan Hamilton6c2a2a82017-12-15 02:06:28348 stream_ = std::make_unique<QuicHttpStream>(
349 session_->CreateHandle(HostPortPair("www.example.org", 443)));
350 promised_stream_ = std::make_unique<QuicHttpStream>(
351 session_->CreateHandle(HostPortPair("www.example.org", 443)));
ckrasic3865ee0f2016-02-29 22:04:56352 push_promise_[":path"] = "/bar";
353 push_promise_[":authority"] = "www.example.org";
354 push_promise_[":version"] = "HTTP/1.1";
355 push_promise_[":method"] = "GET";
356 push_promise_[":scheme"] = "https";
357
358 promised_response_[":status"] = "200 OK";
359 promised_response_[":version"] = "HTTP/1.1";
360 promised_response_["content-type"] = "text/plain";
361
Ryan Hamilton8d9ee76e2018-05-29 23:52:52362 promise_url_ = quic::SpdyUtils::GetPromisedUrlFromHeaders(push_promise_);
[email protected]6cca996b2013-01-25 07:43:36363 }
364
bnc614a92d32016-04-04 13:56:07365 void SetRequest(const string& method,
366 const string& path,
[email protected]1e960032013-12-20 19:00:20367 RequestPriority priority) {
rchcd379012017-04-12 21:53:32368 request_headers_ = client_maker_.GetRequestHeaders(method, "https", path);
[email protected]6cca996b2013-01-25 07:43:36369 }
370
bnc614a92d32016-04-04 13:56:07371 void SetResponse(const string& status, const string& body) {
alyssar2adf3ac2016-05-03 17:12:58372 response_headers_ = server_maker_.GetResponseHeaders(status);
[email protected]92bf17c2014-03-03 21:14:03373 response_data_ = body;
[email protected]6cca996b2013-01-25 07:43:36374 }
[email protected]f702d572012-12-04 15:56:20375
Ryan Hamilton8d9ee76e2018-05-29 23:52:52376 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructDataPacket(
Fan Yangac867502019-01-28 21:10:23377 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52378 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56379 bool should_include_version,
380 bool fin,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52381 quic::QuicStreamOffset offset,
382 quic::QuicStringPiece data,
alyssar2adf3ac2016-05-03 17:12:58383 QuicTestPacketMaker* maker) {
384 return maker->MakeDataPacket(packet_number, stream_id,
ckrasic3865ee0f2016-02-29 22:04:56385 should_include_version, fin, offset, data);
386 }
387
Ryan Hamilton8d9ee76e2018-05-29 23:52:52388 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientDataPacket(
Fan Yangac867502019-01-28 21:10:23389 uint64_t packet_number,
[email protected]e8ff26842013-03-22 21:02:05390 bool should_include_version,
[email protected]f702d572012-12-04 15:56:20391 bool fin,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52392 quic::QuicStreamOffset offset,
393 quic::QuicStringPiece data) {
ckrasic3865ee0f2016-02-29 22:04:56394 return InnerConstructDataPacket(packet_number, stream_id_,
alyssar2adf3ac2016-05-03 17:12:58395 should_include_version, fin, offset, data,
396 &client_maker_);
397 }
398
Renjief49758b2019-01-11 23:32:41399 std::unique_ptr<quic::QuicReceivedPacket>
400 ConstructClientMultipleDataFramesPacket(
Fan Yangac867502019-01-28 21:10:23401 uint64_t packet_number,
Renjief49758b2019-01-11 23:32:41402 bool should_include_version,
403 bool fin,
404 quic::QuicStreamOffset offset,
405 const std::vector<std::string>& data) {
406 return client_maker_.MakeMultipleDataFramesPacket(
407 packet_number, stream_id_, should_include_version, fin, offset, data);
408 }
409
Ryan Hamilton8d9ee76e2018-05-29 23:52:52410 std::unique_ptr<quic::QuicReceivedPacket> ConstructServerDataPacket(
Fan Yangac867502019-01-28 21:10:23411 uint64_t packet_number,
alyssar2adf3ac2016-05-03 17:12:58412 bool should_include_version,
413 bool fin,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52414 quic::QuicStreamOffset offset,
415 quic::QuicStringPiece data) {
alyssar2adf3ac2016-05-03 17:12:58416 return InnerConstructDataPacket(packet_number, stream_id_,
417 should_include_version, fin, offset, data,
418 &server_maker_);
ckrasic3865ee0f2016-02-29 22:04:56419 }
420
Ryan Hamilton8d9ee76e2018-05-29 23:52:52421 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23422 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52423 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56424 bool should_include_version,
425 bool fin,
426 RequestPriority request_priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02427 size_t* spdy_headers_frame_length) {
Yixin Wang7a3f1b8d2018-01-17 21:40:48428 return InnerConstructRequestHeadersPacket(
429 packet_number, stream_id, should_include_version, fin, request_priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02430 0, spdy_headers_frame_length);
Yixin Wang7a3f1b8d2018-01-17 21:40:48431 }
432
Ryan Hamilton8d9ee76e2018-05-29 23:52:52433 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23434 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52435 quic::QuicStreamId stream_id,
Yixin Wang7a3f1b8d2018-01-17 21:40:48436 bool should_include_version,
437 bool fin,
438 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52439 quic::QuicStreamId parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02440 size_t* spdy_headers_frame_length) {
Ryan Hamilton0239aac2018-05-19 00:03:13441 spdy::SpdyPriority priority =
ckrasic3865ee0f2016-02-29 22:04:56442 ConvertRequestPriorityToQuicPriority(request_priority);
alyssar2adf3ac2016-05-03 17:12:58443 return client_maker_.MakeRequestHeadersPacket(
ckrasic3865ee0f2016-02-29 22:04:56444 packet_number, stream_id, should_include_version, fin, priority,
Yixin Wang7a3f1b8d2018-01-17 21:40:48445 std::move(request_headers_), parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02446 spdy_headers_frame_length);
[email protected]f702d572012-12-04 15:56:20447 }
448
Ryan Hamilton8d9ee76e2018-05-29 23:52:52449 std::unique_ptr<quic::QuicReceivedPacket>
Yixin Wange7ecc472018-03-06 19:00:25450 ConstructRequestHeadersAndDataFramesPacket(
Fan Yangac867502019-01-28 21:10:23451 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52452 quic::QuicStreamId stream_id,
Yixin Wange7ecc472018-03-06 19:00:25453 bool should_include_version,
454 bool fin,
455 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52456 quic::QuicStreamId parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25457 size_t* spdy_headers_frame_length,
458 const std::vector<std::string>& data_writes) {
Ryan Hamilton0239aac2018-05-19 00:03:13459 spdy::SpdyPriority priority =
Yixin Wange7ecc472018-03-06 19:00:25460 ConvertRequestPriorityToQuicPriority(request_priority);
461 return client_maker_.MakeRequestHeadersAndMultipleDataFramesPacket(
462 packet_number, stream_id, should_include_version, fin, priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02463 std::move(request_headers_), parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25464 spdy_headers_frame_length, data_writes);
465 }
466
Ryan Hamilton8d9ee76e2018-05-29 23:52:52467 std::unique_ptr<quic::QuicReceivedPacket> ConstructRequestAndRstPacket(
Fan Yangac867502019-01-28 21:10:23468 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52469 quic::QuicStreamId stream_id,
Yixin Wange7ecc472018-03-06 19:00:25470 bool should_include_version,
471 bool fin,
472 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52473 quic::QuicStreamId parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25474 size_t* spdy_headers_frame_length,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52475 quic::QuicRstStreamErrorCode error_code,
Yixin Wange7ecc472018-03-06 19:00:25476 size_t bytes_written) {
Ryan Hamilton0239aac2018-05-19 00:03:13477 spdy::SpdyPriority priority =
Yixin Wange7ecc472018-03-06 19:00:25478 ConvertRequestPriorityToQuicPriority(request_priority);
479 return client_maker_.MakeRequestHeadersAndRstPacket(
480 packet_number, stream_id, should_include_version, fin, priority,
481 std::move(request_headers_), parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02482 spdy_headers_frame_length, error_code, bytes_written);
Yixin Wange7ecc472018-03-06 19:00:25483 }
484
Ryan Hamilton8d9ee76e2018-05-29 23:52:52485 std::unique_ptr<quic::QuicReceivedPacket> ConstructRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23486 uint64_t packet_number,
rtennetif4bdb542015-01-21 14:33:05487 bool fin,
sclittlec4dc1a32015-09-24 00:15:45488 RequestPriority request_priority,
489 size_t* spdy_headers_frame_length) {
ckrasic3865ee0f2016-02-29 22:04:56490 return InnerConstructRequestHeadersPacket(
491 packet_number, stream_id_, kIncludeVersion, fin, request_priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02492 spdy_headers_frame_length);
ckrasic3865ee0f2016-02-29 22:04:56493 }
494
Ryan Hamilton8d9ee76e2018-05-29 23:52:52495 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructResponseHeadersPacket(
Fan Yangac867502019-01-28 21:10:23496 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52497 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56498 bool fin,
499 size_t* spdy_headers_frame_length) {
alyssar2adf3ac2016-05-03 17:12:58500 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26501 packet_number, stream_id, !kIncludeVersion, fin,
Ryan Hamilton0d65a8c2019-06-07 00:46:02502 std::move(response_headers_), spdy_headers_frame_length);
[email protected]1e960032013-12-20 19:00:20503 }
504
Ryan Hamilton8d9ee76e2018-05-29 23:52:52505 std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseHeadersPacket(
Fan Yangac867502019-01-28 21:10:23506 uint64_t packet_number,
sclittlec4dc1a32015-09-24 00:15:45507 bool fin,
508 size_t* spdy_headers_frame_length) {
ckrasic3865ee0f2016-02-29 22:04:56509 return InnerConstructResponseHeadersPacket(packet_number, stream_id_, fin,
510 spdy_headers_frame_length);
[email protected]1e960032013-12-20 19:00:20511 }
512
Ryan Hamilton8d9ee76e2018-05-29 23:52:52513 std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseTrailersPacket(
Fan Yangac867502019-01-28 21:10:23514 uint64_t packet_number,
xunjieli34291fe12016-03-02 13:58:38515 bool fin,
Ryan Hamilton0239aac2018-05-19 00:03:13516 spdy::SpdyHeaderBlock trailers,
Ryan Hamilton0d65a8c2019-06-07 00:46:02517 size_t* spdy_headers_frame_length) {
alyssar2adf3ac2016-05-03 17:12:58518 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26519 packet_number, stream_id_, !kIncludeVersion, fin, std::move(trailers),
Ryan Hamilton0d65a8c2019-06-07 00:46:02520 spdy_headers_frame_length);
xunjieli34291fe12016-03-02 13:58:38521 }
522
Ryan Hamilton8d9ee76e2018-05-29 23:52:52523 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientRstStreamPacket(
Fan Yangac867502019-01-28 21:10:23524 uint64_t packet_number) {
alyssara72f5352016-10-20 12:45:16525 return client_maker_.MakeRstPacket(packet_number, true, stream_id_,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52526 quic::QUIC_RST_ACKNOWLEDGEMENT);
[email protected]06ff5152013-08-29 01:03:05527 }
528
Ryan Hamilton8d9ee76e2018-05-29 23:52:52529 std::unique_ptr<quic::QuicReceivedPacket>
Fan Yangac867502019-01-28 21:10:23530 ConstructClientRstStreamCancelledPacket(uint64_t packet_number) {
alyssar2adf3ac2016-05-03 17:12:58531 return client_maker_.MakeRstPacket(packet_number, !kIncludeVersion,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52532 stream_id_, quic::QUIC_STREAM_CANCELLED);
rtenneti6bd660b2015-07-18 00:19:53533 }
534
Ryan Hamilton8d9ee76e2018-05-29 23:52:52535 std::unique_ptr<quic::QuicReceivedPacket>
Fan Yangac867502019-01-28 21:10:23536 ConstructClientRstStreamVaryMismatchPacket(uint64_t packet_number) {
alyssar2adf3ac2016-05-03 17:12:58537 return client_maker_.MakeRstPacket(packet_number, !kIncludeVersion,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52538 promise_id_,
539 quic::QUIC_PROMISE_VARY_MISMATCH);
ckrasic3865ee0f2016-02-29 22:04:56540 }
541
Fan Yang550c6282018-06-22 18:53:25542 std::unique_ptr<quic::QuicReceivedPacket>
543 ConstructClientRstStreamVaryMismatchAndRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23544 uint64_t packet_number,
Fan Yang550c6282018-06-22 18:53:25545 quic::QuicStreamId stream_id,
546 bool should_include_version,
547 bool fin,
548 RequestPriority request_priority,
549 quic::QuicStreamId parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02550 size_t* spdy_headers_frame_length) {
Fan Yang550c6282018-06-22 18:53:25551 spdy::SpdyPriority priority =
552 ConvertRequestPriorityToQuicPriority(request_priority);
553 return client_maker_.MakeRstAndRequestHeadersPacket(
554 packet_number, should_include_version, promise_id_,
555 quic::QUIC_PROMISE_VARY_MISMATCH, stream_id, fin, priority,
556 std::move(request_headers_), parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02557 spdy_headers_frame_length);
Fan Yang550c6282018-06-22 18:53:25558 }
559
Ryan Hamilton8d9ee76e2018-05-29 23:52:52560 std::unique_ptr<quic::QuicReceivedPacket> ConstructAckAndRstStreamPacket(
Fan Yangac867502019-01-28 21:10:23561 uint64_t packet_number,
562 uint64_t largest_received,
563 uint64_t smallest_received,
564 uint64_t least_unacked) {
alyssar2adf3ac2016-05-03 17:12:58565 return client_maker_.MakeAckAndRstPacket(
Ryan Hamilton8d9ee76e2018-05-29 23:52:52566 packet_number, !kIncludeVersion, stream_id_,
567 quic::QUIC_STREAM_CANCELLED, largest_received, smallest_received,
568 least_unacked, !kIncludeCongestionFeedback);
xunjieli34291fe12016-03-02 13:58:38569 }
570
Ryan Hamilton8d9ee76e2018-05-29 23:52:52571 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientRstStreamErrorPacket(
Fan Yangac867502019-01-28 21:10:23572 uint64_t packet_number,
maksim.sisov84e20c92016-06-23 08:49:34573 bool include_version) {
574 return client_maker_.MakeRstPacket(packet_number, include_version,
575 stream_id_,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52576 quic::QUIC_ERROR_PROCESSING_STREAM);
maksim.sisov84e20c92016-06-23 08:49:34577 }
578
Ryan Hamilton8d9ee76e2018-05-29 23:52:52579 std::unique_ptr<quic::QuicReceivedPacket> ConstructAckAndRstStreamPacket(
Fan Yangac867502019-01-28 21:10:23580 uint64_t packet_number) {
Renjie90e808e2019-01-24 07:24:04581 return ConstructAckAndRstStreamPacket(packet_number, 2, 1, 2);
[email protected]c5e1aca2014-01-30 04:03:04582 }
583
Ryan Hamilton8d9ee76e2018-05-29 23:52:52584 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientAckPacket(
Fan Yangac867502019-01-28 21:10:23585 uint64_t packet_number,
586 uint64_t largest_received,
587 uint64_t smallest_received,
588 uint64_t least_unacked) {
alyssar2adf3ac2016-05-03 17:12:58589 return client_maker_.MakeAckPacket(packet_number, largest_received,
wangyix6444ffe2017-04-25 17:49:49590 smallest_received, least_unacked,
alyssar2adf3ac2016-05-03 17:12:58591 !kIncludeCongestionFeedback);
592 }
593
Ryan Hamilton8d9ee76e2018-05-29 23:52:52594 std::unique_ptr<quic::QuicReceivedPacket> ConstructServerAckPacket(
Fan Yangac867502019-01-28 21:10:23595 uint64_t packet_number,
596 uint64_t largest_received,
597 uint64_t smallest_received,
598 uint64_t least_unacked) {
alyssar2adf3ac2016-05-03 17:12:58599 return server_maker_.MakeAckPacket(packet_number, largest_received,
wangyix6444ffe2017-04-25 17:49:49600 smallest_received, least_unacked,
alyssar2adf3ac2016-05-03 17:12:58601 !kIncludeCongestionFeedback);
[email protected]63534512012-12-23 18:49:00602 }
603
Ryan Hamilton8d9ee76e2018-05-29 23:52:52604 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientPriorityPacket(
Fan Yangac867502019-01-28 21:10:23605 uint64_t packet_number,
Yixin Wangb470bc882018-02-15 18:43:57606 bool should_include_version,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52607 quic::QuicStreamId id,
608 quic::QuicStreamId parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02609 RequestPriority request_priority) {
Yixin Wangb470bc882018-02-15 18:43:57610 return client_maker_.MakePriorityPacket(
611 packet_number, should_include_version, id, parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02612 ConvertRequestPriorityToQuicPriority(request_priority));
Yixin Wangb470bc882018-02-15 18:43:57613 }
614
Ryan Hamilton0d65a8c2019-06-07 00:46:02615 std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket() {
616 return client_maker_.MakeInitialSettingsPacket(1);
fayang3bcb8b502016-12-07 21:44:37617 }
618
Victor Vasiliev076657c2019-03-12 02:46:43619 std::string ConstructDataHeader(size_t body_len) {
Nick Harper23290b82019-05-02 00:02:56620 if (version_.transport_version != quic::QUIC_VERSION_99) {
Renjief49758b2019-01-11 23:32:41621 return "";
622 }
623 quic::HttpEncoder encoder;
624 std::unique_ptr<char[]> buffer;
625 auto header_length = encoder.SerializeDataFrameHeader(body_len, &buffer);
Victor Vasiliev076657c2019-03-12 02:46:43626 return std::string(buffer.get(), header_length);
Renjief49758b2019-01-11 23:32:41627 }
628
Ryan Hamilton8d9ee76e2018-05-29 23:52:52629 void ReceivePromise(quic::QuicStreamId id) {
630 auto headers = quic::test::AsHeaderList(push_promise_);
rch08e198572017-05-09 16:56:55631 QuicChromiumClientStream::Handle* stream =
ckrasic3865ee0f2016-02-29 22:04:56632 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
ckrasic32b17dcd2016-10-31 06:15:35633 stream->OnPromiseHeaderList(id, headers.uncompressed_header_bytes(),
634 headers);
ckrasic3865ee0f2016-02-29 22:04:56635 }
636
xunjieli84adaab2016-09-20 01:12:28637 void ExpectLoadTimingValid(const LoadTimingInfo& load_timing_info,
xunjieli100937eb52016-09-15 20:09:37638 bool session_reused) {
639 EXPECT_EQ(session_reused, load_timing_info.socket_reused);
xunjieli84adaab2016-09-20 01:12:28640 if (session_reused) {
641 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
642 } else {
643 ExpectConnectTimingHasTimes(
644 load_timing_info.connect_timing,
645 CONNECT_TIMING_HAS_SSL_TIMES | CONNECT_TIMING_HAS_DNS_TIMES);
646 }
647 ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info);
xunjieli100937eb52016-09-15 20:09:37648 }
649
Fan Yang32c5a112018-12-10 20:06:33650 quic::QuicStreamId GetNthClientInitiatedBidirectionalStreamId(int n) {
Nick Harper23290b82019-05-02 00:02:56651 return quic::test::GetNthClientInitiatedBidirectionalStreamId(
652 version_.transport_version, n);
ckrasicbf2f59c2017-05-04 23:54:36653 }
654
Fan Yang32c5a112018-12-10 20:06:33655 quic::QuicStreamId GetNthServerInitiatedUnidirectionalStreamId(int n) {
Nick Harper23290b82019-05-02 00:02:56656 return quic::test::GetNthServerInitiatedUnidirectionalStreamId(
657 version_.transport_version, n);
ckrasicbf2f59c2017-05-04 23:54:36658 }
659
Nick Harper23290b82019-05-02 00:02:56660 const quic::ParsedQuicVersion version_;
Yixin Wang079ad542018-01-11 04:06:05661 const bool client_headers_include_h2_stream_dependency_;
662
xunjieli5fafe142016-03-23 23:32:54663 BoundTestNetLog net_log_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52664 quic::test::MockSendAlgorithm* send_algorithm_;
[email protected]f702d572012-12-04 15:56:20665 scoped_refptr<TestTaskRunner> runner_;
danakjad1777e2016-04-16 00:56:42666 std::unique_ptr<MockWrite[]> mock_writes_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52667 quic::MockClock clock_;
[email protected]f702d572012-12-04 15:56:20668 TestQuicConnection* connection_;
danakjad1777e2016-04-16 00:56:42669 std::unique_ptr<QuicChromiumConnectionHelper> helper_;
rch16c74d1d2016-04-22 06:14:07670 std::unique_ptr<QuicChromiumAlarmFactory> alarm_factory_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52671 testing::StrictMock<quic::test::MockQuicConnectionVisitor> visitor_;
rch97827ee2017-05-24 23:49:12672 std::unique_ptr<UploadDataStream> upload_data_stream_;
danakjad1777e2016-04-16 00:56:42673 std::unique_ptr<QuicHttpStream> stream_;
[email protected]5db452202014-08-19 05:22:15674 TransportSecurityState transport_security_state_;
danakjad1777e2016-04-16 00:56:42675 std::unique_ptr<QuicChromiumClientSession> session_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52676 quic::QuicCryptoClientConfig crypto_config_;
[email protected]f702d572012-12-04 15:56:20677 TestCompletionCallback callback_;
678 HttpRequestInfo request_;
679 HttpRequestHeaders headers_;
680 HttpResponseInfo response_;
681 scoped_refptr<IOBufferWithSize> read_buffer_;
Ryan Hamilton0239aac2018-05-19 00:03:13682 spdy::SpdyHeaderBlock request_headers_;
683 spdy::SpdyHeaderBlock response_headers_;
bnc614a92d32016-04-04 13:56:07684 string request_data_;
685 string response_data_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52686 quic::QuicClientPushPromiseIndex push_promise_index_;
[email protected]f702d572012-12-04 15:56:20687
ckrasic3865ee0f2016-02-29 22:04:56688 // For server push testing
danakjad1777e2016-04-16 00:56:42689 std::unique_ptr<QuicHttpStream> promised_stream_;
Ryan Hamilton0239aac2018-05-19 00:03:13690 spdy::SpdyHeaderBlock push_promise_;
691 spdy::SpdyHeaderBlock promised_response_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52692 const quic::QuicStreamId promise_id_;
ckrasic3865ee0f2016-02-29 22:04:56693 string promise_url_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52694 const quic::QuicStreamId stream_id_;
ckrasic3865ee0f2016-02-29 22:04:56695
Ryan Hamilton8d9ee76e2018-05-29 23:52:52696 const quic::QuicConnectionId connection_id_;
alyssar2adf3ac2016-05-03 17:12:58697 QuicTestPacketMaker client_maker_;
698 QuicTestPacketMaker server_maker_;
[email protected]f702d572012-12-04 15:56:20699 IPEndPoint self_addr_;
700 IPEndPoint peer_addr_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52701 quic::test::MockRandom random_generator_;
rch03b7a202016-02-05 00:54:20702 ProofVerifyDetailsChromium verify_details_;
[email protected]e8ff26842013-03-22 21:02:05703 MockCryptoClientStreamFactory crypto_client_stream_factory_;
danakjad1777e2016-04-16 00:56:42704 std::unique_ptr<StaticSocketDataProvider> socket_data_;
Ryan Hamilton0d65a8c2019-06-07 00:46:02705 QuicPacketPrinter printer_;
[email protected]f702d572012-12-04 15:56:20706 std::vector<PacketToWrite> writes_;
707};
708
Victor Costane635086f2019-01-27 05:20:30709INSTANTIATE_TEST_SUITE_P(
Bence Békyce380cb2018-04-26 23:39:55710 VersionIncludeStreamDependencySequence,
Yixin Wang079ad542018-01-11 04:06:05711 QuicHttpStreamTest,
Victor Vasiliev5d6cdc22019-05-28 20:37:43712 ::testing::Combine(::testing::ValuesIn(quic::AllVersionsExcept99()),
Nick Harper23290b82019-05-02 00:02:56713 ::testing::Bool()));
[email protected]1e960032013-12-20 19:00:20714
715TEST_P(QuicHttpStreamTest, RenewStreamForAuth) {
[email protected]ed3fc15d2013-03-08 18:37:44716 Initialize();
rtennetibe635732014-10-02 22:51:42717 EXPECT_EQ(nullptr, stream_->RenewStreamForAuth());
[email protected]f702d572012-12-04 15:56:20718}
719
mmenkebd84c392015-09-02 14:12:34720TEST_P(QuicHttpStreamTest, CanReuseConnection) {
[email protected]ed3fc15d2013-03-08 18:37:44721 Initialize();
mmenkebd84c392015-09-02 14:12:34722 EXPECT_FALSE(stream_->CanReuseConnection());
[email protected]f702d572012-12-04 15:56:20723}
724
jri231c2972016-03-08 19:50:11725TEST_P(QuicHttpStreamTest, DisableConnectionMigrationForStream) {
Zhongyi Shibb28b1f2018-07-18 02:41:26726 request_.load_flags |= LOAD_DISABLE_CONNECTION_MIGRATION_TO_CELLULAR;
jri231c2972016-03-08 19:50:11727 Initialize();
xunjieli5fafe142016-03-23 23:32:54728 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27729 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:54730 net_log_.bound(), callback_.callback()));
rch08e198572017-05-09 16:56:55731 QuicChromiumClientStream::Handle* client_stream =
jri231c2972016-03-08 19:50:11732 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
Zhongyi Shibb28b1f2018-07-18 02:41:26733 EXPECT_FALSE(client_stream->can_migrate_to_cellular_network());
jri231c2972016-03-08 19:50:11734}
735
[email protected]1e960032013-12-20 19:00:20736TEST_P(QuicHttpStreamTest, GetRequest) {
737 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:45738 size_t spdy_request_header_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:02739 AddWrite(ConstructInitialSettingsPacket());
fayang3bcb8b502016-12-07 21:44:37740 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33741 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:02742 DEFAULT_PRIORITY, &spdy_request_header_frame_length));
fayang3bcb8b502016-12-07 21:44:37743
[email protected]f702d572012-12-04 15:56:20744 Initialize();
745
746 request_.method = "GET";
rchcd379012017-04-12 21:53:32747 request_.url = GURL("https://www.example.org/");
[email protected]f702d572012-12-04 15:56:20748
xunjieli100937eb52016-09-15 20:09:37749 // Make sure getting load timing from the stream early does not crash.
750 LoadTimingInfo load_timing_info;
751 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
752
xunjieli5fafe142016-03-23 23:32:54753 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27754 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:54755 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:02756 EXPECT_EQ(OK,
757 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20758
759 // Ack the request.
Renjie90e808e2019-01-24 07:24:04760 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]f702d572012-12-04 15:56:20761
robpercival214763f2016-07-01 23:27:01762 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
763 IsError(ERR_IO_PENDING));
[email protected]f702d572012-12-04 15:56:20764
bnc614a92d32016-04-04 13:56:07765 SetResponse("404 Not Found", string());
sclittlec4dc1a32015-09-24 00:15:45766 size_t spdy_response_header_frame_length;
767 ProcessPacket(ConstructResponseHeadersPacket(
768 2, kFin, &spdy_response_header_frame_length));
[email protected]f702d572012-12-04 15:56:20769
770 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:01771 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]cadac622013-06-11 16:46:36772 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:20773 EXPECT_EQ(404, response_.headers->response_code());
774 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
[email protected]6ed67432014-06-24 01:53:53775 EXPECT_FALSE(response_.response_time.is_null());
776 EXPECT_FALSE(response_.request_time.is_null());
[email protected]f702d572012-12-04 15:56:20777
778 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:02779 EXPECT_EQ(0,
780 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
781 callback_.callback()));
[email protected]f702d572012-12-04 15:56:20782 EXPECT_TRUE(stream_->IsResponseBodyComplete());
783 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:10784
xunjieli100937eb52016-09-15 20:09:37785 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
xunjieli84adaab2016-09-20 01:12:28786 ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
xunjieli100937eb52016-09-15 20:09:37787
sclittle1edeeb22015-09-02 20:46:10788 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:45789 // headers and payload.
790 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
791 stream_->GetTotalSentBytes());
792 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length),
793 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:20794}
795
xunjieli100937eb52016-09-15 20:09:37796TEST_P(QuicHttpStreamTest, LoadTimingTwoRequests) {
797 SetRequest("GET", "/", DEFAULT_PRIORITY);
798 size_t spdy_request_header_frame_length;
799
Ryan Hamilton0d65a8c2019-06-07 00:46:02800 AddWrite(ConstructInitialSettingsPacket());
xunjieli100937eb52016-09-15 20:09:37801 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33802 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:02803 DEFAULT_PRIORITY, &spdy_request_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37804
805 // SetRequest() again for second request as |request_headers_| was moved.
806 SetRequest("GET", "/", DEFAULT_PRIORITY);
807 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33808 3, GetNthClientInitiatedBidirectionalStreamId(1), kIncludeVersion, kFin,
809 DEFAULT_PRIORITY, GetNthClientInitiatedBidirectionalStreamId(0),
Ryan Hamilton0d65a8c2019-06-07 00:46:02810 &spdy_request_header_frame_length));
Renjie90e808e2019-01-24 07:24:04811 AddWrite(ConstructClientAckPacket(4, 3, 1, 2)); // Ack the responses.
xunjieli100937eb52016-09-15 20:09:37812
813 Initialize();
814
815 request_.method = "GET";
rchcd379012017-04-12 21:53:32816 request_.url = GURL("https://www.example.org/");
xunjieli100937eb52016-09-15 20:09:37817 // Start first request.
818 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27819 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli100937eb52016-09-15 20:09:37820 net_log_.bound(), callback_.callback()));
821 EXPECT_EQ(OK,
822 stream_->SendRequest(headers_, &response_, callback_.callback()));
823
824 // Start a second request.
Ryan Hamilton6c2a2a82017-12-15 02:06:28825 QuicHttpStream stream2(
826 session_->CreateHandle(HostPortPair("www.example.org", 443)));
xunjieli100937eb52016-09-15 20:09:37827 TestCompletionCallback callback2;
828 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27829 stream2.InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli100937eb52016-09-15 20:09:37830 net_log_.bound(), callback2.callback()));
831 EXPECT_EQ(OK,
832 stream2.SendRequest(headers_, &response_, callback2.callback()));
833
834 // Ack both requests.
Renjie90e808e2019-01-24 07:24:04835 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
xunjieli100937eb52016-09-15 20:09:37836
837 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
838 IsError(ERR_IO_PENDING));
839 size_t spdy_response_header_frame_length;
840 SetResponse("200 OK", string());
841 ProcessPacket(InnerConstructResponseHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33842 2, GetNthClientInitiatedBidirectionalStreamId(0), kFin,
ckrasicbf2f59c2017-05-04 23:54:36843 &spdy_response_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37844
845 // Now that the headers have been processed, the callback will return.
846 EXPECT_THAT(callback_.WaitForResult(), IsOk());
847 EXPECT_EQ(200, response_.headers->response_code());
848
849 // There is no body, so this should return immediately.
850 EXPECT_EQ(0,
851 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
852 callback_.callback()));
853 EXPECT_TRUE(stream_->IsResponseBodyComplete());
854
855 LoadTimingInfo load_timing_info;
856 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
xunjieli84adaab2016-09-20 01:12:28857 ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
xunjieli100937eb52016-09-15 20:09:37858
859 // SetResponse() again for second request as |response_headers_| was moved.
860 SetResponse("200 OK", string());
861 EXPECT_THAT(stream2.ReadResponseHeaders(callback2.callback()),
862 IsError(ERR_IO_PENDING));
863
864 ProcessPacket(InnerConstructResponseHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33865 3, GetNthClientInitiatedBidirectionalStreamId(1), kFin,
ckrasicbf2f59c2017-05-04 23:54:36866 &spdy_response_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37867
868 EXPECT_THAT(callback2.WaitForResult(), IsOk());
869
870 // There is no body, so this should return immediately.
871 EXPECT_EQ(0,
872 stream2.ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
873 callback2.callback()));
874 EXPECT_TRUE(stream2.IsResponseBodyComplete());
875
876 LoadTimingInfo load_timing_info2;
877 EXPECT_TRUE(stream2.GetLoadTimingInfo(&load_timing_info2));
xunjieli84adaab2016-09-20 01:12:28878 ExpectLoadTimingValid(load_timing_info2, /*session_reused=*/true);
xunjieli100937eb52016-09-15 20:09:37879}
880
xunjieli34291fe12016-03-02 13:58:38881// QuicHttpStream does not currently support trailers. It should ignore
882// trailers upon receiving them.
883TEST_P(QuicHttpStreamTest, GetRequestWithTrailers) {
884 SetRequest("GET", "/", DEFAULT_PRIORITY);
885 size_t spdy_request_header_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:02886 AddWrite(ConstructInitialSettingsPacket());
fayang3bcb8b502016-12-07 21:44:37887 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33888 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:02889 DEFAULT_PRIORITY, &spdy_request_header_frame_length));
Renjie90e808e2019-01-24 07:24:04890 AddWrite(ConstructClientAckPacket(3, 3, 1, 2)); // Ack the data packet.
xunjieli34291fe12016-03-02 13:58:38891
892 Initialize();
893
894 request_.method = "GET";
rchcd379012017-04-12 21:53:32895 request_.url = GURL("https://www.example.org/");
xunjieli34291fe12016-03-02 13:58:38896
xunjieli5fafe142016-03-23 23:32:54897 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27898 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:54899 net_log_.bound(), callback_.callback()));
900
xunjieli34291fe12016-03-02 13:58:38901 EXPECT_EQ(OK,
902 stream_->SendRequest(headers_, &response_, callback_.callback()));
xunjieli34291fe12016-03-02 13:58:38903 // Ack the request.
Renjie90e808e2019-01-24 07:24:04904 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
xunjieli34291fe12016-03-02 13:58:38905
robpercival214763f2016-07-01 23:27:01906 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
907 IsError(ERR_IO_PENDING));
xunjieli34291fe12016-03-02 13:58:38908
bnc614a92d32016-04-04 13:56:07909 SetResponse("200 OK", string());
xunjieli34291fe12016-03-02 13:58:38910
911 // Send the response headers.
912 size_t spdy_response_header_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:02913 ProcessPacket(ConstructResponseHeadersPacket(
914 2, !kFin, &spdy_response_header_frame_length));
xunjieli34291fe12016-03-02 13:58:38915 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:01916 EXPECT_THAT(callback_.WaitForResult(), IsOk());
xunjieli34291fe12016-03-02 13:58:38917 ASSERT_TRUE(response_.headers.get());
918 EXPECT_EQ(200, response_.headers->response_code());
919 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
920 EXPECT_FALSE(response_.response_time.is_null());
921 EXPECT_FALSE(response_.request_time.is_null());
922
923 // Send the response body.
924 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:43925 std::string header = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:41926 ProcessPacket(ConstructServerDataPacket(3, false, !kFin, /*offset=*/0,
927 header + kResponseBody));
Ryan Hamilton0239aac2018-05-19 00:03:13928 spdy::SpdyHeaderBlock trailers;
xunjieli34291fe12016-03-02 13:58:38929 size_t spdy_trailers_frame_length;
930 trailers["foo"] = "bar";
Ryan Hamilton8d9ee76e2018-05-29 23:52:52931 trailers[quic::kFinalOffsetHeaderKey] =
Raul Tambre8c1981d2019-02-08 02:22:26932 base::NumberToString(strlen(kResponseBody) + header.length());
Ryan Hamilton0d65a8c2019-06-07 00:46:02933 ProcessPacket(ConstructResponseTrailersPacket(4, kFin, std::move(trailers),
934 &spdy_trailers_frame_length));
xunjieli34291fe12016-03-02 13:58:38935
936 // Make sure trailers are processed.
fdoray92e35a72016-06-10 15:54:55937 base::RunLoop().RunUntilIdle();
xunjieli34291fe12016-03-02 13:58:38938
939 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
940 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
941 callback_.callback()));
942 EXPECT_TRUE(stream_->IsResponseBodyComplete());
943
944 EXPECT_EQ(OK,
945 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
946 callback_.callback()));
947
948 EXPECT_TRUE(stream_->IsResponseBodyComplete());
949 EXPECT_TRUE(AtEof());
950
951 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
952 // headers and payload.
953 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
954 stream_->GetTotalSentBytes());
Renjief49758b2019-01-11 23:32:41955 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length +
956 strlen(kResponseBody) + header.length() +
957 +spdy_trailers_frame_length),
958 stream_->GetTotalReceivedBytes());
xunjieli5fafe142016-03-23 23:32:54959 // Check that NetLog was filled as expected.
960 TestNetLogEntry::List entries;
961 net_log_.GetEntries(&entries);
962 size_t pos = ExpectLogContainsSomewhere(
963 entries, /*min_offset=*/0,
mikecirone8b85c432016-09-08 19:11:00964 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
965 NetLogEventPhase::NONE);
xunjieli5fafe142016-03-23 23:32:54966 pos = ExpectLogContainsSomewhere(
967 entries, /*min_offset=*/pos,
mikecirone8b85c432016-09-08 19:11:00968 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
969 NetLogEventPhase::NONE);
xunjieli5fafe142016-03-23 23:32:54970 ExpectLogContainsSomewhere(
971 entries, /*min_offset=*/pos,
mikecirone8b85c432016-09-08 19:11:00972 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
973 NetLogEventPhase::NONE);
xunjieli34291fe12016-03-02 13:58:38974}
975
[email protected]3e7dca62013-09-10 16:14:23976// Regression test for http://crbug.com/288128
[email protected]1e960032013-12-20 19:00:20977TEST_P(QuicHttpStreamTest, GetRequestLargeResponse) {
978 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:45979 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:02980 AddWrite(ConstructInitialSettingsPacket());
fayang3bcb8b502016-12-07 21:44:37981 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33982 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:02983 DEFAULT_PRIORITY, &spdy_request_headers_frame_length));
[email protected]3e7dca62013-09-10 16:14:23984 Initialize();
985
986 request_.method = "GET";
rchcd379012017-04-12 21:53:32987 request_.url = GURL("https://www.example.org/");
[email protected]3e7dca62013-09-10 16:14:23988
xunjieli5fafe142016-03-23 23:32:54989 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27990 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:54991 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:02992 EXPECT_EQ(OK,
993 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:23994
995 // Ack the request.
Renjie90e808e2019-01-24 07:24:04996 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]3e7dca62013-09-10 16:14:23997
robpercival214763f2016-07-01 23:27:01998 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
999 IsError(ERR_IO_PENDING));
[email protected]3e7dca62013-09-10 16:14:231000
bnc086b39e12016-06-24 13:05:261001 response_headers_[":status"] = "200 OK";
1002 response_headers_[":version"] = "HTTP/1.1";
1003 response_headers_["content-type"] = "text/plain";
1004 response_headers_["big6"] = string(1000, 'x'); // Lots of x's.
[email protected]3e7dca62013-09-10 16:14:231005
sclittlec4dc1a32015-09-24 00:15:451006 size_t spdy_response_headers_frame_length;
1007 ProcessPacket(ConstructResponseHeadersPacket(
1008 2, kFin, &spdy_response_headers_frame_length));
[email protected]3e7dca62013-09-10 16:14:231009
1010 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:011011 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]3e7dca62013-09-10 16:14:231012 ASSERT_TRUE(response_.headers.get());
1013 EXPECT_EQ(200, response_.headers->response_code());
1014 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1015
1016 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:021017 EXPECT_EQ(0,
1018 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1019 callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:231020 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1021 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101022
1023 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451024 // headers and payload.
1025 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1026 stream_->GetTotalSentBytes());
1027 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length),
1028 stream_->GetTotalReceivedBytes());
[email protected]3e7dca62013-09-10 16:14:231029}
1030
rchf9f103cbc2014-08-30 05:28:041031// Regression test for http://crbug.com/409101
1032TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendRequest) {
1033 SetRequest("GET", "/", DEFAULT_PRIORITY);
1034 Initialize();
1035
1036 request_.method = "GET";
rchcd379012017-04-12 21:53:321037 request_.url = GURL("https://www.example.org/");
rchf9f103cbc2014-08-30 05:28:041038
xunjieli5fafe142016-03-23 23:32:541039 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271040 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541041 net_log_.bound(), callback_.callback()));
rchf9f103cbc2014-08-30 05:28:041042
jri78ec06a2016-03-31 18:19:401043 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521044 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rchf9f103cbc2014-08-30 05:28:041045
1046 EXPECT_EQ(ERR_CONNECTION_CLOSED,
rjshaded5ced072015-12-18 19:26:021047 stream_->SendRequest(headers_, &response_, callback_.callback()));
sclittle1edeeb22015-09-02 20:46:101048
1049 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1050 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rchf9f103cbc2014-08-30 05:28:041051}
1052
rch03b7a202016-02-05 00:54:201053// Regression test for http://crbug.com/584441
1054TEST_P(QuicHttpStreamTest, GetSSLInfoAfterSessionClosed) {
1055 SetRequest("GET", "/", DEFAULT_PRIORITY);
1056 Initialize();
1057
1058 request_.method = "GET";
rchcd379012017-04-12 21:53:321059 request_.url = GURL("https://www.example.org/");
rch03b7a202016-02-05 00:54:201060
xunjieli5fafe142016-03-23 23:32:541061 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271062 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541063 net_log_.bound(), callback_.callback()));
rch03b7a202016-02-05 00:54:201064
1065 SSLInfo ssl_info;
rch11565e02016-02-09 20:13:471066 EXPECT_FALSE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:201067 stream_->GetSSLInfo(&ssl_info);
rch11565e02016-02-09 20:13:471068 EXPECT_TRUE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:201069
jri78ec06a2016-03-31 18:19:401070 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521071 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rch03b7a202016-02-05 00:54:201072
rch11565e02016-02-09 20:13:471073 SSLInfo ssl_info2;
1074 stream_->GetSSLInfo(&ssl_info2);
1075 EXPECT_TRUE(ssl_info2.is_valid());
rch03b7a202016-02-05 00:54:201076}
1077
rchcd379012017-04-12 21:53:321078TEST_P(QuicHttpStreamTest, GetAlternativeService) {
1079 SetRequest("GET", "/", DEFAULT_PRIORITY);
1080 Initialize();
1081
1082 request_.method = "GET";
1083 request_.url = GURL("https://www.example.org/");
1084
1085 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271086 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
rchcd379012017-04-12 21:53:321087 net_log_.bound(), callback_.callback()));
1088
1089 AlternativeService alternative_service;
1090 EXPECT_TRUE(stream_->GetAlternativeService(&alternative_service));
1091 EXPECT_EQ(AlternativeService(kProtoQUIC, "www.example.org", 443),
1092 alternative_service);
1093
1094 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521095 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rchcd379012017-04-12 21:53:321096
1097 AlternativeService alternative_service2;
1098 EXPECT_TRUE(stream_->GetAlternativeService(&alternative_service2));
1099 EXPECT_EQ(AlternativeService(kProtoQUIC, "www.example.org", 443),
1100 alternative_service2);
1101}
1102
zhongyica364fbb2015-12-12 03:39:121103TEST_P(QuicHttpStreamTest, LogGranularQuicConnectionError) {
1104 SetRequest("GET", "/", DEFAULT_PRIORITY);
1105 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:021106 AddWrite(ConstructInitialSettingsPacket());
fayang3bcb8b502016-12-07 21:44:371107 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:331108 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:021109 DEFAULT_PRIORITY, &spdy_request_headers_frame_length));
fayang3bcb8b502016-12-07 21:44:371110 AddWrite(ConstructAckAndRstStreamPacket(3));
zhongyica364fbb2015-12-12 03:39:121111 Initialize();
1112
1113 request_.method = "GET";
rchcd379012017-04-12 21:53:321114 request_.url = GURL("https://www.example.org/");
zhongyica364fbb2015-12-12 03:39:121115
xunjieli5fafe142016-03-23 23:32:541116 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271117 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541118 net_log_.bound(), callback_.callback()));
zhongyica364fbb2015-12-12 03:39:121119 EXPECT_EQ(OK,
1120 stream_->SendRequest(headers_, &response_, callback_.callback()));
1121
1122 // Ack the request.
Renjie90e808e2019-01-24 07:24:041123 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011124 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1125 IsError(ERR_IO_PENDING));
zhongyica364fbb2015-12-12 03:39:121126
Ryan Hamilton8d9ee76e2018-05-29 23:52:521127 quic::QuicConnectionCloseFrame frame;
Zhongyi Shica576df2019-04-12 17:43:401128 frame.quic_error_code = quic::QUIC_PEER_GOING_AWAY;
rch1c5b74a2016-06-23 22:10:551129 session_->connection()->OnConnectionCloseFrame(frame);
zhongyica364fbb2015-12-12 03:39:121130
1131 NetErrorDetails details;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521132 EXPECT_EQ(quic::QUIC_NO_ERROR, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121133 stream_->PopulateNetErrorDetails(&details);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521134 EXPECT_EQ(quic::QUIC_PEER_GOING_AWAY, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121135}
1136
Ryan Hamiltone316e482017-08-17 02:48:531137TEST_P(QuicHttpStreamTest, LogGranularQuicErrorIfHandshakeNotConfirmed) {
rch617e0652017-04-26 17:57:511138 // By default the test setup defaults handshake to be confirmed. Manually set
1139 // it to be not confirmed.
rch617e0652017-04-26 17:57:511140 crypto_client_stream_factory_.set_handshake_mode(
Ryan Hamilton9835e662018-08-02 05:36:271141 MockCryptoClientStream::ZERO_RTT);
rch617e0652017-04-26 17:57:511142
zhongyica364fbb2015-12-12 03:39:121143 SetRequest("GET", "/", DEFAULT_PRIORITY);
1144 size_t spdy_request_headers_frame_length;
Michael Warres167db3e2019-03-01 21:38:031145 client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
fayang3bcb8b502016-12-07 21:44:371146 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:331147 1, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:021148 DEFAULT_PRIORITY, &spdy_request_headers_frame_length));
zhongyica364fbb2015-12-12 03:39:121149 Initialize();
1150
1151 request_.method = "GET";
rchcd379012017-04-12 21:53:321152 request_.url = GURL("https://www.example.org/");
zhongyica364fbb2015-12-12 03:39:121153
xunjieli5fafe142016-03-23 23:32:541154 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271155 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541156 net_log_.bound(), callback_.callback()));
zhongyica364fbb2015-12-12 03:39:121157 EXPECT_EQ(OK,
1158 stream_->SendRequest(headers_, &response_, callback_.callback()));
1159
1160 // Ack the request.
Renjie90e808e2019-01-24 07:24:041161 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011162 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1163 IsError(ERR_IO_PENDING));
zhongyica364fbb2015-12-12 03:39:121164
Ryan Hamilton8d9ee76e2018-05-29 23:52:521165 quic::QuicConnectionCloseFrame frame;
Zhongyi Shica576df2019-04-12 17:43:401166 frame.quic_error_code = quic::QUIC_PEER_GOING_AWAY;
rch1c5b74a2016-06-23 22:10:551167 session_->connection()->OnConnectionCloseFrame(frame);
zhongyica364fbb2015-12-12 03:39:121168
1169 NetErrorDetails details;
zhongyica364fbb2015-12-12 03:39:121170 stream_->PopulateNetErrorDetails(&details);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521171 EXPECT_EQ(quic::QUIC_PEER_GOING_AWAY, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121172}
1173
rch11a114a2014-09-04 23:41:591174// Regression test for http://crbug.com/409871
1175TEST_P(QuicHttpStreamTest, SessionClosedBeforeReadResponseHeaders) {
1176 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451177 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:021178 AddWrite(ConstructInitialSettingsPacket());
fayang3bcb8b502016-12-07 21:44:371179 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:331180 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:021181 DEFAULT_PRIORITY, &spdy_request_headers_frame_length));
rch11a114a2014-09-04 23:41:591182 Initialize();
1183
1184 request_.method = "GET";
rchcd379012017-04-12 21:53:321185 request_.url = GURL("https://www.example.org/");
rch11a114a2014-09-04 23:41:591186
xunjieli5fafe142016-03-23 23:32:541187 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271188 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541189 net_log_.bound(), callback_.callback()));
rch11a114a2014-09-04 23:41:591190
rjshaded5ced072015-12-18 19:26:021191 EXPECT_EQ(OK,
1192 stream_->SendRequest(headers_, &response_, callback_.callback()));
rch11a114a2014-09-04 23:41:591193
jri78ec06a2016-03-31 18:19:401194 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521195 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rch11a114a2014-09-04 23:41:591196
1197 EXPECT_NE(OK, stream_->ReadResponseHeaders(callback_.callback()));
sclittle1edeeb22015-09-02 20:46:101198
1199 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451200 // headers and payload.
1201 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1202 stream_->GetTotalSentBytes());
sclittle1edeeb22015-09-02 20:46:101203 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rch11a114a2014-09-04 23:41:591204}
1205
[email protected]1e960032013-12-20 19:00:201206TEST_P(QuicHttpStreamTest, SendPostRequest) {
1207 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451208 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:021209 AddWrite(ConstructInitialSettingsPacket());
Yixin Wange7ecc472018-03-06 19:00:251210
Victor Vasiliev076657c2019-03-12 02:46:431211 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harper23290b82019-05-02 00:02:561212 if (version_.transport_version != quic::QUIC_VERSION_99) {
Renjief49758b2019-01-11 23:32:411213 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1214 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:021215 DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
1216 {kUploadData}));
Renjief49758b2019-01-11 23:32:411217 } else {
1218 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1219 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:021220 DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
1221 {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411222 }
Yixin Wange7ecc472018-03-06 19:00:251223
Renjie90e808e2019-01-24 07:24:041224 AddWrite(ConstructClientAckPacket(3, 3, 1, 2));
[email protected]f702d572012-12-04 15:56:201225
1226 Initialize();
1227
danakjad1777e2016-04-16 00:56:421228 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:191229 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
ricea2deef682016-09-09 08:04:071230 kUploadData, strlen(kUploadData)));
rch97827ee2017-05-24 23:49:121231 upload_data_stream_ =
Jeremy Roman0579ed62017-08-29 15:56:191232 std::make_unique<ElementsUploadDataStream>(std::move(element_readers), 0);
[email protected]f702d572012-12-04 15:56:201233 request_.method = "POST";
rchcd379012017-04-12 21:53:321234 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121235 request_.upload_data_stream = upload_data_stream_.get();
Bence Békyd8a21fc32018-06-27 18:29:581236 ASSERT_THAT(request_.upload_data_stream->Init(CompletionOnceCallback(),
tfarina42834112016-09-22 13:38:201237 NetLogWithSource()),
1238 IsOk());
[email protected]f702d572012-12-04 15:56:201239
xunjieli5fafe142016-03-23 23:32:541240 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271241 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541242 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021243 EXPECT_EQ(OK,
1244 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:201245
1246 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041247 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]f702d572012-12-04 15:56:201248
1249 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071250 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451251 size_t spdy_response_headers_frame_length;
1252 ProcessPacket(ConstructResponseHeadersPacket(
1253 2, !kFin, &spdy_response_headers_frame_length));
[email protected]f702d572012-12-04 15:56:201254
rchfb47f712017-05-21 03:24:001255 // The headers have already arrived.
1256 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]cadac622013-06-11 16:46:361257 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:201258 EXPECT_EQ(200, response_.headers->response_code());
1259 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1260
1261 // Send the response body.
1262 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431263 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:411264 ProcessPacket(
1265 ConstructServerDataPacket(3, false, kFin, 0, header2 + kResponseBody));
[email protected]f702d572012-12-04 15:56:201266 // Since the body has already arrived, this should return immediately.
1267 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
1268 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1269 callback_.callback()));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291270 EXPECT_EQ(0,
1271 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1272 callback_.callback()));
1273
1274 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1275 EXPECT_TRUE(AtEof());
1276
1277 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
1278 // headers and payload.
1279 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411280 strlen(kUploadData) + header.length()),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291281 stream_->GetTotalSentBytes());
1282 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411283 strlen(kResponseBody) + header2.length()),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291284 stream_->GetTotalReceivedBytes());
1285}
1286
1287TEST_P(QuicHttpStreamTest, SendPostRequestAndReceiveSoloFin) {
1288 SetRequest("POST", "/", DEFAULT_PRIORITY);
1289 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:021290 AddWrite(ConstructInitialSettingsPacket());
Victor Vasiliev076657c2019-03-12 02:46:431291 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harper23290b82019-05-02 00:02:561292 if (version_.transport_version != quic::QUIC_VERSION_99) {
Renjief49758b2019-01-11 23:32:411293 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1294 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:021295 DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
1296 {kUploadData}));
Renjief49758b2019-01-11 23:32:411297 } else {
1298 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1299 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:021300 DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
1301 {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411302 }
1303
Renjie90e808e2019-01-24 07:24:041304 AddWrite(ConstructClientAckPacket(3, 3, 1, 2));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291305
1306 Initialize();
1307
1308 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:191309 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
Ryan Hamilton2ef0a9c2017-07-25 03:18:291310 kUploadData, strlen(kUploadData)));
1311 upload_data_stream_ =
Jeremy Roman0579ed62017-08-29 15:56:191312 std::make_unique<ElementsUploadDataStream>(std::move(element_readers), 0);
Ryan Hamilton2ef0a9c2017-07-25 03:18:291313 request_.method = "POST";
1314 request_.url = GURL("https://www.example.org/");
1315 request_.upload_data_stream = upload_data_stream_.get();
Bence Békyd8a21fc32018-06-27 18:29:581316 ASSERT_THAT(request_.upload_data_stream->Init(CompletionOnceCallback(),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291317 NetLogWithSource()),
1318 IsOk());
1319
1320 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271321 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
Ryan Hamilton2ef0a9c2017-07-25 03:18:291322 net_log_.bound(), callback_.callback()));
1323 EXPECT_EQ(OK,
1324 stream_->SendRequest(headers_, &response_, callback_.callback()));
1325
1326 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041327 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291328
1329 // Send the response headers (but not the body).
1330 SetResponse("200 OK", string());
1331 size_t spdy_response_headers_frame_length;
1332 ProcessPacket(ConstructResponseHeadersPacket(
1333 2, !kFin, &spdy_response_headers_frame_length));
1334
1335 // The headers have already arrived.
1336 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
1337 ASSERT_TRUE(response_.headers.get());
1338 EXPECT_EQ(200, response_.headers->response_code());
1339 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1340
1341 // Send the response body.
1342 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431343 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:411344 ProcessPacket(
1345 ConstructServerDataPacket(3, false, !kFin, 0, header2 + kResponseBody));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291346 // Since the body has already arrived, this should return immediately.
1347 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
1348 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1349 callback_.callback()));
Renjief49758b2019-01-11 23:32:411350 ProcessPacket(ConstructServerDataPacket(
1351 4, false, kFin, base::size(kResponseBody) - 1 + header2.length(), ""));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291352 EXPECT_EQ(0,
1353 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1354 callback_.callback()));
[email protected]f702d572012-12-04 15:56:201355
1356 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1357 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101358
1359 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451360 // headers and payload.
1361 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411362 strlen(kUploadData) + header.length()),
sclittle1edeeb22015-09-02 20:46:101363 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451364 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411365 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101366 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:201367}
1368
[email protected]1e960032013-12-20 19:00:201369TEST_P(QuicHttpStreamTest, SendChunkedPostRequest) {
1370 SetRequest("POST", "/", DEFAULT_PRIORITY);
[email protected]c9e49a02013-02-26 05:56:471371 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:451372 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:021373 AddWrite(ConstructInitialSettingsPacket());
Victor Vasiliev076657c2019-03-12 02:46:431374 std::string header = ConstructDataHeader(chunk_size);
Nick Harper23290b82019-05-02 00:02:561375 if (version_.transport_version == quic::QUIC_VERSION_99) {
Renjief49758b2019-01-11 23:32:411376 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1377 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
Ryan Hamilton0d65a8c2019-06-07 00:46:021378 !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
1379 {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411380 AddWrite(ConstructClientMultipleDataFramesPacket(
1381 3, kIncludeVersion, kFin, header.length() + chunk_size,
1382 {header, kUploadData}));
1383 } else {
1384 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1385 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
Ryan Hamilton0d65a8c2019-06-07 00:46:021386 !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
1387 {kUploadData}));
Renjief49758b2019-01-11 23:32:411388 AddWrite(ConstructClientDataPacket(3, kIncludeVersion, kFin, chunk_size,
1389 kUploadData));
1390 }
1391
Renjie90e808e2019-01-24 07:24:041392 AddWrite(ConstructClientAckPacket(4, 3, 1, 2));
[email protected]c9e49a02013-02-26 05:56:471393 Initialize();
1394
Jeremy Roman0579ed62017-08-29 15:56:191395 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121396 auto* chunked_upload_stream =
1397 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1398 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
[email protected]c9e49a02013-02-26 05:56:471399
1400 request_.method = "POST";
rchcd379012017-04-12 21:53:321401 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121402 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071403 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201404 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]c9e49a02013-02-26 05:56:471405
xunjieli5fafe142016-03-23 23:32:541406 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271407 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541408 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021409 ASSERT_EQ(ERR_IO_PENDING,
1410 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]c9e49a02013-02-26 05:56:471411
rch97827ee2017-05-24 23:49:121412 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
robpercival214763f2016-07-01 23:27:011413 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]c9e49a02013-02-26 05:56:471414
1415 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041416 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]c9e49a02013-02-26 05:56:471417
1418 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071419 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451420 size_t spdy_response_headers_frame_length;
1421 ProcessPacket(ConstructResponseHeadersPacket(
1422 2, !kFin, &spdy_response_headers_frame_length));
[email protected]c9e49a02013-02-26 05:56:471423
rchfb47f712017-05-21 03:24:001424 // The headers have already arrived.
1425 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]cadac622013-06-11 16:46:361426 ASSERT_TRUE(response_.headers.get());
[email protected]c9e49a02013-02-26 05:56:471427 EXPECT_EQ(200, response_.headers->response_code());
1428 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1429
1430 // Send the response body.
1431 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431432 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
alyssar2adf3ac2016-05-03 17:12:581433 ProcessPacket(ConstructServerDataPacket(
Renjief49758b2019-01-11 23:32:411434 3, false, kFin, response_data_.length(), header2 + kResponseBody));
[email protected]c9e49a02013-02-26 05:56:471435
1436 // Since the body has already arrived, this should return immediately.
1437 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1438 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1439 callback_.callback()));
1440
1441 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1442 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101443
1444 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451445 // headers and payload.
1446 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411447 strlen(kUploadData) * 2 + header.length() * 2),
sclittle1edeeb22015-09-02 20:46:101448 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451449 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411450 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101451 stream_->GetTotalReceivedBytes());
[email protected]c9e49a02013-02-26 05:56:471452}
1453
[email protected]16ba7742014-08-22 00:57:251454TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithFinalEmptyDataPacket) {
1455 SetRequest("POST", "/", DEFAULT_PRIORITY);
1456 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:451457 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:021458 AddWrite(ConstructInitialSettingsPacket());
Victor Vasiliev076657c2019-03-12 02:46:431459 std::string header = ConstructDataHeader(chunk_size);
Renjief49758b2019-01-11 23:32:411460
Nick Harper23290b82019-05-02 00:02:561461 if (version_.transport_version != quic::QUIC_VERSION_99) {
Renjief49758b2019-01-11 23:32:411462 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1463 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
Ryan Hamilton0d65a8c2019-06-07 00:46:021464 !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
1465 {kUploadData}));
Renjief49758b2019-01-11 23:32:411466 } else {
1467 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1468 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
Ryan Hamilton0d65a8c2019-06-07 00:46:021469 !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
1470 {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411471 }
1472 AddWrite(ConstructClientDataPacket(3, kIncludeVersion, kFin,
1473 chunk_size + header.length(), ""));
Renjie90e808e2019-01-24 07:24:041474 AddWrite(ConstructClientAckPacket(4, 3, 1, 2));
[email protected]16ba7742014-08-22 00:57:251475 Initialize();
1476
Jeremy Roman0579ed62017-08-29 15:56:191477 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121478 auto* chunked_upload_stream =
1479 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1480 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
[email protected]16ba7742014-08-22 00:57:251481
1482 request_.method = "POST";
rchcd379012017-04-12 21:53:321483 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121484 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071485 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201486 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]16ba7742014-08-22 00:57:251487
xunjieli5fafe142016-03-23 23:32:541488 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271489 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541490 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021491 ASSERT_EQ(ERR_IO_PENDING,
1492 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251493
rch97827ee2017-05-24 23:49:121494 chunked_upload_stream->AppendData(nullptr, 0, true);
robpercival214763f2016-07-01 23:27:011495 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]16ba7742014-08-22 00:57:251496
Renjie90e808e2019-01-24 07:24:041497 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]16ba7742014-08-22 00:57:251498
1499 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071500 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451501 size_t spdy_response_headers_frame_length;
1502 ProcessPacket(ConstructResponseHeadersPacket(
1503 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251504
rchfb47f712017-05-21 03:24:001505 // The headers have already arrived.
1506 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]16ba7742014-08-22 00:57:251507 ASSERT_TRUE(response_.headers.get());
1508 EXPECT_EQ(200, response_.headers->response_code());
1509 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1510
1511 // Send the response body.
1512 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431513 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
alyssar2adf3ac2016-05-03 17:12:581514 ProcessPacket(ConstructServerDataPacket(
Renjief49758b2019-01-11 23:32:411515 3, false, kFin, response_data_.length(), header2 + kResponseBody));
[email protected]16ba7742014-08-22 00:57:251516
rchb27683c2015-07-29 23:53:501517 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251518 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1519 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1520 callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251521 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1522 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101523
1524 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451525 // headers and payload.
1526 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411527 strlen(kUploadData) + header.length()),
sclittle1edeeb22015-09-02 20:46:101528 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451529 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411530 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101531 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251532}
1533
1534TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithOneEmptyDataPacket) {
1535 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451536 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:021537 AddWrite(ConstructInitialSettingsPacket());
fayang3bcb8b502016-12-07 21:44:371538 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:331539 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, !kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:021540 DEFAULT_PRIORITY, &spdy_request_headers_frame_length));
fayang3bcb8b502016-12-07 21:44:371541 AddWrite(ConstructClientDataPacket(3, kIncludeVersion, kFin, 0, ""));
Renjie90e808e2019-01-24 07:24:041542 AddWrite(ConstructClientAckPacket(4, 3, 1, 2));
[email protected]16ba7742014-08-22 00:57:251543 Initialize();
1544
Jeremy Roman0579ed62017-08-29 15:56:191545 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121546 auto* chunked_upload_stream =
1547 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
[email protected]16ba7742014-08-22 00:57:251548
1549 request_.method = "POST";
rchcd379012017-04-12 21:53:321550 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121551 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071552 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201553 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]16ba7742014-08-22 00:57:251554
xunjieli5fafe142016-03-23 23:32:541555 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271556 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541557 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021558 ASSERT_EQ(ERR_IO_PENDING,
1559 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251560
rch97827ee2017-05-24 23:49:121561 chunked_upload_stream->AppendData(nullptr, 0, true);
robpercival214763f2016-07-01 23:27:011562 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]16ba7742014-08-22 00:57:251563
Renjie90e808e2019-01-24 07:24:041564 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]16ba7742014-08-22 00:57:251565
1566 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071567 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451568 size_t spdy_response_headers_frame_length;
1569 ProcessPacket(ConstructResponseHeadersPacket(
1570 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251571
rchfb47f712017-05-21 03:24:001572 // The headers have already arrived.
1573 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]16ba7742014-08-22 00:57:251574 ASSERT_TRUE(response_.headers.get());
1575 EXPECT_EQ(200, response_.headers->response_code());
1576 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1577
1578 // Send the response body.
1579 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431580 std::string header = ConstructDataHeader(strlen(kResponseBody));
alyssar2adf3ac2016-05-03 17:12:581581 ProcessPacket(ConstructServerDataPacket(
Renjief49758b2019-01-11 23:32:411582 3, false, kFin, response_data_.length(), header + kResponseBody));
[email protected]16ba7742014-08-22 00:57:251583
rchb27683c2015-07-29 23:53:501584 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251585 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1586 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1587 callback_.callback()));
1588
1589 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1590 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101591
1592 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451593 // headers and payload.
1594 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1595 stream_->GetTotalSentBytes());
1596 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411597 strlen(kResponseBody) + header.length()),
sclittle1edeeb22015-09-02 20:46:101598 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251599}
1600
[email protected]1e960032013-12-20 19:00:201601TEST_P(QuicHttpStreamTest, DestroyedEarly) {
1602 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451603 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:021604 AddWrite(ConstructInitialSettingsPacket());
fayang3bcb8b502016-12-07 21:44:371605 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:331606 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:021607 DEFAULT_PRIORITY, &spdy_request_headers_frame_length));
fayang3bcb8b502016-12-07 21:44:371608 AddWrite(ConstructAckAndRstStreamPacket(3));
[email protected]63534512012-12-23 18:49:001609 Initialize();
1610
1611 request_.method = "GET";
rchcd379012017-04-12 21:53:321612 request_.url = GURL("https://www.example.org/");
[email protected]63534512012-12-23 18:49:001613
xunjieli5fafe142016-03-23 23:32:541614 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271615 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541616 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021617 EXPECT_EQ(OK,
1618 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]63534512012-12-23 18:49:001619
1620 // Ack the request.
Renjie90e808e2019-01-24 07:24:041621 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
rchfb47f712017-05-21 03:24:001622 EXPECT_THAT(stream_->ReadResponseHeaders(
1623 base::Bind(&QuicHttpStreamTest::CloseStream,
1624 base::Unretained(this), stream_.get())),
robpercival214763f2016-07-01 23:27:011625 IsError(ERR_IO_PENDING));
[email protected]63534512012-12-23 18:49:001626
1627 // Send the response with a body.
[email protected]1e960032013-12-20 19:00:201628 SetResponse("404 OK", "hello world!");
[email protected]63534512012-12-23 18:49:001629 // In the course of processing this packet, the QuicHttpStream close itself.
rchfb47f712017-05-21 03:24:001630 size_t response_size = 0;
rch1bcfddf22017-06-03 00:26:291631 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin, &response_size));
[email protected]63534512012-12-23 18:49:001632
fdoray92e35a72016-06-10 15:54:551633 base::RunLoop().RunUntilIdle();
rchb27683c2015-07-29 23:53:501634
[email protected]63534512012-12-23 18:49:001635 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101636
1637 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451638 // headers and payload.
1639 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1640 stream_->GetTotalSentBytes());
rchfb47f712017-05-21 03:24:001641 // The stream was closed after receiving the headers.
1642 EXPECT_EQ(static_cast<int64_t>(response_size),
1643 stream_->GetTotalReceivedBytes());
[email protected]63534512012-12-23 18:49:001644}
1645
[email protected]1e960032013-12-20 19:00:201646TEST_P(QuicHttpStreamTest, Priority) {
1647 SetRequest("GET", "/", MEDIUM);
sclittlec4dc1a32015-09-24 00:15:451648 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:021649 AddWrite(ConstructInitialSettingsPacket());
fayang3bcb8b502016-12-07 21:44:371650 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:331651 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:021652 MEDIUM, &spdy_request_headers_frame_length));
[email protected]24e5bc52013-09-18 15:36:581653 Initialize();
1654
1655 request_.method = "GET";
rchcd379012017-04-12 21:53:321656 request_.url = GURL("https://www.example.org/");
[email protected]24e5bc52013-09-18 15:36:581657
Steven Valdezb4ff0412018-01-18 22:39:271658 EXPECT_EQ(OK,
1659 stream_->InitializeStream(&request_, true, MEDIUM, net_log_.bound(),
1660 callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581661
rjshaded5ced072015-12-18 19:26:021662 EXPECT_EQ(OK,
1663 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581664
[email protected]24e5bc52013-09-18 15:36:581665 // Ack the request.
Renjie90e808e2019-01-24 07:24:041666 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011667 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1668 IsError(ERR_IO_PENDING));
[email protected]24e5bc52013-09-18 15:36:581669
1670 // Send the response with a body.
[email protected]1e960032013-12-20 19:00:201671 SetResponse("404 OK", "hello world!");
rchfb47f712017-05-21 03:24:001672 size_t response_size = 0;
1673 ProcessPacket(ConstructResponseHeadersPacket(2, kFin, &response_size));
[email protected]24e5bc52013-09-18 15:36:581674
rchfb47f712017-05-21 03:24:001675 EXPECT_EQ(OK, callback_.WaitForResult());
rchb27683c2015-07-29 23:53:501676
[email protected]24e5bc52013-09-18 15:36:581677 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101678
1679 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451680 // headers and payload.
1681 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1682 stream_->GetTotalSentBytes());
rchfb47f712017-05-21 03:24:001683 EXPECT_EQ(static_cast<int64_t>(response_size),
1684 stream_->GetTotalReceivedBytes());
[email protected]24e5bc52013-09-18 15:36:581685}
1686
xunjieli8dff50b2016-07-22 14:19:061687TEST_P(QuicHttpStreamTest, SessionClosedDuringDoLoop) {
1688 SetRequest("POST", "/", DEFAULT_PRIORITY);
1689 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:021690 AddWrite(ConstructInitialSettingsPacket());
Victor Vasiliev076657c2019-03-12 02:46:431691 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harper23290b82019-05-02 00:02:561692 if (version_.transport_version != quic::QUIC_VERSION_99) {
Renjief49758b2019-01-11 23:32:411693 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1694 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
Ryan Hamilton0d65a8c2019-06-07 00:46:021695 !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
1696 {kUploadData}));
Renjief49758b2019-01-11 23:32:411697 } else {
1698 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1699 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
Ryan Hamilton0d65a8c2019-06-07 00:46:021700 !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
1701 {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411702 }
1703
xunjieli8dff50b2016-07-22 14:19:061704 // Second data write will result in a synchronous failure which will close
1705 // the session.
1706 AddWrite(SYNCHRONOUS, ERR_FAILED);
1707 Initialize();
1708
Jeremy Roman0579ed62017-08-29 15:56:191709 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121710 auto* chunked_upload_stream =
1711 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
xunjieli8dff50b2016-07-22 14:19:061712
1713 request_.method = "POST";
rchcd379012017-04-12 21:53:321714 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121715 request_.upload_data_stream = upload_data_stream_.get();
xunjieli8dff50b2016-07-22 14:19:061716 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201717 TestCompletionCallback().callback(), NetLogWithSource()));
xunjieli8dff50b2016-07-22 14:19:061718
1719 size_t chunk_size = strlen(kUploadData);
rch97827ee2017-05-24 23:49:121720 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
xunjieli8dff50b2016-07-22 14:19:061721 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271722 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli8dff50b2016-07-22 14:19:061723 net_log_.bound(), callback_.callback()));
1724 QuicHttpStream* stream = stream_.get();
1725 DeleteStreamCallback delete_stream_callback(std::move(stream_));
1726 // SendRequest() completes asynchronously after the final chunk is added.
Yixin Wange7ecc472018-03-06 19:00:251727 // Error does not surface yet since packet write is triggered by a packet
1728 // flusher that tries to bundle request body writes.
xunjieli8dff50b2016-07-22 14:19:061729 ASSERT_EQ(ERR_IO_PENDING,
1730 stream->SendRequest(headers_, &response_, callback_.callback()));
rch97827ee2017-05-24 23:49:121731 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
xunjieli8dff50b2016-07-22 14:19:061732 int rv = callback_.WaitForResult();
Yixin Wange7ecc472018-03-06 19:00:251733 EXPECT_EQ(OK, rv);
1734 // Error will be surfaced once an attempt to read the response occurs.
1735 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1736 stream->ReadResponseHeaders(callback_.callback()));
xunjieli8dff50b2016-07-22 14:19:061737}
1738
rtenneti15656ae2016-01-23 03:05:031739TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersComplete) {
1740 SetRequest("POST", "/", DEFAULT_PRIORITY);
Ryan Hamilton0d65a8c2019-06-07 00:46:021741 AddWrite(ConstructInitialSettingsPacket());
rtenneti15656ae2016-01-23 03:05:031742 AddWrite(SYNCHRONOUS, ERR_FAILED);
1743 Initialize();
1744
Jeremy Roman0579ed62017-08-29 15:56:191745 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
Yixin Wange7ecc472018-03-06 19:00:251746 auto* chunked_upload_stream =
1747 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
rtenneti15656ae2016-01-23 03:05:031748
1749 request_.method = "POST";
rchcd379012017-04-12 21:53:321750 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121751 request_.upload_data_stream = upload_data_stream_.get();
rtenneti15656ae2016-01-23 03:05:031752 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201753 TestCompletionCallback().callback(), NetLogWithSource()));
rtenneti15656ae2016-01-23 03:05:031754
xunjieli5fafe142016-03-23 23:32:541755 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271756 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541757 net_log_.bound(), callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:251758 ASSERT_EQ(ERR_IO_PENDING,
rtenneti15656ae2016-01-23 03:05:031759 stream_->SendRequest(headers_, &response_, callback_.callback()));
mmenkeffff3642017-06-15 17:37:241760
Yixin Wange7ecc472018-03-06 19:00:251761 // Error will be surfaced once |upload_data_stream| triggers the next write.
1762 size_t chunk_size = strlen(kUploadData);
1763 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1764 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR, callback_.WaitForResult());
1765
1766 EXPECT_LE(0, stream_->GetTotalSentBytes());
1767 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1768}
1769
1770TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersCompleteReadResponse) {
1771 SetRequest("POST", "/", DEFAULT_PRIORITY);
Ryan Hamilton0d65a8c2019-06-07 00:46:021772 AddWrite(ConstructInitialSettingsPacket());
Yixin Wange7ecc472018-03-06 19:00:251773 AddWrite(SYNCHRONOUS, ERR_FAILED);
1774 Initialize();
1775
1776 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
1777 auto* chunked_upload_stream =
1778 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1779
1780 request_.method = "POST";
1781 request_.url = GURL("https://www.example.org/");
1782 request_.upload_data_stream = upload_data_stream_.get();
1783
1784 size_t chunk_size = strlen(kUploadData);
1785 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1786
1787 ASSERT_EQ(OK, request_.upload_data_stream->Init(
1788 TestCompletionCallback().callback(), NetLogWithSource()));
1789
1790 ASSERT_EQ(OK,
1791 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1792 net_log_.bound(), callback_.callback()));
1793 ASSERT_EQ(OK,
1794 stream_->SendRequest(headers_, &response_, callback_.callback()));
1795
1796 // Error will be surfaced once an attempt to read the response occurs.
1797 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1798 stream_->ReadResponseHeaders(callback_.callback()));
1799
mmenkeffff3642017-06-15 17:37:241800 EXPECT_LE(0, stream_->GetTotalSentBytes());
1801 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rtenneti15656ae2016-01-23 03:05:031802}
1803
1804TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBodyComplete) {
1805 SetRequest("POST", "/", DEFAULT_PRIORITY);
1806 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:021807 AddWrite(ConstructInitialSettingsPacket());
fayang3bcb8b502016-12-07 21:44:371808 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:331809 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, !kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:021810 DEFAULT_PRIORITY, &spdy_request_headers_frame_length));
rtenneti15656ae2016-01-23 03:05:031811 AddWrite(SYNCHRONOUS, ERR_FAILED);
1812 Initialize();
1813
Jeremy Roman0579ed62017-08-29 15:56:191814 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121815 auto* chunked_upload_stream =
1816 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
rtenneti15656ae2016-01-23 03:05:031817
1818 request_.method = "POST";
rchcd379012017-04-12 21:53:321819 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121820 request_.upload_data_stream = upload_data_stream_.get();
rtenneti15656ae2016-01-23 03:05:031821 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201822 TestCompletionCallback().callback(), NetLogWithSource()));
rtenneti15656ae2016-01-23 03:05:031823
xunjieli5fafe142016-03-23 23:32:541824 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271825 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541826 net_log_.bound(), callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:251827 ASSERT_EQ(ERR_IO_PENDING,
rtenneti15656ae2016-01-23 03:05:031828 stream_->SendRequest(headers_, &response_, callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:251829
1830 size_t chunk_size = strlen(kUploadData);
1831 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1832 // Error does not surface yet since packet write is triggered by a packet
1833 // flusher that tries to bundle request body writes.
1834 ASSERT_EQ(OK, callback_.WaitForResult());
1835 // Error will be surfaced once an attempt to read the response occurs.
1836 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1837 stream_->ReadResponseHeaders(callback_.callback()));
1838
1839 EXPECT_LE(0, stream_->GetTotalSentBytes());
1840 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1841}
1842
1843TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBundledBodyComplete) {
1844 SetRequest("POST", "/", DEFAULT_PRIORITY);
1845 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:021846 AddWrite(ConstructInitialSettingsPacket());
Victor Vasiliev076657c2019-03-12 02:46:431847 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harper23290b82019-05-02 00:02:561848 if (version_.transport_version != quic::QUIC_VERSION_99) {
Renjief49758b2019-01-11 23:32:411849 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1850 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
Ryan Hamilton0d65a8c2019-06-07 00:46:021851 !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
1852 {kUploadData}));
Renjief49758b2019-01-11 23:32:411853 } else {
1854 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1855 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
Ryan Hamilton0d65a8c2019-06-07 00:46:021856 !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
1857 {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411858 }
1859
Yixin Wange7ecc472018-03-06 19:00:251860 AddWrite(SYNCHRONOUS, ERR_FAILED);
1861 Initialize();
1862
1863 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
1864 auto* chunked_upload_stream =
1865 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1866
1867 request_.method = "POST";
1868 request_.url = GURL("https://www.example.org/");
1869 request_.upload_data_stream = upload_data_stream_.get();
1870
1871 size_t chunk_size = strlen(kUploadData);
1872 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
1873
1874 ASSERT_EQ(OK, request_.upload_data_stream->Init(
1875 TestCompletionCallback().callback(), NetLogWithSource()));
1876
1877 ASSERT_EQ(OK,
1878 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1879 net_log_.bound(), callback_.callback()));
1880 ASSERT_EQ(ERR_IO_PENDING,
1881 stream_->SendRequest(headers_, &response_, callback_.callback()));
1882
1883 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1884
1885 // Error does not surface yet since packet write is triggered by a packet
1886 // flusher that tries to bundle request body writes.
1887 ASSERT_EQ(OK, callback_.WaitForResult());
1888 // Error will be surfaced once an attempt to read the response occurs.
1889 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1890 stream_->ReadResponseHeaders(callback_.callback()));
1891
1892 EXPECT_LE(0, stream_->GetTotalSentBytes());
1893 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rtenneti15656ae2016-01-23 03:05:031894}
1895
ckrasic3865ee0f2016-02-29 22:04:561896TEST_P(QuicHttpStreamTest, ServerPushGetRequest) {
1897 SetRequest("GET", "/", DEFAULT_PRIORITY);
1898 Initialize();
1899
1900 // Initialize the first stream, for receiving the promise on.
1901 request_.method = "GET";
rchcd379012017-04-12 21:53:321902 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:561903
xunjieli5fafe142016-03-23 23:32:541904 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271905 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541906 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561907
1908 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
1909 // packet, but does it matter?
1910 ReceivePromise(promise_id_);
1911 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
1912
1913 request_.url = GURL(promise_url_);
1914
1915 // Make the second stream that will exercise the first step of the
1916 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:271917 EXPECT_EQ(OK, promised_stream_->InitializeStream(
1918 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
1919 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561920
1921 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:251922 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:561923 size_t spdy_response_headers_frame_length;
1924 ProcessPacket(InnerConstructResponseHeadersPacket(
1925 1, promise_id_, false, &spdy_response_headers_frame_length));
1926
1927 // Receive the promised response body.
1928 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431929 std::string header = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:411930 ProcessPacket(InnerConstructDataPacket(
1931 2, promise_id_, false, kFin, 0, header + kResponseBody, &server_maker_));
ckrasic3865ee0f2016-02-29 22:04:561932
1933 // Now sending a matching request will have successful rendezvous
1934 // with the promised stream.
1935 EXPECT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
1936 callback_.callback()));
1937
1938 EXPECT_EQ(
1939 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
1940 ->id(),
1941 promise_id_);
1942
1943 // The headers will be immediately available.
robpercival214763f2016-07-01 23:27:011944 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
1945 IsOk());
ckrasic3865ee0f2016-02-29 22:04:561946
1947 // As will be the body.
1948 EXPECT_EQ(
1949 static_cast<int>(strlen(kResponseBody)),
1950 promised_stream_->ReadResponseBody(
1951 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
1952 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
1953 EXPECT_TRUE(AtEof());
1954
1955 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1956 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1957 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
1958 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411959 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:561960 promised_stream_->GetTotalReceivedBytes());
1961}
1962
1963TEST_P(QuicHttpStreamTest, ServerPushGetRequestSlowResponse) {
1964 SetRequest("GET", "/", DEFAULT_PRIORITY);
1965 Initialize();
1966
1967 // Initialize the first stream, for receiving the promise on.
1968 request_.method = "GET";
rchcd379012017-04-12 21:53:321969 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:561970
xunjieli5fafe142016-03-23 23:32:541971 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271972 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541973 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561974
1975 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
1976 // packet, but does it matter?
1977 ReceivePromise(promise_id_);
1978 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
1979
1980 request_.url = GURL(promise_url_);
1981
1982 // Make the second stream that will exercise the first step of the
1983 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:271984 EXPECT_EQ(OK, promised_stream_->InitializeStream(
1985 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
1986 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561987
1988 // Now sending a matching request will rendezvous with the promised
1989 // stream, but pending secondary validation.
1990 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
1991 headers_, &response_, callback_.callback()));
1992
1993 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:251994 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:561995 size_t spdy_response_headers_frame_length;
1996 ProcessPacket(InnerConstructResponseHeadersPacket(
1997 1, promise_id_, false, &spdy_response_headers_frame_length));
1998
1999 // Receive the promised response body.
2000 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432001 std::string header = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:412002 ProcessPacket(InnerConstructDataPacket(
2003 2, promise_id_, false, kFin, 0, header + kResponseBody, &server_maker_));
ckrasic3865ee0f2016-02-29 22:04:562004
fdoray92e35a72016-06-10 15:54:552005 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562006
2007 // Rendezvous should have succeeded now, so the promised stream
2008 // should point at our push stream, and we should be able read
2009 // headers and data from it.
robpercival214763f2016-07-01 23:27:012010 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562011
2012 EXPECT_EQ(
2013 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2014 ->id(),
2015 promise_id_);
2016
robpercival214763f2016-07-01 23:27:012017 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2018 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562019
2020 EXPECT_EQ(
2021 static_cast<int>(strlen(kResponseBody)),
2022 promised_stream_->ReadResponseBody(
2023 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2024
2025 // Callback should return
2026 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2027 EXPECT_TRUE(AtEof());
2028
2029 EXPECT_EQ(0, stream_->GetTotalSentBytes());
2030 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2031 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2032 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412033 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562034 promised_stream_->GetTotalReceivedBytes());
2035}
2036
ckrasic2c63f9b2016-08-16 23:54:072037// Verify fix for crbug.com/637349
2038TEST_P(QuicHttpStreamTest, ServerPushCancelHttpStreamBeforeResponse) {
2039 SetRequest("GET", "/", DEFAULT_PRIORITY);
2040 Initialize();
2041
2042 // Initialize the first stream, for receiving the promise on.
2043 request_.method = "GET";
rchcd379012017-04-12 21:53:322044 request_.url = GURL("https://www.example.org/");
ckrasic2c63f9b2016-08-16 23:54:072045
2046 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272047 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
ckrasic2c63f9b2016-08-16 23:54:072048 net_log_.bound(), callback_.callback()));
2049
2050 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2051 // packet, but does it matter?
2052 ReceivePromise(promise_id_);
2053 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2054
2055 request_.url = GURL(promise_url_);
2056
2057 // Make the second stream that will exercise the first step of the
2058 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272059 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2060 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2061 callback_.callback()));
ckrasic2c63f9b2016-08-16 23:54:072062
2063 // Now sending a matching request will rendezvous with the promised
2064 // stream, but pending secondary validation.
2065 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2066 headers_, &response_, callback_.callback()));
2067
2068 base::RunLoop().RunUntilIdle();
2069
2070 // Cause of FinalValidation() crash as per bug.
2071 promised_stream_.reset();
2072
2073 // Receive the promised response headers.
2074 response_headers_ = promised_response_.Clone();
2075 size_t spdy_response_headers_frame_length;
2076 ProcessPacket(InnerConstructResponseHeadersPacket(
2077 1, promise_id_, false, &spdy_response_headers_frame_length));
2078}
2079
ckrasic3865ee0f2016-02-29 22:04:562080TEST_P(QuicHttpStreamTest, ServerPushCrossOriginOK) {
2081 SetRequest("GET", "/", DEFAULT_PRIORITY);
2082 Initialize();
2083
2084 // Initialize the first stream, for receiving the promise on.
2085 request_.method = "GET";
rchcd379012017-04-12 21:53:322086 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562087
xunjieli5fafe142016-03-23 23:32:542088 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272089 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542090 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562091
2092 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2093 // packet, but does it matter?
2094
2095 push_promise_[":authority"] = "mail.example.org";
Ryan Hamilton8d9ee76e2018-05-29 23:52:522096 promise_url_ = quic::SpdyUtils::GetPromisedUrlFromHeaders(push_promise_);
ckrasic3865ee0f2016-02-29 22:04:562097
2098 ReceivePromise(promise_id_);
2099 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2100
2101 request_.url = GURL(promise_url_);
2102
2103 // Make the second stream that will exercise the first step of the
2104 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272105 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2106 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2107 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562108
2109 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252110 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562111 size_t spdy_response_headers_frame_length;
2112 ProcessPacket(InnerConstructResponseHeadersPacket(
2113 1, promise_id_, false, &spdy_response_headers_frame_length));
2114
2115 // Receive the promised response body.
2116 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432117 std::string header = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:412118 ProcessPacket(InnerConstructDataPacket(
2119 2, promise_id_, false, kFin, 0, header + kResponseBody, &server_maker_));
ckrasic3865ee0f2016-02-29 22:04:562120
2121 // Now sending a matching request will have successful rendezvous
2122 // with the promised stream.
2123 EXPECT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
2124 callback_.callback()));
2125
2126 EXPECT_EQ(
2127 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2128 ->id(),
2129 promise_id_);
2130
2131 // The headers will be immediately available.
robpercival214763f2016-07-01 23:27:012132 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2133 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562134
2135 // As will be the body.
2136 EXPECT_EQ(
2137 static_cast<int>(strlen(kResponseBody)),
2138 promised_stream_->ReadResponseBody(
2139 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2140 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2141 EXPECT_TRUE(AtEof());
2142
2143 EXPECT_EQ(0, stream_->GetTotalSentBytes());
2144 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2145 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2146 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412147 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562148 promised_stream_->GetTotalReceivedBytes());
2149}
2150
2151TEST_P(QuicHttpStreamTest, ServerPushCrossOriginFail) {
2152 SetRequest("GET", "/", DEFAULT_PRIORITY);
2153 Initialize();
2154
2155 // Initialize the first stream, for receiving the promise on.
2156 request_.method = "GET";
rchcd379012017-04-12 21:53:322157 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562158
xunjieli5fafe142016-03-23 23:32:542159 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272160 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542161 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562162
2163 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2164 // packet, but does it matter?
2165 push_promise_[":authority"] = "www.notexample.org";
Ryan Hamilton8d9ee76e2018-05-29 23:52:522166 promise_url_ = quic::SpdyUtils::GetPromisedUrlFromHeaders(push_promise_);
ckrasic3865ee0f2016-02-29 22:04:562167
2168 ReceivePromise(promise_id_);
2169 // The promise will have been rejected because the cert doesn't
2170 // match.
2171 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
2172}
2173
2174TEST_P(QuicHttpStreamTest, ServerPushVaryCheckOK) {
2175 SetRequest("GET", "/", DEFAULT_PRIORITY);
2176 Initialize();
2177
2178 // Initialize the first stream, for receiving the promise on.
2179 request_.method = "GET";
rchcd379012017-04-12 21:53:322180 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562181
xunjieli5fafe142016-03-23 23:32:542182 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272183 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542184 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562185
2186 push_promise_["accept-encoding"] = "gzip";
ckrasic3865ee0f2016-02-29 22:04:562187
2188 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2189 // packet, but does it matter?
2190 ReceivePromise(promise_id_);
2191 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2192
2193 request_.url = GURL(promise_url_);
2194
2195 // Make the second stream that will exercise the first step of the
2196 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272197 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2198 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2199 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562200
2201 headers_.SetHeader("accept-encoding", "gzip");
2202
2203 // Now sending a matching request will rendezvous with the promised
2204 // stream, but pending secondary validation.
2205 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2206 headers_, &response_, callback_.callback()));
2207
2208 // Receive the promised response headers.
2209 promised_response_["vary"] = "accept-encoding";
bnc94893a72016-06-30 13:45:252210 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562211 size_t spdy_response_headers_frame_length;
2212 ProcessPacket(InnerConstructResponseHeadersPacket(
2213 1, promise_id_, false, &spdy_response_headers_frame_length));
2214
2215 // Receive the promised response body.
2216 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432217 std::string header = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:412218 ProcessPacket(InnerConstructDataPacket(
2219 2, promise_id_, false, kFin, 0, header + kResponseBody, &server_maker_));
ckrasic3865ee0f2016-02-29 22:04:562220
fdoray92e35a72016-06-10 15:54:552221 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562222
2223 // Rendezvous should have succeeded now, so the promised stream
2224 // should point at our push stream, and we should be able read
2225 // headers and data from it.
robpercival214763f2016-07-01 23:27:012226 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562227
2228 EXPECT_EQ(
2229 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2230 ->id(),
2231 promise_id_);
2232
robpercival214763f2016-07-01 23:27:012233 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2234 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562235
2236 EXPECT_EQ(
2237 static_cast<int>(strlen(kResponseBody)),
2238 promised_stream_->ReadResponseBody(
2239 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2240
2241 // Callback should return
2242 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2243 EXPECT_TRUE(AtEof());
2244
2245 EXPECT_EQ(0, stream_->GetTotalSentBytes());
2246 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2247 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2248 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412249 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562250 promised_stream_->GetTotalReceivedBytes());
2251}
2252
2253TEST_P(QuicHttpStreamTest, ServerPushVaryCheckFail) {
2254 SetRequest("GET", "/", DEFAULT_PRIORITY);
2255 request_headers_[":scheme"] = "https";
2256 request_headers_[":path"] = "/bar";
2257 request_headers_["accept-encoding"] = "sdch";
2258
2259 size_t spdy_request_header_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:022260 AddWrite(ConstructInitialSettingsPacket());
Yixin Wangb470bc882018-02-15 18:43:572261
Fan Yangac867502019-01-28 21:10:232262 uint64_t client_packet_number = 2;
Yixin Wangb470bc882018-02-15 18:43:572263 if (client_headers_include_h2_stream_dependency_ &&
Nick Harper23290b82019-05-02 00:02:562264 version_.transport_version >= quic::QUIC_VERSION_43) {
Ryan Hamilton0d65a8c2019-06-07 00:46:022265 AddWrite(ConstructClientPriorityPacket(client_packet_number++,
2266 kIncludeVersion, promise_id_, 0,
2267 DEFAULT_PRIORITY));
Yixin Wangb470bc882018-02-15 18:43:572268 }
Michael Warresabba8b7d2018-07-20 22:50:272269 AddWrite(ConstructClientRstStreamVaryMismatchAndRequestHeadersPacket(
Victor Vasiliev4a6798e2019-03-06 02:26:092270 client_packet_number++,
Nick Harper23290b82019-05-02 00:02:562271 stream_id_ + quic::QuicUtils::StreamIdDelta(version_.transport_version),
2272 !kIncludeVersion, kFin, DEFAULT_PRIORITY, promise_id_,
Ryan Hamilton0d65a8c2019-06-07 00:46:022273 &spdy_request_header_frame_length));
Renjie90e808e2019-01-24 07:24:042274 AddWrite(ConstructClientAckPacket(client_packet_number++, 3, 1, 2));
Yixin Wangb470bc882018-02-15 18:43:572275 AddWrite(ConstructClientRstStreamCancelledPacket(client_packet_number++));
2276
ckrasic3865ee0f2016-02-29 22:04:562277 Initialize();
2278
2279 // Initialize the first stream, for receiving the promise on.
2280 request_.method = "GET";
rchcd379012017-04-12 21:53:322281 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562282
xunjieli5fafe142016-03-23 23:32:542283 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272284 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542285 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562286
2287 push_promise_["accept-encoding"] = "gzip";
ckrasic3865ee0f2016-02-29 22:04:562288
2289 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2290 // packet, but does it matter?
2291 ReceivePromise(promise_id_);
2292 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2293
2294 request_.url = GURL(promise_url_);
2295
2296 // Make the second stream that will exercise the first step of the
2297 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272298 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2299 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2300 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562301
2302 headers_.SetHeader("accept-encoding", "sdch");
2303
2304 // Now sending a matching request will rendezvous with the promised
2305 // stream, but pending secondary validation.
2306 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2307 headers_, &response_, callback_.callback()));
2308
2309 // Receive the promised response headers.
2310 promised_response_["vary"] = "accept-encoding";
bnc94893a72016-06-30 13:45:252311 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562312 size_t spdy_response_headers_frame_length;
2313 ProcessPacket(InnerConstructResponseHeadersPacket(
2314 1, promise_id_, false, &spdy_response_headers_frame_length));
2315
fdoray92e35a72016-06-10 15:54:552316 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562317
2318 // Rendezvous should have failed due to vary mismatch, so the
2319 // promised stream should have been aborted, and instead we have a
2320 // new, regular client initiated stream.
robpercival214763f2016-07-01 23:27:012321 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562322
2323 // Not a server-initiated stream.
2324 EXPECT_NE(
2325 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2326 ->id(),
2327 promise_id_);
2328
2329 // Instead, a new client-initiated stream.
2330 EXPECT_EQ(
2331 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2332 ->id(),
Nick Harper23290b82019-05-02 00:02:562333 stream_id_ + quic::QuicUtils::StreamIdDelta(version_.transport_version));
ckrasic3865ee0f2016-02-29 22:04:562334
2335 // After rendezvous failure, the push stream has been cancelled.
2336 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
2337
2338 // The rest of the test verifies that the retried as
2339 // client-initiated version of |promised_stream_| works as intended.
2340
2341 // Ack the request.
Renjie90e808e2019-01-24 07:24:042342 ProcessPacket(ConstructServerAckPacket(2, 1, 1, 1));
ckrasic3865ee0f2016-02-29 22:04:562343
bnc614a92d32016-04-04 13:56:072344 SetResponse("404 Not Found", string());
ckrasic3865ee0f2016-02-29 22:04:562345 size_t spdy_response_header_frame_length;
2346 ProcessPacket(InnerConstructResponseHeadersPacket(
Nick Harper23290b82019-05-02 00:02:562347 3,
2348 stream_id_ + quic::QuicUtils::StreamIdDelta(version_.transport_version),
2349 kFin, &spdy_response_header_frame_length));
ckrasic3865ee0f2016-02-29 22:04:562350
fdoray92e35a72016-06-10 15:54:552351 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562352
robpercival214763f2016-07-01 23:27:012353 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2354 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562355 ASSERT_TRUE(response_.headers.get());
2356 EXPECT_EQ(404, response_.headers->response_code());
2357 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
2358 EXPECT_FALSE(response_.response_time.is_null());
2359 EXPECT_FALSE(response_.request_time.is_null());
2360
2361 // There is no body, so this should return immediately.
2362 EXPECT_EQ(
2363 0, promised_stream_->ReadResponseBody(
2364 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2365 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2366
2367 stream_->Close(true);
2368
2369 EXPECT_TRUE(AtEof());
2370
2371 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
2372 // headers and payload.
2373 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
2374 promised_stream_->GetTotalSentBytes());
2375 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length),
2376 promised_stream_->GetTotalReceivedBytes());
2377}
2378
maksim.sisov84e20c92016-06-23 08:49:342379TEST_P(QuicHttpStreamTest, DataReadErrorSynchronous) {
2380 SetRequest("POST", "/", DEFAULT_PRIORITY);
2381 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:022382 AddWrite(ConstructInitialSettingsPacket());
Yixin Wange7ecc472018-03-06 19:00:252383 AddWrite(ConstructRequestAndRstPacket(
Fan Yang32c5a112018-12-10 20:06:332384 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, !kFin,
Yixin Wange7ecc472018-03-06 19:00:252385 DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
Ryan Hamilton0d65a8c2019-06-07 00:46:022386 quic::QUIC_ERROR_PROCESSING_STREAM, 0));
maksim.sisov84e20c92016-06-23 08:49:342387
2388 Initialize();
2389
Jeremy Roman0579ed62017-08-29 15:56:192390 upload_data_stream_ = std::make_unique<ReadErrorUploadDataStream>(
maksim.sisov84e20c92016-06-23 08:49:342391 ReadErrorUploadDataStream::FailureMode::SYNC);
2392 request_.method = "POST";
rchcd379012017-04-12 21:53:322393 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122394 request_.upload_data_stream = upload_data_stream_.get();
maksim.sisov84e20c92016-06-23 08:49:342395 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202396 TestCompletionCallback().callback(), NetLogWithSource()));
maksim.sisov84e20c92016-06-23 08:49:342397
2398 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272399 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
maksim.sisov84e20c92016-06-23 08:49:342400 net_log_.bound(), callback_.callback()));
2401
2402 int result = stream_->SendRequest(headers_, &response_, callback_.callback());
robpercival214763f2016-07-01 23:27:012403 EXPECT_THAT(result, IsError(ERR_FAILED));
maksim.sisov84e20c92016-06-23 08:49:342404
2405 EXPECT_TRUE(AtEof());
2406
2407 // QuicHttpStream::GetTotalSent/ReceivedBytes includes only headers.
2408 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
2409 stream_->GetTotalSentBytes());
2410 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2411}
2412
2413TEST_P(QuicHttpStreamTest, DataReadErrorAsynchronous) {
2414 SetRequest("POST", "/", DEFAULT_PRIORITY);
2415 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:022416 AddWrite(ConstructInitialSettingsPacket());
fayang3bcb8b502016-12-07 21:44:372417 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:332418 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, !kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:022419 DEFAULT_PRIORITY, &spdy_request_headers_frame_length));
fayang3bcb8b502016-12-07 21:44:372420 AddWrite(ConstructClientRstStreamErrorPacket(3, !kIncludeVersion));
maksim.sisov84e20c92016-06-23 08:49:342421
2422 Initialize();
2423
Jeremy Roman0579ed62017-08-29 15:56:192424 upload_data_stream_ = std::make_unique<ReadErrorUploadDataStream>(
maksim.sisov84e20c92016-06-23 08:49:342425 ReadErrorUploadDataStream::FailureMode::ASYNC);
2426 request_.method = "POST";
rchcd379012017-04-12 21:53:322427 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122428 request_.upload_data_stream = upload_data_stream_.get();
maksim.sisov84e20c92016-06-23 08:49:342429 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202430 TestCompletionCallback().callback(), NetLogWithSource()));
maksim.sisov84e20c92016-06-23 08:49:342431
2432 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272433 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
maksim.sisov84e20c92016-06-23 08:49:342434 net_log_.bound(), callback_.callback()));
2435
2436 int result = stream_->SendRequest(headers_, &response_, callback_.callback());
2437
Renjie90e808e2019-01-24 07:24:042438 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
maksim.sisov84e20c92016-06-23 08:49:342439 SetResponse("200 OK", string());
2440
robpercival214763f2016-07-01 23:27:012441 EXPECT_THAT(result, IsError(ERR_IO_PENDING));
2442 EXPECT_THAT(callback_.GetResult(result), IsError(ERR_FAILED));
maksim.sisov84e20c92016-06-23 08:49:342443
2444 EXPECT_TRUE(AtEof());
2445
2446 // QuicHttpStream::GetTotalSent/ReceivedBytes includes only headers.
2447 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
2448 stream_->GetTotalSentBytes());
2449 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2450}
2451
[email protected]f702d572012-12-04 15:56:202452} // namespace test
[email protected]f702d572012-12-04 15:56:202453} // namespace net