blob: b2341a44365795f95b3396c66970ae51ce3b9977 [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"
Bence Békye0d3747d2020-08-28 23:16:4016#include "base/strings/strcat.h"
xunjieli188bd402016-03-12 00:17:2517#include "base/strings/string_number_conversions.h"
Bence Béky97ec688c2021-03-16 13:48:5018#include "base/test/metrics/histogram_tester.h"
gabf767595f2016-05-11 18:50:3519#include "base/threading/thread_task_runner_handle.h"
Zhongyi Shic16b4102019-02-12 00:37:4020#include "base/time/default_tick_clock.h"
xunjieli84adaab2016-09-20 01:12:2821#include "base/time/time.h"
mmenkecbc2b712014-10-09 20:29:0722#include "net/base/chunked_upload_data_stream.h"
23#include "net/base/elements_upload_data_stream.h"
David Benjamin0288768a2019-07-22 15:00:2624#include "net/base/load_flags.h"
xunjieli84adaab2016-09-20 01:12:2825#include "net/base/load_timing_info.h"
26#include "net/base/load_timing_info_test_util.h"
[email protected]f702d572012-12-04 15:56:2027#include "net/base/net_errors.h"
28#include "net/base/test_completion_callback.h"
[email protected]b2d26cfd2012-12-11 10:36:0629#include "net/base/upload_bytes_element_reader.h"
[email protected]f702d572012-12-04 15:56:2030#include "net/http/http_response_headers.h"
[email protected]5db452202014-08-19 05:22:1531#include "net/http/transport_security_state.h"
mikecirone8b85c432016-09-08 19:11:0032#include "net/log/net_log_event_type.h"
xunjieli5fafe142016-03-23 23:32:5433#include "net/log/test_net_log.h"
34#include "net/log/test_net_log_util.h"
Victor Vasiliev4f6fb892019-05-31 16:58:3135#include "net/quic/address_utils.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0836#include "net/quic/crypto/proof_verifier_chromium.h"
37#include "net/quic/mock_crypto_client_stream_factory.h"
Ryan Hamiltona1d1f4a2019-06-26 14:43:0438#include "net/quic/platform/impl/quic_test_impl.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0839#include "net/quic/quic_chromium_alarm_factory.h"
40#include "net/quic/quic_chromium_connection_helper.h"
41#include "net/quic/quic_chromium_packet_reader.h"
42#include "net/quic/quic_chromium_packet_writer.h"
Matt Menkefca05b62019-09-20 23:15:5643#include "net/quic/quic_crypto_client_config_handle.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0844#include "net/quic/quic_http_utils.h"
45#include "net/quic/quic_server_info.h"
46#include "net/quic/quic_stream_factory.h"
47#include "net/quic/quic_test_packet_maker.h"
Ryan Hamilton0d65a8c2019-06-07 00:46:0248#include "net/quic/quic_test_packet_printer.h"
Matt Menkefca05b62019-09-20 23:15:5649#include "net/quic/test_quic_crypto_client_config_handle.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0850#include "net/quic/test_task_runner.h"
tbansalca83c002016-04-28 20:56:2851#include "net/socket/socket_performance_watcher.h"
[email protected]f702d572012-12-04 15:56:2052#include "net/socket/socket_test_util.h"
Bence Béky94658bf2018-05-11 19:22:5853#include "net/spdy/spdy_http_utils.h"
rch03b7a202016-02-05 00:54:2054#include "net/test/cert_test_util.h"
robpercival214763f2016-07-01 23:27:0155#include "net/test/gtest_util.h"
rsleevia69c79a2016-06-22 03:28:4356#include "net/test/test_data_directory.h"
Gabriel Charettec7108742019-08-23 03:31:4057#include "net/test/test_with_task_environment.h"
Zhongyi Shid1c00fc42019-12-14 06:05:0958#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
Victor Vasiliev6bb59d22019-03-08 21:34:5159#include "net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.h"
60#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
61#include "net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h"
62#include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
David Schinazi3f7465c2019-07-12 01:57:0563#include "net/third_party/quiche/src/quic/core/http/spdy_server_push_utils.h"
Victor Vasiliev6bb59d22019-03-08 21:34:5164#include "net/third_party/quiche/src/quic/core/quic_connection.h"
65#include "net/third_party/quiche/src/quic/core/quic_utils.h"
66#include "net/third_party/quiche/src/quic/core/quic_write_blocked_list.h"
Ryan Hamiltona1d1f4a2019-06-26 14:43:0467#include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h"
68#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
Victor Vasiliev6bb59d22019-03-08 21:34:5169#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
70#include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
71#include "net/third_party/quiche/src/quic/test_tools/mock_random.h"
Bence Béky6e243aa2019-12-13 19:01:0772#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h"
Victor Vasiliev6bb59d22019-03-08 21:34:5173#include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
74#include "net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h"
75#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
Victor Vasiliev27cc7712019-01-24 11:50:1476#include "net/third_party/quiche/src/spdy/core/spdy_frame_builder.h"
77#include "net/third_party/quiche/src/spdy/core/spdy_framer.h"
78#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
Ramin Halavati683bcaa92018-02-14 08:42:3979#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
[email protected]f702d572012-12-04 15:56:2080#include "testing/gmock/include/gmock/gmock.h"
81#include "testing/gtest/include/gtest/gtest.h"
82
bnc614a92d32016-04-04 13:56:0783using std::string;
[email protected]f702d572012-12-04 15:56:2084using testing::_;
[email protected]06ff5152013-08-29 01:03:0585using testing::AnyNumber;
86using testing::Return;
[email protected]f702d572012-12-04 15:56:2087
88namespace net {
[email protected]f702d572012-12-04 15:56:2089namespace test {
[email protected]f702d572012-12-04 15:56:2090namespace {
91
[email protected]16ba7742014-08-22 00:57:2592const char kUploadData[] = "Really nifty data!";
rch9ae5b3b2016-02-11 00:36:2993const char kDefaultServerHostName[] = "www.example.org";
rchcd379012017-04-12 21:53:3294const uint16_t kDefaultServerPort = 443;
[email protected]f702d572012-12-04 15:56:2095
David Schinazi09e9a6012019-10-03 17:37:5796struct TestParams {
97 quic::ParsedQuicVersion version;
98 bool client_headers_include_h2_stream_dependency;
99};
100
101// Used by ::testing::PrintToStringParamName().
102std::string PrintToString(const TestParams& p) {
Victor Vasiliev62c09dc2020-11-06 18:18:29103 return base::StrCat(
104 {ParsedQuicVersionToString(p.version), "_",
105 (p.client_headers_include_h2_stream_dependency ? "" : "No"),
106 "Dependency"});
David Schinazi09e9a6012019-10-03 17:37:57107}
108
109std::vector<TestParams> GetTestParams() {
110 std::vector<TestParams> params;
111 quic::ParsedQuicVersionVector all_supported_versions =
112 quic::AllSupportedVersions();
113 for (const auto& version : all_supported_versions) {
114 params.push_back(TestParams{version, false});
115 params.push_back(TestParams{version, true});
116 }
117 return params;
118}
119
Bence Békye0d3747d2020-08-28 23:16:40120// Returns true if |params| is a dict, has an entry with key "headers", that
121// entry is a list of strings, which when interpreted as colon-separated
122// key-value pairs has exactly one entry with |key| and that entry has value
123// |expected_value|.
124bool CheckHeader(const base::Value& params,
125 base::StringPiece key,
126 base::StringPiece expected_value) {
127 if (!params.is_dict()) {
128 return false;
129 }
130 const base::Value* headers = params.FindListKey("headers");
131 if (!headers) {
132 return false;
133 }
134
135 std::string header_prefix = base::StrCat({key, ": "});
136 std::string expected_header = base::StrCat({header_prefix, expected_value});
137
138 auto header_list = headers->GetList();
139 auto header_it = header_list.begin();
140 bool header_found = false;
141 while (header_it != header_list.end()) {
142 if (!header_it->is_string()) {
143 return false;
144 }
145 const std::string& header = header_it->GetString();
146 if (base::StartsWith(header, header_prefix)) {
147 if (header_found) {
148 return false;
149 }
150 if (header != expected_header) {
151 return false;
152 }
153 header_found = true;
154 }
155 ++header_it;
156 }
157 return header_found;
158}
159
Ryan Hamilton8d9ee76e2018-05-29 23:52:52160class TestQuicConnection : public quic::QuicConnection {
[email protected]f702d572012-12-04 15:56:20161 public:
Ryan Hamilton8d9ee76e2018-05-29 23:52:52162 TestQuicConnection(const quic::ParsedQuicVersionVector& versions,
163 quic::QuicConnectionId connection_id,
[email protected]f702d572012-12-04 15:56:20164 IPEndPoint address,
rch12fef552016-01-15 16:26:31165 QuicChromiumConnectionHelper* helper,
rch16c74d1d2016-04-22 06:14:07166 QuicChromiumAlarmFactory* alarm_factory,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52167 quic::QuicPacketWriter* writer)
Victor Vasiliev4f6fb892019-05-31 16:58:31168 : quic::QuicConnection(connection_id,
Nick Harperd049f192020-10-02 02:56:10169 quic::QuicSocketAddress(),
Victor Vasiliev4f6fb892019-05-31 16:58:31170 ToQuicSocketAddress(address),
171 helper,
172 alarm_factory,
173 writer,
174 true /* owns_writer */,
175 quic::Perspective::IS_CLIENT,
176 versions) {}
[email protected]f702d572012-12-04 15:56:20177
Ryan Hamilton8d9ee76e2018-05-29 23:52:52178 void SetSendAlgorithm(quic::SendAlgorithmInterface* send_algorithm) {
179 quic::test::QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
[email protected]f702d572012-12-04 15:56:20180 }
181};
182
maksim.sisov84e20c92016-06-23 08:49:34183// UploadDataStream that always returns errors on data read.
184class ReadErrorUploadDataStream : public UploadDataStream {
185 public:
186 enum class FailureMode { SYNC, ASYNC };
187
188 explicit ReadErrorUploadDataStream(FailureMode mode)
Jeremy Romand54000b22019-07-08 18:40:16189 : UploadDataStream(true, 0), async_(mode) {}
maksim.sisov84e20c92016-06-23 08:49:34190 ~ReadErrorUploadDataStream() override {}
191
192 private:
193 void CompleteRead() { UploadDataStream::OnReadCompleted(ERR_FAILED); }
194
195 // UploadDataStream implementation:
tfarina42834112016-09-22 13:38:20196 int InitInternal(const NetLogWithSource& net_log) override { return OK; }
maksim.sisov84e20c92016-06-23 08:49:34197
198 int ReadInternal(IOBuffer* buf, int buf_len) override {
199 if (async_ == FailureMode::ASYNC) {
200 base::ThreadTaskRunnerHandle::Get()->PostTask(
kylecharf4fe5172019-02-15 18:53:49201 FROM_HERE, base::BindOnce(&ReadErrorUploadDataStream::CompleteRead,
202 weak_factory_.GetWeakPtr()));
maksim.sisov84e20c92016-06-23 08:49:34203 return ERR_IO_PENDING;
204 }
205 return ERR_FAILED;
206 }
207
208 void ResetInternal() override {}
209
210 const FailureMode async_;
211
Jeremy Romand54000b22019-07-08 18:40:16212 base::WeakPtrFactory<ReadErrorUploadDataStream> weak_factory_{this};
maksim.sisov84e20c92016-06-23 08:49:34213
214 DISALLOW_COPY_AND_ASSIGN(ReadErrorUploadDataStream);
215};
216
Bence Béky8ddc2492018-06-13 01:02:04217// A helper class that will delete |stream| when the callback is invoked.
xunjieli8dff50b2016-07-22 14:19:06218class DeleteStreamCallback : public TestCompletionCallbackBase {
219 public:
Bence Béky8ddc2492018-06-13 01:02:04220 explicit DeleteStreamCallback(std::unique_ptr<QuicHttpStream> stream)
221 : stream_(std::move(stream)) {}
xunjieli8dff50b2016-07-22 14:19:06222
Bence Béky8ddc2492018-06-13 01:02:04223 CompletionOnceCallback callback() {
224 return base::BindOnce(&DeleteStreamCallback::DeleteStream,
225 base::Unretained(this));
226 }
xunjieli8dff50b2016-07-22 14:19:06227
228 private:
229 void DeleteStream(int result) {
230 stream_.reset();
231 SetResult(result);
232 }
233
234 std::unique_ptr<QuicHttpStream> stream_;
xunjieli8dff50b2016-07-22 14:19:06235};
236
[email protected]f702d572012-12-04 15:56:20237} // namespace
238
[email protected]24e5bc52013-09-18 15:36:58239class QuicHttpStreamPeer {
240 public:
rch08e198572017-05-09 16:56:55241 static QuicChromiumClientStream::Handle* GetQuicChromiumClientStream(
[email protected]24e5bc52013-09-18 15:36:58242 QuicHttpStream* stream) {
rch08e198572017-05-09 16:56:55243 return stream->stream_.get();
[email protected]24e5bc52013-09-18 15:36:58244 }
245};
246
David Schinazi09e9a6012019-10-03 17:37:57247class QuicHttpStreamTest : public ::testing::TestWithParam<TestParams>,
Gabriel Charette694c3c332019-08-19 14:53:05248 public WithTaskEnvironment {
rchfb47f712017-05-21 03:24:00249 public:
250 void CloseStream(QuicHttpStream* stream, int /*rv*/) { stream->Close(false); }
251
[email protected]f702d572012-12-04 15:56:20252 protected:
[email protected]1e960032013-12-20 19:00:20253 static const bool kFin = true;
254 static const bool kIncludeVersion = true;
[email protected]1e960032013-12-20 19:00:20255
[email protected]f702d572012-12-04 15:56:20256 // Holds a packet to be written to the wire, and the IO mode that should
257 // be used by the mock socket when performing the write.
258 struct PacketToWrite {
Ryan Hamilton8d9ee76e2018-05-29 23:52:52259 PacketToWrite(IoMode mode, quic::QuicReceivedPacket* packet)
rjshaded5ced072015-12-18 19:26:02260 : mode(mode), packet(packet) {}
rtenneti15656ae2016-01-23 03:05:03261 PacketToWrite(IoMode mode, int rv) : mode(mode), packet(nullptr), rv(rv) {}
[email protected]f702d572012-12-04 15:56:20262 IoMode mode;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52263 quic::QuicReceivedPacket* packet;
rtenneti15656ae2016-01-23 03:05:03264 int rv;
[email protected]f702d572012-12-04 15:56:20265 };
266
267 QuicHttpStreamTest()
David Schinazi09e9a6012019-10-03 17:37:57268 : version_(GetParam().version),
269 client_headers_include_h2_stream_dependency_(
270 GetParam().client_headers_include_h2_stream_dependency),
Nick Harpera598fc5f2019-06-21 08:46:50271 crypto_config_(
272 quic::test::crypto_test_utils::ProofVerifierForTesting()),
Victor Costan9c7302b2018-08-27 16:39:44273 read_buffer_(base::MakeRefCounted<IOBufferWithSize>(4096)),
Fan Yang32c5a112018-12-10 20:06:33274 promise_id_(GetNthServerInitiatedUnidirectionalStreamId(0)),
275 stream_id_(GetNthClientInitiatedBidirectionalStreamId(0)),
David Schinazic8281052019-01-24 06:14:17276 connection_id_(quic::test::TestConnectionId(2)),
Yixin Wang079ad542018-01-11 04:06:05277 client_maker_(version_,
alyssar2adf3ac2016-05-03 17:12:58278 connection_id_,
279 &clock_,
280 kDefaultServerHostName,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52281 quic::Perspective::IS_CLIENT,
Yixin Wang079ad542018-01-11 04:06:05282 client_headers_include_h2_stream_dependency_),
283 server_maker_(version_,
zhongyi5dbfdd42017-06-20 05:22:15284 connection_id_,
alyssar2adf3ac2016-05-03 17:12:58285 &clock_,
286 kDefaultServerHostName,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52287 quic::Perspective::IS_SERVER,
Yixin Wang079ad542018-01-11 04:06:05288 false),
ckrasic3865ee0f2016-02-29 22:04:56289 random_generator_(0),
Ryan Hamilton0d65a8c2019-06-07 00:46:02290 printer_(version_) {
Renjie Tang98b4d512020-02-08 01:24:19291 FLAGS_quic_enable_http3_grease_randomness = false;
Zhongyi Shi49f8ad2fd2019-12-13 01:20:31292 quic::QuicEnableVersion(version_);
martijn21968ea2016-02-24 18:46:20293 IPAddress ip(192, 0, 2, 33);
[email protected]f702d572012-12-04 15:56:20294 peer_addr_ = IPEndPoint(ip, 443);
295 self_addr_ = IPEndPoint(ip, 8435);
Ryan Hamilton8d9ee76e2018-05-29 23:52:52296 clock_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(20));
Ramin Halavati683bcaa92018-02-14 08:42:39297 request_.traffic_annotation =
298 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f702d572012-12-04 15:56:20299 }
300
301 ~QuicHttpStreamTest() {
Renjieba55fae2018-09-20 03:05:16302 session_->CloseSessionOnError(ERR_ABORTED, quic::QUIC_INTERNAL_ERROR,
303 quic::ConnectionCloseBehavior::SILENT_CLOSE);
[email protected]f702d572012-12-04 15:56:20304 for (size_t i = 0; i < writes_.size(); i++) {
305 delete writes_[i].packet;
306 }
307 }
308
309 // Adds a packet to the list of expected writes.
Ryan Hamilton8d9ee76e2018-05-29 23:52:52310 void AddWrite(std::unique_ptr<quic::QuicReceivedPacket> packet) {
[email protected]1e960032013-12-20 19:00:20311 writes_.push_back(PacketToWrite(SYNCHRONOUS, packet.release()));
[email protected]f702d572012-12-04 15:56:20312 }
313
rtenneti15656ae2016-01-23 03:05:03314 void AddWrite(IoMode mode, int rv) {
315 writes_.push_back(PacketToWrite(mode, rv));
316 }
317
[email protected]f702d572012-12-04 15:56:20318 // Returns the packet to be written at position |pos|.
Ryan Hamilton8d9ee76e2018-05-29 23:52:52319 quic::QuicReceivedPacket* GetWrite(size_t pos) { return writes_[pos].packet; }
[email protected]f702d572012-12-04 15:56:20320
321 bool AtEof() {
rch37de576c2015-05-17 20:28:17322 return socket_data_->AllReadDataConsumed() &&
323 socket_data_->AllWriteDataConsumed();
[email protected]f702d572012-12-04 15:56:20324 }
325
Ryan Hamilton8d9ee76e2018-05-29 23:52:52326 void ProcessPacket(std::unique_ptr<quic::QuicReceivedPacket> packet) {
Victor Vasiliev4f6fb892019-05-31 16:58:31327 connection_->ProcessUdpPacket(ToQuicSocketAddress(self_addr_),
328 ToQuicSocketAddress(peer_addr_), *packet);
[email protected]f702d572012-12-04 15:56:20329 }
330
331 // Configures the test fixture to use the list of expected writes.
332 void Initialize() {
Renjie Tang6ff9a9b2021-02-03 22:11:09333 mock_writes_ = std::make_unique<MockWrite[]>(writes_.size());
[email protected]f702d572012-12-04 15:56:20334 for (size_t i = 0; i < writes_.size(); i++) {
rtenneti15656ae2016-01-23 03:05:03335 if (writes_[i].packet == nullptr) {
336 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].rv, i);
337 } else {
338 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].packet->data(),
339 writes_[i].packet->length());
340 }
bnc614a92d32016-04-04 13:56:07341 }
[email protected]f702d572012-12-04 15:56:20342
Renjie Tang6ff9a9b2021-02-03 22:11:09343 socket_data_ = std::make_unique<StaticSocketDataProvider>(
Ryan Sleevib8d7ea02018-05-07 20:01:01344 base::span<MockRead>(),
Renjie Tang6ff9a9b2021-02-03 22:11:09345 base::make_span(mock_writes_.get(), writes_.size()));
Ryan Hamilton0d65a8c2019-06-07 00:46:02346 socket_data_->set_printer(&printer_);
[email protected]f702d572012-12-04 15:56:20347
danakjad1777e2016-04-16 00:56:42348 std::unique_ptr<MockUDPClientSocket> socket(new MockUDPClientSocket(
xunjielib53b38c2016-03-24 15:54:36349 socket_data_.get(), net_log_.bound().net_log()));
[email protected]e13201d82012-12-12 05:00:32350 socket->Connect(peer_addr_);
[email protected]f702d572012-12-04 15:56:20351 runner_ = new TestTaskRunner(&clock_);
Ryan Hamilton8d9ee76e2018-05-29 23:52:52352 send_algorithm_ = new quic::test::MockSendAlgorithm();
rch7dd15702015-07-01 18:57:57353 EXPECT_CALL(*send_algorithm_, InRecovery()).WillRepeatedly(Return(false));
354 EXPECT_CALL(*send_algorithm_, InSlowStart()).WillRepeatedly(Return(false));
Victor Vasiliev7da08172019-10-14 06:04:25355 if (VersionUsesHttp3(version_.transport_version)) {
Renjie Tangaadb84b2019-08-31 01:00:23356 EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
357 .Times(testing::AtLeast(1));
358 }
Ryan Hamiltona1d1f4a2019-06-26 14:43:04359 EXPECT_CALL(*send_algorithm_, OnCongestionEvent(_, _, _, _, _))
360 .Times(AnyNumber());
rtenneti44f4a2e2015-08-07 14:00:07361 EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
Zhongyi Shica576df2019-04-12 17:43:40362 .WillRepeatedly(Return(quic::kMaxOutgoingPacketSize));
jokulik0e0a00c32016-06-13 21:51:58363 EXPECT_CALL(*send_algorithm_, PacingRate(_))
Ryan Hamilton8d9ee76e2018-05-29 23:52:52364 .WillRepeatedly(Return(quic::QuicBandwidth::Zero()));
Michael Warres74ee3ce2017-10-09 15:26:37365 EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true));
rtenneti44f4a2e2015-08-07 14:00:07366 EXPECT_CALL(*send_algorithm_, BandwidthEstimate())
Ryan Hamilton8d9ee76e2018-05-29 23:52:52367 .WillRepeatedly(Return(quic::QuicBandwidth::Zero()));
rch1e543ec2015-03-29 07:04:40368 EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(AnyNumber());
rch08cae032017-03-29 00:59:15369 EXPECT_CALL(*send_algorithm_, OnApplicationLimited(_)).Times(AnyNumber());
rch0d5bcf62017-05-24 22:48:45370 EXPECT_CALL(*send_algorithm_, GetCongestionControlType())
371 .Times(AnyNumber());
Renjie Tang6ff9a9b2021-02-03 22:11:09372 helper_ = std::make_unique<QuicChromiumConnectionHelper>(
373 &clock_, &random_generator_);
374 alarm_factory_ =
375 std::make_unique<QuicChromiumAlarmFactory>(runner_.get(), &clock_);
rch16c74d1d2016-04-22 06:14:07376
Michael Warres74ee3ce2017-10-09 15:26:37377 connection_ = new TestQuicConnection(
Nick Harper23290b82019-05-02 00:02:56378 quic::test::SupportedVersions(version_), connection_id_, peer_addr_,
379 helper_.get(), alarm_factory_.get(),
Ryan Hamilton9edcf1a2017-11-22 05:55:17380 new QuicChromiumPacketWriter(
381 socket.get(), base::ThreadTaskRunnerHandle::Get().get()));
[email protected]f702d572012-12-04 15:56:20382 connection_->set_visitor(&visitor_);
[email protected]fee17f72013-02-03 07:47:41383 connection_->SetSendAlgorithm(send_algorithm_);
rch03b7a202016-02-05 00:54:20384
385 // Load a certificate that is valid for *.example.org
386 scoped_refptr<X509Certificate> test_cert(
387 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
388 EXPECT_TRUE(test_cert.get());
389
390 verify_details_.cert_verify_result.verified_cert = test_cert;
391 verify_details_.cert_verify_result.is_issued_by_known_root = true;
392 crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details_);
393
xunjieli84adaab2016-09-20 01:12:28394 base::TimeTicks dns_end = base::TimeTicks::Now();
395 base::TimeTicks dns_start = dns_end - base::TimeDelta::FromMilliseconds(1);
Renjie Tang6ff9a9b2021-02-03 22:11:09396 session_ = std::make_unique<QuicChromiumClientSession>(
xunjielib53b38c2016-03-24 15:54:36397 connection_, std::move(socket),
rtenneti1cd3b162015-09-29 02:58:28398 /*stream_factory=*/nullptr, &crypto_client_stream_factory_, &clock_,
Nick Harper89bc7212018-07-31 19:07:57399 &transport_security_state_, /*ssl_config_service=*/nullptr,
danakjad1777e2016-04-16 00:56:42400 base::WrapUnique(static_cast<QuicServerInfo*>(nullptr)),
Paul Jensen8e3c5d32018-02-19 17:06:33401 QuicSessionKey(kDefaultServerHostName, kDefaultServerPort,
dalyk51ab46b2019-10-15 15:14:34402 PRIVACY_MODE_DISABLED, SocketTag(),
403 NetworkIsolationKey(), false /* disable_secure_dns */),
Bence Béky1ceba552019-07-19 17:11:05404 /*require_confirmation=*/false,
405 /*max_allowed_push_id=*/0,
406 /*migrate_session_early_v2=*/false,
Zhongyi Shi757fcce2018-06-27 05:41:27407 /*migrate_session_on_network_change_v2=*/false,
408 /*default_network=*/NetworkChangeNotifier::kInvalidNetworkHandle,
Zhongyi Shie01f2db2019-02-22 19:53:23409 quic::QuicTime::Delta::FromMilliseconds(
Ryan Sleevi2e8255b2019-07-17 21:02:21410 kDefaultRetransmittableOnWireTimeout.InMilliseconds()),
Zhongyi Shiaf38c4e42019-08-29 22:49:05411 /*migrate_idle_session=*/false, /*allow_port_migration=*/false,
412 kDefaultIdleSessionMigrationPeriod, kMaxTimeOnNonDefaultNetwork,
Zhongyi Shiee760762018-08-01 00:54:29413 kMaxMigrationsToNonDefaultNetworkOnWriteError,
Zhongyi Shi8b1e43f2017-12-13 20:46:30414 kMaxMigrationsToNonDefaultNetworkOnPathDegrading,
Zhongyi Shi5f587cc2017-11-21 23:24:17415 kQuicYieldAfterPacketsRead,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52416 quic::QuicTime::Delta::FromMilliseconds(
417 kQuicYieldAfterDurationMilliseconds),
Zhongyi Shidbce7f412019-02-01 23:16:29418 /*go_away_on_path_degrading*/ false,
Yixin Wang079ad542018-01-11 04:06:05419 client_headers_include_h2_stream_dependency_, /*cert_verify_flags=*/0,
Matt Menkefca05b62019-09-20 23:15:56420 quic::test::DefaultQuicConfig(),
421 std::make_unique<TestQuicCryptoClientConfigHandle>(&crypto_config_),
Matt Menked804aaf2020-07-21 21:25:48422 "CONNECTION_UNKNOWN", dns_start, dns_end,
423 std::make_unique<quic::QuicClientPushPromiseIndex>(), nullptr,
Zhongyi Shic16b4102019-02-12 00:37:40424 base::DefaultTickClock::GetInstance(),
xunjieli84adaab2016-09-20 01:12:28425 base::ThreadTaskRunnerHandle::Get().get(),
Renjie Tang6ff9a9b2021-02-03 22:11:09426 /*socket_performance_watcher=*/nullptr, net_log_.bound().net_log());
rtennetid39bd762015-06-12 01:05:52427 session_->Initialize();
rchf0b18c8a2017-05-05 19:31:57428
Bence Béky6e243aa2019-12-13 19:01:07429 // Blackhole QPACK decoder stream instead of constructing mock writes.
430 if (VersionUsesHttp3(version_.transport_version)) {
431 session_->qpack_decoder()->set_qpack_stream_sender_delegate(
432 &noop_qpack_stream_sender_delegate_);
433 }
434
435 TestCompletionCallback callback;
rch433bf5f2017-02-14 04:10:47436 session_->CryptoConnect(callback.callback());
Ryan Hamilton6c2a2a82017-12-15 02:06:28437 stream_ = std::make_unique<QuicHttpStream>(
Cammie Smith Barnes0f38aff2021-03-02 23:14:35438 session_->CreateHandle(HostPortPair("www.example.org", 443)),
439 std::vector<std::string>() /* dns_aliases */);
Ryan Hamilton6c2a2a82017-12-15 02:06:28440 promised_stream_ = std::make_unique<QuicHttpStream>(
Cammie Smith Barnes0f38aff2021-03-02 23:14:35441 session_->CreateHandle(HostPortPair("www.example.org", 443)),
442 std::vector<std::string>() /* dns_aliases */);
ckrasic3865ee0f2016-02-29 22:04:56443 push_promise_[":path"] = "/bar";
444 push_promise_[":authority"] = "www.example.org";
445 push_promise_[":version"] = "HTTP/1.1";
446 push_promise_[":method"] = "GET";
447 push_promise_[":scheme"] = "https";
448
449 promised_response_[":status"] = "200 OK";
450 promised_response_[":version"] = "HTTP/1.1";
451 promised_response_["content-type"] = "text/plain";
452
David Schinazi3f7465c2019-07-12 01:57:05453 promise_url_ =
454 quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
[email protected]6cca996b2013-01-25 07:43:36455 }
456
bnc614a92d32016-04-04 13:56:07457 void SetRequest(const string& method,
458 const string& path,
[email protected]1e960032013-12-20 19:00:20459 RequestPriority priority) {
rchcd379012017-04-12 21:53:32460 request_headers_ = client_maker_.GetRequestHeaders(method, "https", path);
[email protected]6cca996b2013-01-25 07:43:36461 }
462
bnc614a92d32016-04-04 13:56:07463 void SetResponse(const string& status, const string& body) {
alyssar2adf3ac2016-05-03 17:12:58464 response_headers_ = server_maker_.GetResponseHeaders(status);
[email protected]92bf17c2014-03-03 21:14:03465 response_data_ = body;
[email protected]6cca996b2013-01-25 07:43:36466 }
[email protected]f702d572012-12-04 15:56:20467
Ryan Hamilton8d9ee76e2018-05-29 23:52:52468 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientDataPacket(
Fan Yangac867502019-01-28 21:10:23469 uint64_t packet_number,
[email protected]e8ff26842013-03-22 21:02:05470 bool should_include_version,
[email protected]f702d572012-12-04 15:56:20471 bool fin,
Victor Vasiliev47ecb6a2020-10-14 17:22:10472 absl::string_view data) {
Ryan Hamilton7505eb92019-06-08 00:22:17473 return client_maker_.MakeDataPacket(packet_number, stream_id_,
474 should_include_version, fin, data);
alyssar2adf3ac2016-05-03 17:12:58475 }
476
Ryan Hamilton8d9ee76e2018-05-29 23:52:52477 std::unique_ptr<quic::QuicReceivedPacket> ConstructServerDataPacket(
Fan Yangac867502019-01-28 21:10:23478 uint64_t packet_number,
alyssar2adf3ac2016-05-03 17:12:58479 bool should_include_version,
480 bool fin,
Victor Vasiliev47ecb6a2020-10-14 17:22:10481 absl::string_view data) {
Ryan Hamilton7505eb92019-06-08 00:22:17482 return server_maker_.MakeDataPacket(packet_number, stream_id_,
483 should_include_version, fin, data);
ckrasic3865ee0f2016-02-29 22:04:56484 }
485
Ryan Hamilton8d9ee76e2018-05-29 23:52:52486 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23487 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52488 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56489 bool should_include_version,
490 bool fin,
491 RequestPriority request_priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02492 size_t* spdy_headers_frame_length) {
Yixin Wang7a3f1b8d2018-01-17 21:40:48493 return InnerConstructRequestHeadersPacket(
494 packet_number, stream_id, should_include_version, fin, request_priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02495 0, spdy_headers_frame_length);
Yixin Wang7a3f1b8d2018-01-17 21:40:48496 }
497
Ryan Hamilton8d9ee76e2018-05-29 23:52:52498 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23499 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52500 quic::QuicStreamId stream_id,
Yixin Wang7a3f1b8d2018-01-17 21:40:48501 bool should_include_version,
502 bool fin,
503 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52504 quic::QuicStreamId parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02505 size_t* spdy_headers_frame_length) {
Ryan Hamilton0239aac2018-05-19 00:03:13506 spdy::SpdyPriority priority =
ckrasic3865ee0f2016-02-29 22:04:56507 ConvertRequestPriorityToQuicPriority(request_priority);
alyssar2adf3ac2016-05-03 17:12:58508 return client_maker_.MakeRequestHeadersPacket(
ckrasic3865ee0f2016-02-29 22:04:56509 packet_number, stream_id, should_include_version, fin, priority,
Yixin Wang7a3f1b8d2018-01-17 21:40:48510 std::move(request_headers_), parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02511 spdy_headers_frame_length);
[email protected]f702d572012-12-04 15:56:20512 }
513
Ryan Hamilton8d9ee76e2018-05-29 23:52:52514 std::unique_ptr<quic::QuicReceivedPacket>
Yixin Wange7ecc472018-03-06 19:00:25515 ConstructRequestHeadersAndDataFramesPacket(
Fan Yangac867502019-01-28 21:10:23516 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52517 quic::QuicStreamId stream_id,
Yixin Wange7ecc472018-03-06 19:00:25518 bool should_include_version,
519 bool fin,
520 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52521 quic::QuicStreamId parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25522 size_t* spdy_headers_frame_length,
523 const std::vector<std::string>& data_writes) {
Ryan Hamilton0239aac2018-05-19 00:03:13524 spdy::SpdyPriority priority =
Yixin Wange7ecc472018-03-06 19:00:25525 ConvertRequestPriorityToQuicPriority(request_priority);
526 return client_maker_.MakeRequestHeadersAndMultipleDataFramesPacket(
527 packet_number, stream_id, should_include_version, fin, priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02528 std::move(request_headers_), parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25529 spdy_headers_frame_length, data_writes);
530 }
531
Ryan Hamilton8d9ee76e2018-05-29 23:52:52532 std::unique_ptr<quic::QuicReceivedPacket> ConstructRequestAndRstPacket(
Fan Yangac867502019-01-28 21:10:23533 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52534 quic::QuicStreamId stream_id,
Yixin Wange7ecc472018-03-06 19:00:25535 bool should_include_version,
536 bool fin,
537 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52538 quic::QuicStreamId parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25539 size_t* spdy_headers_frame_length,
Ryan Hamiltonb5d4c5a2019-06-21 22:08:41540 quic::QuicRstStreamErrorCode error_code) {
Ryan Hamilton0239aac2018-05-19 00:03:13541 spdy::SpdyPriority priority =
Yixin Wange7ecc472018-03-06 19:00:25542 ConvertRequestPriorityToQuicPriority(request_priority);
543 return client_maker_.MakeRequestHeadersAndRstPacket(
544 packet_number, stream_id, should_include_version, fin, priority,
545 std::move(request_headers_), parent_stream_id,
Ryan Hamiltonb5d4c5a2019-06-21 22:08:41546 spdy_headers_frame_length, error_code);
Yixin Wange7ecc472018-03-06 19:00:25547 }
548
Ryan Hamilton8d9ee76e2018-05-29 23:52:52549 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructResponseHeadersPacket(
Fan Yangac867502019-01-28 21:10:23550 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52551 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56552 bool fin,
553 size_t* spdy_headers_frame_length) {
alyssar2adf3ac2016-05-03 17:12:58554 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26555 packet_number, stream_id, !kIncludeVersion, fin,
Ryan Hamilton0d65a8c2019-06-07 00:46:02556 std::move(response_headers_), spdy_headers_frame_length);
[email protected]1e960032013-12-20 19:00:20557 }
558
Ryan Hamilton8d9ee76e2018-05-29 23:52:52559 std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseHeadersPacket(
Fan Yangac867502019-01-28 21:10:23560 uint64_t packet_number,
sclittlec4dc1a32015-09-24 00:15:45561 bool fin,
562 size_t* spdy_headers_frame_length) {
ckrasic3865ee0f2016-02-29 22:04:56563 return InnerConstructResponseHeadersPacket(packet_number, stream_id_, fin,
564 spdy_headers_frame_length);
[email protected]1e960032013-12-20 19:00:20565 }
566
Ryan Hamilton8d9ee76e2018-05-29 23:52:52567 std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseTrailersPacket(
Fan Yangac867502019-01-28 21:10:23568 uint64_t packet_number,
xunjieli34291fe12016-03-02 13:58:38569 bool fin,
Bence Béky4c325e52020-10-22 20:48:01570 spdy::Http2HeaderBlock trailers,
Ryan Hamilton0d65a8c2019-06-07 00:46:02571 size_t* spdy_headers_frame_length) {
alyssar2adf3ac2016-05-03 17:12:58572 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26573 packet_number, stream_id_, !kIncludeVersion, fin, std::move(trailers),
Ryan Hamilton0d65a8c2019-06-07 00:46:02574 spdy_headers_frame_length);
xunjieli34291fe12016-03-02 13:58:38575 }
576
Ryan Hamilton8d9ee76e2018-05-29 23:52:52577 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientRstStreamErrorPacket(
Fan Yangac867502019-01-28 21:10:23578 uint64_t packet_number,
maksim.sisov84e20c92016-06-23 08:49:34579 bool include_version) {
580 return client_maker_.MakeRstPacket(packet_number, include_version,
581 stream_id_,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52582 quic::QUIC_ERROR_PROCESSING_STREAM);
maksim.sisov84e20c92016-06-23 08:49:34583 }
584
Ryan Hamilton8d9ee76e2018-05-29 23:52:52585 std::unique_ptr<quic::QuicReceivedPacket> ConstructAckAndRstStreamPacket(
Fan Yangac867502019-01-28 21:10:23586 uint64_t packet_number) {
Renjie Tangcd594f32020-07-11 20:18:34587 return client_maker_.MakeAckAndRstPacket(packet_number, !kIncludeVersion,
588 stream_id_,
589 quic::QUIC_STREAM_CANCELLED, 2, 1);
[email protected]c5e1aca2014-01-30 04:03:04590 }
591
Ryan Hamilton8d9ee76e2018-05-29 23:52:52592 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientAckPacket(
Fan Yangac867502019-01-28 21:10:23593 uint64_t packet_number,
594 uint64_t largest_received,
Renjie Tangcd594f32020-07-11 20:18:34595 uint64_t smallest_received) {
alyssar2adf3ac2016-05-03 17:12:58596 return client_maker_.MakeAckPacket(packet_number, largest_received,
Renjie Tangcd594f32020-07-11 20:18:34597 smallest_received);
alyssar2adf3ac2016-05-03 17:12:58598 }
599
Ryan Hamilton8d9ee76e2018-05-29 23:52:52600 std::unique_ptr<quic::QuicReceivedPacket> ConstructServerAckPacket(
Fan Yangac867502019-01-28 21:10:23601 uint64_t packet_number,
602 uint64_t largest_received,
603 uint64_t smallest_received,
604 uint64_t least_unacked) {
alyssar2adf3ac2016-05-03 17:12:58605 return server_maker_.MakeAckPacket(packet_number, largest_received,
Bence Béky7a45d4d2020-05-08 01:59:23606 smallest_received, least_unacked);
[email protected]63534512012-12-23 18:49:00607 }
608
Ryan Hamilton0d65a8c2019-06-07 00:46:02609 std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket() {
610 return client_maker_.MakeInitialSettingsPacket(1);
fayang3bcb8b502016-12-07 21:44:37611 }
612
Renjie Tangaadb84b2019-08-31 01:00:23613 std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket(
614 int packet_number) {
615 return client_maker_.MakeInitialSettingsPacket(packet_number);
616 }
617
Victor Vasiliev076657c2019-03-12 02:46:43618 std::string ConstructDataHeader(size_t body_len) {
Nick Harperc6cb7a612020-02-24 20:03:32619 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:41620 return "";
621 }
Renjief49758b2019-01-11 23:32:41622 std::unique_ptr<char[]> buffer;
Victor Vasiliev55d997922019-10-31 19:40:57623 auto header_length =
624 quic::HttpEncoder::SerializeDataFrameHeader(body_len, &buffer);
Victor Vasiliev076657c2019-03-12 02:46:43625 return std::string(buffer.get(), header_length);
Renjief49758b2019-01-11 23:32:41626 }
627
Ryan Hamilton8d9ee76e2018-05-29 23:52:52628 void ReceivePromise(quic::QuicStreamId id) {
629 auto headers = quic::test::AsHeaderList(push_promise_);
rch08e198572017-05-09 16:56:55630 QuicChromiumClientStream::Handle* stream =
ckrasic3865ee0f2016-02-29 22:04:56631 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
ckrasic32b17dcd2016-10-31 06:15:35632 stream->OnPromiseHeaderList(id, headers.uncompressed_header_bytes(),
633 headers);
ckrasic3865ee0f2016-02-29 22:04:56634 }
635
xunjieli84adaab2016-09-20 01:12:28636 void ExpectLoadTimingValid(const LoadTimingInfo& load_timing_info,
xunjieli100937eb52016-09-15 20:09:37637 bool session_reused) {
638 EXPECT_EQ(session_reused, load_timing_info.socket_reused);
xunjieli84adaab2016-09-20 01:12:28639 if (session_reused) {
640 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
641 } else {
642 ExpectConnectTimingHasTimes(
643 load_timing_info.connect_timing,
644 CONNECT_TIMING_HAS_SSL_TIMES | CONNECT_TIMING_HAS_DNS_TIMES);
645 }
646 ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info);
xunjieli100937eb52016-09-15 20:09:37647 }
648
Fan Yang32c5a112018-12-10 20:06:33649 quic::QuicStreamId GetNthClientInitiatedBidirectionalStreamId(int n) {
Nick Harper23290b82019-05-02 00:02:56650 return quic::test::GetNthClientInitiatedBidirectionalStreamId(
651 version_.transport_version, n);
ckrasicbf2f59c2017-05-04 23:54:36652 }
653
Fan Yang32c5a112018-12-10 20:06:33654 quic::QuicStreamId GetNthServerInitiatedUnidirectionalStreamId(int n) {
Nick Harper23290b82019-05-02 00:02:56655 return quic::test::GetNthServerInitiatedUnidirectionalStreamId(
656 version_.transport_version, n);
ckrasicbf2f59c2017-05-04 23:54:36657 }
658
Ryan Hamiltona1d1f4a2019-06-26 14:43:04659 QuicFlagSaver saver_;
660
Nick Harper23290b82019-05-02 00:02:56661 const quic::ParsedQuicVersion version_;
Yixin Wang079ad542018-01-11 04:06:05662 const bool client_headers_include_h2_stream_dependency_;
663
Matt Muellerd9342e3a2019-11-26 01:41:14664 RecordingBoundTestNetLog net_log_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52665 quic::test::MockSendAlgorithm* send_algorithm_;
[email protected]f702d572012-12-04 15:56:20666 scoped_refptr<TestTaskRunner> runner_;
danakjad1777e2016-04-16 00:56:42667 std::unique_ptr<MockWrite[]> mock_writes_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52668 quic::MockClock clock_;
[email protected]f702d572012-12-04 15:56:20669 TestQuicConnection* connection_;
danakjad1777e2016-04-16 00:56:42670 std::unique_ptr<QuicChromiumConnectionHelper> helper_;
rch16c74d1d2016-04-22 06:14:07671 std::unique_ptr<QuicChromiumAlarmFactory> alarm_factory_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52672 testing::StrictMock<quic::test::MockQuicConnectionVisitor> visitor_;
rch97827ee2017-05-24 23:49:12673 std::unique_ptr<UploadDataStream> upload_data_stream_;
danakjad1777e2016-04-16 00:56:42674 std::unique_ptr<QuicHttpStream> stream_;
[email protected]5db452202014-08-19 05:22:15675 TransportSecurityState transport_security_state_;
danakjad1777e2016-04-16 00:56:42676 std::unique_ptr<QuicChromiumClientSession> session_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52677 quic::QuicCryptoClientConfig crypto_config_;
[email protected]f702d572012-12-04 15:56:20678 TestCompletionCallback callback_;
679 HttpRequestInfo request_;
680 HttpRequestHeaders headers_;
681 HttpResponseInfo response_;
682 scoped_refptr<IOBufferWithSize> read_buffer_;
Bence Béky4c325e52020-10-22 20:48:01683 spdy::Http2HeaderBlock request_headers_;
684 spdy::Http2HeaderBlock response_headers_;
bnc614a92d32016-04-04 13:56:07685 string request_data_;
686 string response_data_;
[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_;
Bence Béky4c325e52020-10-22 20:48:01690 spdy::Http2HeaderBlock push_promise_;
691 spdy::Http2HeaderBlock 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_;
Bence Béky6e243aa2019-12-13 19:01:07707 quic::test::NoopQpackStreamSenderDelegate noop_qpack_stream_sender_delegate_;
[email protected]f702d572012-12-04 15:56:20708};
709
David Schinazi09e9a6012019-10-03 17:37:57710INSTANTIATE_TEST_SUITE_P(VersionIncludeStreamDependencySequence,
711 QuicHttpStreamTest,
712 ::testing::ValuesIn(GetTestParams()),
713 ::testing::PrintToStringParamName());
[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;
Renjie Tangaadb84b2019-08-31 01:00:23739 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:25740 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:23741 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:37742 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23743 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
744 kIncludeVersion, kFin, DEFAULT_PRIORITY,
745 &spdy_request_header_frame_length));
fayang3bcb8b502016-12-07 21:44:37746
[email protected]f702d572012-12-04 15:56:20747 Initialize();
748
749 request_.method = "GET";
rchcd379012017-04-12 21:53:32750 request_.url = GURL("https://www.example.org/");
[email protected]f702d572012-12-04 15:56:20751
xunjieli100937eb52016-09-15 20:09:37752 // Make sure getting load timing from the stream early does not crash.
753 LoadTimingInfo load_timing_info;
754 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
755
xunjieli5fafe142016-03-23 23:32:54756 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27757 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:54758 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:02759 EXPECT_EQ(OK,
760 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20761
762 // Ack the request.
Renjie90e808e2019-01-24 07:24:04763 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]f702d572012-12-04 15:56:20764
robpercival214763f2016-07-01 23:27:01765 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
766 IsError(ERR_IO_PENDING));
[email protected]f702d572012-12-04 15:56:20767
bnc614a92d32016-04-04 13:56:07768 SetResponse("404 Not Found", string());
sclittlec4dc1a32015-09-24 00:15:45769 size_t spdy_response_header_frame_length;
770 ProcessPacket(ConstructResponseHeadersPacket(
771 2, kFin, &spdy_response_header_frame_length));
[email protected]f702d572012-12-04 15:56:20772
773 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:01774 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]cadac622013-06-11 16:46:36775 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:20776 EXPECT_EQ(404, response_.headers->response_code());
777 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
[email protected]6ed67432014-06-24 01:53:53778 EXPECT_FALSE(response_.response_time.is_null());
779 EXPECT_FALSE(response_.request_time.is_null());
[email protected]f702d572012-12-04 15:56:20780
781 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:02782 EXPECT_EQ(0,
783 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
784 callback_.callback()));
[email protected]f702d572012-12-04 15:56:20785 EXPECT_TRUE(stream_->IsResponseBodyComplete());
786 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:10787
xunjieli100937eb52016-09-15 20:09:37788 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
xunjieli84adaab2016-09-20 01:12:28789 ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
xunjieli100937eb52016-09-15 20:09:37790
sclittle1edeeb22015-09-02 20:46:10791 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:45792 // headers and payload.
793 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
794 stream_->GetTotalSentBytes());
795 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length),
796 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:20797}
798
xunjieli100937eb52016-09-15 20:09:37799TEST_P(QuicHttpStreamTest, LoadTimingTwoRequests) {
800 SetRequest("GET", "/", DEFAULT_PRIORITY);
801 size_t spdy_request_header_frame_length;
802
Renjie Tangaadb84b2019-08-31 01:00:23803 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:25804 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:23805 AddWrite(ConstructInitialSettingsPacket(packet_number++));
xunjieli100937eb52016-09-15 20:09:37806 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23807 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
808 kIncludeVersion, kFin, DEFAULT_PRIORITY,
809 &spdy_request_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37810
811 // SetRequest() again for second request as |request_headers_| was moved.
812 SetRequest("GET", "/", DEFAULT_PRIORITY);
813 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23814 packet_number++, GetNthClientInitiatedBidirectionalStreamId(1),
815 kIncludeVersion, kFin, DEFAULT_PRIORITY,
816 GetNthClientInitiatedBidirectionalStreamId(0),
Ryan Hamilton0d65a8c2019-06-07 00:46:02817 &spdy_request_header_frame_length));
Renjie Tangcd594f32020-07-11 20:18:34818 AddWrite(
819 ConstructClientAckPacket(packet_number++, 3, 1)); // Ack the responses.
xunjieli100937eb52016-09-15 20:09:37820
821 Initialize();
822
823 request_.method = "GET";
rchcd379012017-04-12 21:53:32824 request_.url = GURL("https://www.example.org/");
xunjieli100937eb52016-09-15 20:09:37825 // Start first request.
826 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27827 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli100937eb52016-09-15 20:09:37828 net_log_.bound(), callback_.callback()));
829 EXPECT_EQ(OK,
830 stream_->SendRequest(headers_, &response_, callback_.callback()));
831
832 // Start a second request.
Ryan Hamilton6c2a2a82017-12-15 02:06:28833 QuicHttpStream stream2(
Cammie Smith Barnes0f38aff2021-03-02 23:14:35834 session_->CreateHandle(HostPortPair("www.example.org", 443)),
835 {} /* dns_aliases */);
xunjieli100937eb52016-09-15 20:09:37836 TestCompletionCallback callback2;
837 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27838 stream2.InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli100937eb52016-09-15 20:09:37839 net_log_.bound(), callback2.callback()));
840 EXPECT_EQ(OK,
841 stream2.SendRequest(headers_, &response_, callback2.callback()));
842
843 // Ack both requests.
Renjie90e808e2019-01-24 07:24:04844 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
xunjieli100937eb52016-09-15 20:09:37845
846 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
847 IsError(ERR_IO_PENDING));
848 size_t spdy_response_header_frame_length;
849 SetResponse("200 OK", string());
850 ProcessPacket(InnerConstructResponseHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33851 2, GetNthClientInitiatedBidirectionalStreamId(0), kFin,
ckrasicbf2f59c2017-05-04 23:54:36852 &spdy_response_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37853
854 // Now that the headers have been processed, the callback will return.
855 EXPECT_THAT(callback_.WaitForResult(), IsOk());
856 EXPECT_EQ(200, response_.headers->response_code());
857
858 // There is no body, so this should return immediately.
859 EXPECT_EQ(0,
860 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
861 callback_.callback()));
862 EXPECT_TRUE(stream_->IsResponseBodyComplete());
863
864 LoadTimingInfo load_timing_info;
865 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
xunjieli84adaab2016-09-20 01:12:28866 ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
xunjieli100937eb52016-09-15 20:09:37867
868 // SetResponse() again for second request as |response_headers_| was moved.
869 SetResponse("200 OK", string());
870 EXPECT_THAT(stream2.ReadResponseHeaders(callback2.callback()),
871 IsError(ERR_IO_PENDING));
872
873 ProcessPacket(InnerConstructResponseHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33874 3, GetNthClientInitiatedBidirectionalStreamId(1), kFin,
ckrasicbf2f59c2017-05-04 23:54:36875 &spdy_response_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37876
877 EXPECT_THAT(callback2.WaitForResult(), IsOk());
878
879 // There is no body, so this should return immediately.
880 EXPECT_EQ(0,
881 stream2.ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
882 callback2.callback()));
883 EXPECT_TRUE(stream2.IsResponseBodyComplete());
884
885 LoadTimingInfo load_timing_info2;
886 EXPECT_TRUE(stream2.GetLoadTimingInfo(&load_timing_info2));
xunjieli84adaab2016-09-20 01:12:28887 ExpectLoadTimingValid(load_timing_info2, /*session_reused=*/true);
xunjieli100937eb52016-09-15 20:09:37888}
889
xunjieli34291fe12016-03-02 13:58:38890// QuicHttpStream does not currently support trailers. It should ignore
891// trailers upon receiving them.
892TEST_P(QuicHttpStreamTest, GetRequestWithTrailers) {
893 SetRequest("GET", "/", DEFAULT_PRIORITY);
894 size_t spdy_request_header_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:23895 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:25896 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:23897 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:37898 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23899 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
900 kIncludeVersion, kFin, DEFAULT_PRIORITY,
901 &spdy_request_header_frame_length));
Renjie Tangcd594f32020-07-11 20:18:34902 AddWrite(
903 ConstructClientAckPacket(packet_number++, 3, 1)); // Ack the data packet.
xunjieli34291fe12016-03-02 13:58:38904
905 Initialize();
906
907 request_.method = "GET";
rchcd379012017-04-12 21:53:32908 request_.url = GURL("https://www.example.org/");
xunjieli34291fe12016-03-02 13:58:38909
xunjieli5fafe142016-03-23 23:32:54910 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27911 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:54912 net_log_.bound(), callback_.callback()));
913
xunjieli34291fe12016-03-02 13:58:38914 EXPECT_EQ(OK,
915 stream_->SendRequest(headers_, &response_, callback_.callback()));
xunjieli34291fe12016-03-02 13:58:38916 // Ack the request.
Renjie90e808e2019-01-24 07:24:04917 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
xunjieli34291fe12016-03-02 13:58:38918
robpercival214763f2016-07-01 23:27:01919 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
920 IsError(ERR_IO_PENDING));
xunjieli34291fe12016-03-02 13:58:38921
bnc614a92d32016-04-04 13:56:07922 SetResponse("200 OK", string());
xunjieli34291fe12016-03-02 13:58:38923
924 // Send the response headers.
925 size_t spdy_response_header_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:02926 ProcessPacket(ConstructResponseHeadersPacket(
927 2, !kFin, &spdy_response_header_frame_length));
xunjieli34291fe12016-03-02 13:58:38928 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:01929 EXPECT_THAT(callback_.WaitForResult(), IsOk());
xunjieli34291fe12016-03-02 13:58:38930 ASSERT_TRUE(response_.headers.get());
931 EXPECT_EQ(200, response_.headers->response_code());
932 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
933 EXPECT_FALSE(response_.response_time.is_null());
934 EXPECT_FALSE(response_.request_time.is_null());
935
936 // Send the response body.
937 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:43938 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:17939 ProcessPacket(
940 ConstructServerDataPacket(3, false, !kFin, header + kResponseBody));
Bence Béky4c325e52020-10-22 20:48:01941 spdy::Http2HeaderBlock trailers;
xunjieli34291fe12016-03-02 13:58:38942 size_t spdy_trailers_frame_length;
943 trailers["foo"] = "bar";
Victor Vasiliev7da08172019-10-14 06:04:25944 if (!quic::VersionUsesHttp3(version_.transport_version)) {
Ryan Hamiltona1d1f4a2019-06-26 14:43:04945 trailers[quic::kFinalOffsetHeaderKey] =
946 base::NumberToString(strlen(kResponseBody) + header.length());
947 }
Ryan Hamilton0d65a8c2019-06-07 00:46:02948 ProcessPacket(ConstructResponseTrailersPacket(4, kFin, std::move(trailers),
949 &spdy_trailers_frame_length));
xunjieli34291fe12016-03-02 13:58:38950
951 // Make sure trailers are processed.
fdoray92e35a72016-06-10 15:54:55952 base::RunLoop().RunUntilIdle();
xunjieli34291fe12016-03-02 13:58:38953
954 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
955 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
956 callback_.callback()));
957 EXPECT_TRUE(stream_->IsResponseBodyComplete());
958
959 EXPECT_EQ(OK,
960 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
961 callback_.callback()));
962
963 EXPECT_TRUE(stream_->IsResponseBodyComplete());
964 EXPECT_TRUE(AtEof());
965
966 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
967 // headers and payload.
968 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
969 stream_->GetTotalSentBytes());
Renjief49758b2019-01-11 23:32:41970 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length +
971 strlen(kResponseBody) + header.length() +
972 +spdy_trailers_frame_length),
973 stream_->GetTotalReceivedBytes());
xunjieli5fafe142016-03-23 23:32:54974 // Check that NetLog was filled as expected.
Eric Roman79cc7552019-07-19 02:17:54975 auto entries = net_log_.GetEntries();
xunjieli5fafe142016-03-23 23:32:54976 size_t pos = ExpectLogContainsSomewhere(
977 entries, /*min_offset=*/0,
mikecirone8b85c432016-09-08 19:11:00978 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
979 NetLogEventPhase::NONE);
xunjieli5fafe142016-03-23 23:32:54980 pos = ExpectLogContainsSomewhere(
981 entries, /*min_offset=*/pos,
mikecirone8b85c432016-09-08 19:11:00982 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
983 NetLogEventPhase::NONE);
xunjieli5fafe142016-03-23 23:32:54984 ExpectLogContainsSomewhere(
985 entries, /*min_offset=*/pos,
mikecirone8b85c432016-09-08 19:11:00986 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
987 NetLogEventPhase::NONE);
xunjieli34291fe12016-03-02 13:58:38988}
989
Bence Béky6c2c78f2020-08-28 16:49:06990TEST_P(QuicHttpStreamTest, ElideHeadersInNetLog) {
991 Initialize();
992
993 // QuicHttp3Logger is only used with HTTP/3.
994 if (!VersionUsesHttp3(version_.transport_version)) {
995 return;
996 }
997
998 net_log_.SetObserverCaptureMode(NetLogCaptureMode::kDefault);
999
Bence Békye0d3747d2020-08-28 23:16:401000 // Send first request.
Bence Béky6c2c78f2020-08-28 16:49:061001 SetRequest("GET", "/", DEFAULT_PRIORITY);
1002 request_.method = "GET";
1003 request_.url = GURL("https://www.example.org/");
1004 headers_.SetHeader(HttpRequestHeaders::kCookie, "secret");
1005
1006 size_t spdy_request_header_frame_length;
Bence Békye0d3747d2020-08-28 23:16:401007 int outgoing_packet_number = 1;
1008 AddWrite(ConstructInitialSettingsPacket(outgoing_packet_number++));
Bence Béky6c2c78f2020-08-28 16:49:061009 AddWrite(InnerConstructRequestHeadersPacket(
Bence Békye0d3747d2020-08-28 23:16:401010 outgoing_packet_number++, stream_id_, kIncludeVersion, kFin,
1011 DEFAULT_PRIORITY, &spdy_request_header_frame_length));
Bence Béky6c2c78f2020-08-28 16:49:061012
1013 EXPECT_THAT(stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
1014 net_log_.bound(), callback_.callback()),
1015 IsOk());
1016 EXPECT_THAT(stream_->SendRequest(headers_, &response_, callback_.callback()),
1017 IsOk());
Bence Békye0d3747d2020-08-28 23:16:401018 int incoming_packet_number = 1;
1019 ProcessPacket(ConstructServerAckPacket(incoming_packet_number++, 1, 1,
1020 1)); // Ack the request.
Bence Béky6c2c78f2020-08-28 16:49:061021
Bence Békye0d3747d2020-08-28 23:16:401022 // Process first response.
Bence Béky6c2c78f2020-08-28 16:49:061023 SetResponse("200 OK", string());
1024 response_headers_["set-cookie"] = "secret";
1025 size_t spdy_response_header_frame_length;
1026 ProcessPacket(ConstructResponseHeadersPacket(
Bence Békye0d3747d2020-08-28 23:16:401027 incoming_packet_number++, kFin, &spdy_response_header_frame_length));
Bence Béky6c2c78f2020-08-28 16:49:061028 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
Bence Béky6c2c78f2020-08-28 16:49:061029
1030 ASSERT_TRUE(response_.headers.get());
1031 EXPECT_EQ(200, response_.headers->response_code());
1032 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1033 EXPECT_TRUE(response_.headers->HasHeaderValue("set-cookie", "secret"));
1034
Bence Békye0d3747d2020-08-28 23:16:401035 net_log_.SetObserverCaptureMode(NetLogCaptureMode::kIncludeSensitive);
Bence Béky6c2c78f2020-08-28 16:49:061036
Bence Békye0d3747d2020-08-28 23:16:401037 // Send second request.
1038 quic::QuicStreamId stream_id = GetNthClientInitiatedBidirectionalStreamId(1);
1039 request_.url = GURL("https://www.example.org/foo");
Bence Béky6c2c78f2020-08-28 16:49:061040
Bence Békye0d3747d2020-08-28 23:16:401041 AddWrite(InnerConstructRequestHeadersPacket(
1042 outgoing_packet_number++, stream_id, kIncludeVersion, kFin,
1043 DEFAULT_PRIORITY, &spdy_request_header_frame_length));
Bence Béky6c2c78f2020-08-28 16:49:061044
Bence Békye0d3747d2020-08-28 23:16:401045 auto stream = std::make_unique<QuicHttpStream>(
Cammie Smith Barnes0f38aff2021-03-02 23:14:351046 session_->CreateHandle(HostPortPair("www.example.org/foo", 443)),
1047 std::vector<std::string>() /* dns_aliases */);
Bence Békye0d3747d2020-08-28 23:16:401048 EXPECT_THAT(stream->InitializeStream(&request_, true, DEFAULT_PRIORITY,
1049 net_log_.bound(), callback_.callback()),
1050 IsOk());
1051 EXPECT_THAT(stream->SendRequest(headers_, &response_, callback_.callback()),
1052 IsOk());
1053 ProcessPacket(ConstructServerAckPacket(incoming_packet_number++, 1, 1,
1054 1)); // Ack the request.
Bence Béky6c2c78f2020-08-28 16:49:061055
Bence Békye0d3747d2020-08-28 23:16:401056 // Process second response.
1057 SetResponse("200 OK", string());
1058 response_headers_["set-cookie"] = "secret";
1059 ProcessPacket(InnerConstructResponseHeadersPacket(
1060 incoming_packet_number++, stream_id, kFin,
1061 &spdy_response_header_frame_length));
1062 EXPECT_THAT(stream->ReadResponseHeaders(callback_.callback()), IsOk());
Bence Béky6c2c78f2020-08-28 16:49:061063
Bence Békye0d3747d2020-08-28 23:16:401064 ASSERT_TRUE(response_.headers.get());
1065 EXPECT_EQ(200, response_.headers->response_code());
1066 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1067 EXPECT_TRUE(response_.headers->HasHeaderValue("set-cookie", "secret"));
1068
1069 EXPECT_TRUE(AtEof());
1070
1071 // Check that sensitive header value were stripped
1072 // for the first transaction (logged with NetLogCaptureMode::kDefault)
1073 // but not for the second (logged with NetLogCaptureMode::kIncludeSensitive).
1074 auto entries =
1075 net_log_.GetEntriesWithType(NetLogEventType::HTTP3_HEADERS_SENT);
1076 ASSERT_EQ(2u, entries.size());
1077 EXPECT_TRUE(
1078 CheckHeader(entries[0].params, "cookie", "[6 bytes were stripped]"));
1079 EXPECT_TRUE(CheckHeader(entries[1].params, "cookie", "secret"));
1080
1081 entries = net_log_.GetEntriesWithType(NetLogEventType::HTTP3_HEADERS_DECODED);
1082 ASSERT_EQ(2u, entries.size());
1083 EXPECT_TRUE(
1084 CheckHeader(entries[0].params, "set-cookie", "[6 bytes were stripped]"));
1085 EXPECT_TRUE(CheckHeader(entries[1].params, "set-cookie", "secret"));
Bence Béky6c2c78f2020-08-28 16:49:061086}
1087
[email protected]3e7dca62013-09-10 16:14:231088// Regression test for http://crbug.com/288128
[email protected]1e960032013-12-20 19:00:201089TEST_P(QuicHttpStreamTest, GetRequestLargeResponse) {
1090 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451091 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231092 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251093 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231094 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371095 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231096 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1097 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1098 &spdy_request_headers_frame_length));
[email protected]3e7dca62013-09-10 16:14:231099 Initialize();
1100
1101 request_.method = "GET";
rchcd379012017-04-12 21:53:321102 request_.url = GURL("https://www.example.org/");
[email protected]3e7dca62013-09-10 16:14:231103
xunjieli5fafe142016-03-23 23:32:541104 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271105 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541106 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021107 EXPECT_EQ(OK,
1108 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:231109
1110 // Ack the request.
Renjie90e808e2019-01-24 07:24:041111 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]3e7dca62013-09-10 16:14:231112
robpercival214763f2016-07-01 23:27:011113 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1114 IsError(ERR_IO_PENDING));
[email protected]3e7dca62013-09-10 16:14:231115
bnc086b39e12016-06-24 13:05:261116 response_headers_[":status"] = "200 OK";
1117 response_headers_[":version"] = "HTTP/1.1";
1118 response_headers_["content-type"] = "text/plain";
1119 response_headers_["big6"] = string(1000, 'x'); // Lots of x's.
[email protected]3e7dca62013-09-10 16:14:231120
sclittlec4dc1a32015-09-24 00:15:451121 size_t spdy_response_headers_frame_length;
1122 ProcessPacket(ConstructResponseHeadersPacket(
1123 2, kFin, &spdy_response_headers_frame_length));
[email protected]3e7dca62013-09-10 16:14:231124
1125 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:011126 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]3e7dca62013-09-10 16:14:231127 ASSERT_TRUE(response_.headers.get());
1128 EXPECT_EQ(200, response_.headers->response_code());
1129 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1130
1131 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:021132 EXPECT_EQ(0,
1133 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1134 callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:231135 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1136 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101137
1138 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451139 // headers and payload.
1140 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1141 stream_->GetTotalSentBytes());
1142 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length),
1143 stream_->GetTotalReceivedBytes());
[email protected]3e7dca62013-09-10 16:14:231144}
1145
rchf9f103cbc2014-08-30 05:28:041146// Regression test for http://crbug.com/409101
1147TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendRequest) {
1148 SetRequest("GET", "/", DEFAULT_PRIORITY);
1149 Initialize();
1150
1151 request_.method = "GET";
rchcd379012017-04-12 21:53:321152 request_.url = GURL("https://www.example.org/");
rchf9f103cbc2014-08-30 05:28:041153
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()));
rchf9f103cbc2014-08-30 05:28:041157
jri78ec06a2016-03-31 18:19:401158 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521159 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rchf9f103cbc2014-08-30 05:28:041160
1161 EXPECT_EQ(ERR_CONNECTION_CLOSED,
rjshaded5ced072015-12-18 19:26:021162 stream_->SendRequest(headers_, &response_, callback_.callback()));
sclittle1edeeb22015-09-02 20:46:101163
1164 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1165 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rchf9f103cbc2014-08-30 05:28:041166}
1167
rch03b7a202016-02-05 00:54:201168// Regression test for http://crbug.com/584441
1169TEST_P(QuicHttpStreamTest, GetSSLInfoAfterSessionClosed) {
1170 SetRequest("GET", "/", DEFAULT_PRIORITY);
1171 Initialize();
1172
1173 request_.method = "GET";
rchcd379012017-04-12 21:53:321174 request_.url = GURL("https://www.example.org/");
rch03b7a202016-02-05 00:54:201175
xunjieli5fafe142016-03-23 23:32:541176 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271177 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541178 net_log_.bound(), callback_.callback()));
rch03b7a202016-02-05 00:54:201179
1180 SSLInfo ssl_info;
rch11565e02016-02-09 20:13:471181 EXPECT_FALSE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:201182 stream_->GetSSLInfo(&ssl_info);
rch11565e02016-02-09 20:13:471183 EXPECT_TRUE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:201184
jri78ec06a2016-03-31 18:19:401185 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521186 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rch03b7a202016-02-05 00:54:201187
rch11565e02016-02-09 20:13:471188 SSLInfo ssl_info2;
1189 stream_->GetSSLInfo(&ssl_info2);
1190 EXPECT_TRUE(ssl_info2.is_valid());
rch03b7a202016-02-05 00:54:201191}
1192
rchcd379012017-04-12 21:53:321193TEST_P(QuicHttpStreamTest, GetAlternativeService) {
1194 SetRequest("GET", "/", DEFAULT_PRIORITY);
1195 Initialize();
1196
1197 request_.method = "GET";
1198 request_.url = GURL("https://www.example.org/");
1199
1200 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271201 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
rchcd379012017-04-12 21:53:321202 net_log_.bound(), callback_.callback()));
1203
1204 AlternativeService alternative_service;
1205 EXPECT_TRUE(stream_->GetAlternativeService(&alternative_service));
1206 EXPECT_EQ(AlternativeService(kProtoQUIC, "www.example.org", 443),
1207 alternative_service);
1208
1209 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521210 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rchcd379012017-04-12 21:53:321211
1212 AlternativeService alternative_service2;
1213 EXPECT_TRUE(stream_->GetAlternativeService(&alternative_service2));
1214 EXPECT_EQ(AlternativeService(kProtoQUIC, "www.example.org", 443),
1215 alternative_service2);
1216}
1217
zhongyica364fbb2015-12-12 03:39:121218TEST_P(QuicHttpStreamTest, LogGranularQuicConnectionError) {
1219 SetRequest("GET", "/", DEFAULT_PRIORITY);
1220 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231221 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251222 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231223 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371224 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231225 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1226 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1227 &spdy_request_headers_frame_length));
fayang3bcb8b502016-12-07 21:44:371228 AddWrite(ConstructAckAndRstStreamPacket(3));
zhongyica364fbb2015-12-12 03:39:121229 Initialize();
1230
1231 request_.method = "GET";
rchcd379012017-04-12 21:53:321232 request_.url = GURL("https://www.example.org/");
zhongyica364fbb2015-12-12 03:39:121233
xunjieli5fafe142016-03-23 23:32:541234 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271235 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541236 net_log_.bound(), callback_.callback()));
zhongyica364fbb2015-12-12 03:39:121237 EXPECT_EQ(OK,
1238 stream_->SendRequest(headers_, &response_, callback_.callback()));
1239
1240 // Ack the request.
Renjie90e808e2019-01-24 07:24:041241 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011242 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1243 IsError(ERR_IO_PENDING));
zhongyica364fbb2015-12-12 03:39:121244
Ryan Hamilton8d9ee76e2018-05-29 23:52:521245 quic::QuicConnectionCloseFrame frame;
Zhongyi Shica576df2019-04-12 17:43:401246 frame.quic_error_code = quic::QUIC_PEER_GOING_AWAY;
rch1c5b74a2016-06-23 22:10:551247 session_->connection()->OnConnectionCloseFrame(frame);
zhongyica364fbb2015-12-12 03:39:121248
1249 NetErrorDetails details;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521250 EXPECT_EQ(quic::QUIC_NO_ERROR, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121251 stream_->PopulateNetErrorDetails(&details);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521252 EXPECT_EQ(quic::QUIC_PEER_GOING_AWAY, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121253}
1254
Ryan Hamiltone316e482017-08-17 02:48:531255TEST_P(QuicHttpStreamTest, LogGranularQuicErrorIfHandshakeNotConfirmed) {
rch617e0652017-04-26 17:57:511256 // By default the test setup defaults handshake to be confirmed. Manually set
1257 // it to be not confirmed.
rch617e0652017-04-26 17:57:511258 crypto_client_stream_factory_.set_handshake_mode(
Ryan Hamilton9835e662018-08-02 05:36:271259 MockCryptoClientStream::ZERO_RTT);
rch617e0652017-04-26 17:57:511260
zhongyica364fbb2015-12-12 03:39:121261 SetRequest("GET", "/", DEFAULT_PRIORITY);
1262 size_t spdy_request_headers_frame_length;
Michael Warres167db3e2019-03-01 21:38:031263 client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
Nick Harper057264a82019-09-12 23:33:491264 client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
1265 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251266 if (VersionUsesHttp3(version_.transport_version))
Nick Harper057264a82019-09-12 23:33:491267 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371268 AddWrite(InnerConstructRequestHeadersPacket(
Nick Harper057264a82019-09-12 23:33:491269 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1270 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1271 &spdy_request_headers_frame_length));
zhongyica364fbb2015-12-12 03:39:121272 Initialize();
1273
1274 request_.method = "GET";
rchcd379012017-04-12 21:53:321275 request_.url = GURL("https://www.example.org/");
zhongyica364fbb2015-12-12 03:39:121276
xunjieli5fafe142016-03-23 23:32:541277 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271278 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541279 net_log_.bound(), callback_.callback()));
zhongyica364fbb2015-12-12 03:39:121280 EXPECT_EQ(OK,
1281 stream_->SendRequest(headers_, &response_, callback_.callback()));
1282
1283 // Ack the request.
Renjie90e808e2019-01-24 07:24:041284 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011285 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1286 IsError(ERR_IO_PENDING));
zhongyica364fbb2015-12-12 03:39:121287
Ryan Hamilton8d9ee76e2018-05-29 23:52:521288 quic::QuicConnectionCloseFrame frame;
Zhongyi Shica576df2019-04-12 17:43:401289 frame.quic_error_code = quic::QUIC_PEER_GOING_AWAY;
rch1c5b74a2016-06-23 22:10:551290 session_->connection()->OnConnectionCloseFrame(frame);
zhongyica364fbb2015-12-12 03:39:121291
1292 NetErrorDetails details;
zhongyica364fbb2015-12-12 03:39:121293 stream_->PopulateNetErrorDetails(&details);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521294 EXPECT_EQ(quic::QUIC_PEER_GOING_AWAY, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121295}
1296
rch11a114a2014-09-04 23:41:591297// Regression test for http://crbug.com/409871
1298TEST_P(QuicHttpStreamTest, SessionClosedBeforeReadResponseHeaders) {
1299 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451300 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231301 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251302 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231303 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371304 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231305 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1306 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1307 &spdy_request_headers_frame_length));
rch11a114a2014-09-04 23:41:591308 Initialize();
1309
1310 request_.method = "GET";
rchcd379012017-04-12 21:53:321311 request_.url = GURL("https://www.example.org/");
rch11a114a2014-09-04 23:41:591312
xunjieli5fafe142016-03-23 23:32:541313 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271314 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541315 net_log_.bound(), callback_.callback()));
rch11a114a2014-09-04 23:41:591316
rjshaded5ced072015-12-18 19:26:021317 EXPECT_EQ(OK,
1318 stream_->SendRequest(headers_, &response_, callback_.callback()));
rch11a114a2014-09-04 23:41:591319
jri78ec06a2016-03-31 18:19:401320 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521321 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rch11a114a2014-09-04 23:41:591322
1323 EXPECT_NE(OK, stream_->ReadResponseHeaders(callback_.callback()));
sclittle1edeeb22015-09-02 20:46:101324
1325 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451326 // headers and payload.
1327 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1328 stream_->GetTotalSentBytes());
sclittle1edeeb22015-09-02 20:46:101329 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rch11a114a2014-09-04 23:41:591330}
1331
[email protected]1e960032013-12-20 19:00:201332TEST_P(QuicHttpStreamTest, SendPostRequest) {
1333 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451334 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231335 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251336 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231337 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Yixin Wange7ecc472018-03-06 19:00:251338
Victor Vasiliev076657c2019-03-12 02:46:431339 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:321340 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411341 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231342 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1343 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1344 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411345 } else {
1346 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231347 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1348 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1349 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411350 }
Yixin Wange7ecc472018-03-06 19:00:251351
Renjie Tangcd594f32020-07-11 20:18:341352 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]f702d572012-12-04 15:56:201353
1354 Initialize();
1355
danakjad1777e2016-04-16 00:56:421356 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:191357 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
ricea2deef682016-09-09 08:04:071358 kUploadData, strlen(kUploadData)));
rch97827ee2017-05-24 23:49:121359 upload_data_stream_ =
Jeremy Roman0579ed62017-08-29 15:56:191360 std::make_unique<ElementsUploadDataStream>(std::move(element_readers), 0);
[email protected]f702d572012-12-04 15:56:201361 request_.method = "POST";
rchcd379012017-04-12 21:53:321362 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121363 request_.upload_data_stream = upload_data_stream_.get();
Bence Békyd8a21fc32018-06-27 18:29:581364 ASSERT_THAT(request_.upload_data_stream->Init(CompletionOnceCallback(),
tfarina42834112016-09-22 13:38:201365 NetLogWithSource()),
1366 IsOk());
[email protected]f702d572012-12-04 15:56:201367
xunjieli5fafe142016-03-23 23:32:541368 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271369 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541370 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021371 EXPECT_EQ(OK,
1372 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:201373
1374 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041375 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]f702d572012-12-04 15:56:201376
1377 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071378 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451379 size_t spdy_response_headers_frame_length;
1380 ProcessPacket(ConstructResponseHeadersPacket(
1381 2, !kFin, &spdy_response_headers_frame_length));
[email protected]f702d572012-12-04 15:56:201382
rchfb47f712017-05-21 03:24:001383 // The headers have already arrived.
1384 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]cadac622013-06-11 16:46:361385 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:201386 EXPECT_EQ(200, response_.headers->response_code());
1387 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1388
1389 // Send the response body.
1390 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431391 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:411392 ProcessPacket(
Ryan Hamilton7505eb92019-06-08 00:22:171393 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
[email protected]f702d572012-12-04 15:56:201394 // Since the body has already arrived, this should return immediately.
1395 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
1396 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1397 callback_.callback()));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291398 EXPECT_EQ(0,
1399 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1400 callback_.callback()));
1401
1402 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1403 EXPECT_TRUE(AtEof());
1404
1405 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
1406 // headers and payload.
1407 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411408 strlen(kUploadData) + header.length()),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291409 stream_->GetTotalSentBytes());
1410 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411411 strlen(kResponseBody) + header2.length()),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291412 stream_->GetTotalReceivedBytes());
1413}
1414
1415TEST_P(QuicHttpStreamTest, SendPostRequestAndReceiveSoloFin) {
1416 SetRequest("POST", "/", DEFAULT_PRIORITY);
1417 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231418 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251419 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231420 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431421 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:321422 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411423 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231424 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1425 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1426 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411427 } else {
1428 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231429 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1430 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1431 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411432 }
1433
Renjie Tangcd594f32020-07-11 20:18:341434 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291435
1436 Initialize();
1437
1438 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:191439 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
Ryan Hamilton2ef0a9c2017-07-25 03:18:291440 kUploadData, strlen(kUploadData)));
1441 upload_data_stream_ =
Jeremy Roman0579ed62017-08-29 15:56:191442 std::make_unique<ElementsUploadDataStream>(std::move(element_readers), 0);
Ryan Hamilton2ef0a9c2017-07-25 03:18:291443 request_.method = "POST";
1444 request_.url = GURL("https://www.example.org/");
1445 request_.upload_data_stream = upload_data_stream_.get();
Bence Békyd8a21fc32018-06-27 18:29:581446 ASSERT_THAT(request_.upload_data_stream->Init(CompletionOnceCallback(),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291447 NetLogWithSource()),
1448 IsOk());
1449
1450 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271451 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
Ryan Hamilton2ef0a9c2017-07-25 03:18:291452 net_log_.bound(), callback_.callback()));
1453 EXPECT_EQ(OK,
1454 stream_->SendRequest(headers_, &response_, callback_.callback()));
1455
1456 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041457 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291458
1459 // Send the response headers (but not the body).
1460 SetResponse("200 OK", string());
1461 size_t spdy_response_headers_frame_length;
1462 ProcessPacket(ConstructResponseHeadersPacket(
1463 2, !kFin, &spdy_response_headers_frame_length));
1464
1465 // The headers have already arrived.
1466 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
1467 ASSERT_TRUE(response_.headers.get());
1468 EXPECT_EQ(200, response_.headers->response_code());
1469 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1470
1471 // Send the response body.
1472 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431473 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:411474 ProcessPacket(
Ryan Hamilton7505eb92019-06-08 00:22:171475 ConstructServerDataPacket(3, false, !kFin, header2 + kResponseBody));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291476 // Since the body has already arrived, this should return immediately.
1477 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
1478 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1479 callback_.callback()));
Ryan Hamilton7505eb92019-06-08 00:22:171480 ProcessPacket(ConstructServerDataPacket(4, false, kFin, ""));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291481 EXPECT_EQ(0,
1482 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1483 callback_.callback()));
[email protected]f702d572012-12-04 15:56:201484
1485 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1486 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101487
1488 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451489 // headers and payload.
1490 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411491 strlen(kUploadData) + header.length()),
sclittle1edeeb22015-09-02 20:46:101492 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451493 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411494 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101495 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:201496}
1497
[email protected]1e960032013-12-20 19:00:201498TEST_P(QuicHttpStreamTest, SendChunkedPostRequest) {
1499 SetRequest("POST", "/", DEFAULT_PRIORITY);
[email protected]c9e49a02013-02-26 05:56:471500 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:451501 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231502 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251503 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231504 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431505 std::string header = ConstructDataHeader(chunk_size);
Nick Harperc6cb7a612020-02-24 20:03:321506 if (version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411507 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231508 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1509 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1510 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjie Tangd5133972019-12-06 00:20:281511 AddWrite(ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin,
1512 {header + kUploadData}));
Renjief49758b2019-01-11 23:32:411513 } else {
1514 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231515 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1516 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1517 &spdy_request_headers_frame_length, {kUploadData}));
1518 AddWrite(ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin,
1519 kUploadData));
Renjief49758b2019-01-11 23:32:411520 }
1521
Renjie Tangcd594f32020-07-11 20:18:341522 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]c9e49a02013-02-26 05:56:471523 Initialize();
1524
Jeremy Roman0579ed62017-08-29 15:56:191525 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121526 auto* chunked_upload_stream =
1527 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1528 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
[email protected]c9e49a02013-02-26 05:56:471529
1530 request_.method = "POST";
rchcd379012017-04-12 21:53:321531 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121532 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071533 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201534 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]c9e49a02013-02-26 05:56:471535
xunjieli5fafe142016-03-23 23:32:541536 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271537 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541538 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021539 ASSERT_EQ(ERR_IO_PENDING,
1540 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]c9e49a02013-02-26 05:56:471541
rch97827ee2017-05-24 23:49:121542 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
robpercival214763f2016-07-01 23:27:011543 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]c9e49a02013-02-26 05:56:471544
1545 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041546 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]c9e49a02013-02-26 05:56:471547
1548 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071549 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451550 size_t spdy_response_headers_frame_length;
1551 ProcessPacket(ConstructResponseHeadersPacket(
1552 2, !kFin, &spdy_response_headers_frame_length));
[email protected]c9e49a02013-02-26 05:56:471553
rchfb47f712017-05-21 03:24:001554 // The headers have already arrived.
1555 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]cadac622013-06-11 16:46:361556 ASSERT_TRUE(response_.headers.get());
[email protected]c9e49a02013-02-26 05:56:471557 EXPECT_EQ(200, response_.headers->response_code());
1558 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1559
1560 // Send the response body.
1561 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431562 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171563 ProcessPacket(
1564 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
[email protected]c9e49a02013-02-26 05:56:471565
1566 // Since the body has already arrived, this should return immediately.
1567 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1568 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1569 callback_.callback()));
1570
1571 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1572 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101573
1574 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451575 // headers and payload.
1576 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411577 strlen(kUploadData) * 2 + header.length() * 2),
sclittle1edeeb22015-09-02 20:46:101578 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451579 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411580 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101581 stream_->GetTotalReceivedBytes());
[email protected]c9e49a02013-02-26 05:56:471582}
1583
[email protected]16ba7742014-08-22 00:57:251584TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithFinalEmptyDataPacket) {
1585 SetRequest("POST", "/", DEFAULT_PRIORITY);
1586 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:451587 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231588 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251589 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231590 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431591 std::string header = ConstructDataHeader(chunk_size);
Renjief49758b2019-01-11 23:32:411592
Nick Harperc6cb7a612020-02-24 20:03:321593 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411594 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231595 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1596 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1597 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411598 } else {
1599 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231600 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1601 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1602 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411603 }
Renjie Tangaadb84b2019-08-31 01:00:231604 AddWrite(
1605 ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin, ""));
Renjie Tangcd594f32020-07-11 20:18:341606 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]16ba7742014-08-22 00:57:251607 Initialize();
1608
Jeremy Roman0579ed62017-08-29 15:56:191609 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121610 auto* chunked_upload_stream =
1611 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1612 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
[email protected]16ba7742014-08-22 00:57:251613
1614 request_.method = "POST";
rchcd379012017-04-12 21:53:321615 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121616 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071617 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201618 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]16ba7742014-08-22 00:57:251619
xunjieli5fafe142016-03-23 23:32:541620 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271621 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541622 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021623 ASSERT_EQ(ERR_IO_PENDING,
1624 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251625
rch97827ee2017-05-24 23:49:121626 chunked_upload_stream->AppendData(nullptr, 0, true);
robpercival214763f2016-07-01 23:27:011627 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]16ba7742014-08-22 00:57:251628
Renjie90e808e2019-01-24 07:24:041629 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]16ba7742014-08-22 00:57:251630
1631 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071632 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451633 size_t spdy_response_headers_frame_length;
1634 ProcessPacket(ConstructResponseHeadersPacket(
1635 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251636
rchfb47f712017-05-21 03:24:001637 // The headers have already arrived.
1638 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]16ba7742014-08-22 00:57:251639 ASSERT_TRUE(response_.headers.get());
1640 EXPECT_EQ(200, response_.headers->response_code());
1641 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1642
1643 // Send the response body.
1644 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431645 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171646 ProcessPacket(
1647 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
[email protected]16ba7742014-08-22 00:57:251648
rchb27683c2015-07-29 23:53:501649 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251650 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1651 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1652 callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251653 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1654 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101655
1656 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451657 // headers and payload.
1658 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411659 strlen(kUploadData) + header.length()),
sclittle1edeeb22015-09-02 20:46:101660 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451661 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411662 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101663 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251664}
1665
1666TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithOneEmptyDataPacket) {
1667 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451668 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231669 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251670 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231671 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371672 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231673 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1674 kIncludeVersion, !kFin, DEFAULT_PRIORITY,
1675 &spdy_request_headers_frame_length));
1676 AddWrite(
1677 ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin, ""));
Renjie Tangcd594f32020-07-11 20:18:341678 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]16ba7742014-08-22 00:57:251679 Initialize();
1680
Jeremy Roman0579ed62017-08-29 15:56:191681 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121682 auto* chunked_upload_stream =
1683 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
[email protected]16ba7742014-08-22 00:57:251684
1685 request_.method = "POST";
rchcd379012017-04-12 21:53:321686 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121687 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071688 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201689 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]16ba7742014-08-22 00:57:251690
xunjieli5fafe142016-03-23 23:32:541691 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271692 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541693 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021694 ASSERT_EQ(ERR_IO_PENDING,
1695 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251696
rch97827ee2017-05-24 23:49:121697 chunked_upload_stream->AppendData(nullptr, 0, true);
robpercival214763f2016-07-01 23:27:011698 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]16ba7742014-08-22 00:57:251699
Renjie90e808e2019-01-24 07:24:041700 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]16ba7742014-08-22 00:57:251701
1702 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071703 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451704 size_t spdy_response_headers_frame_length;
1705 ProcessPacket(ConstructResponseHeadersPacket(
1706 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251707
rchfb47f712017-05-21 03:24:001708 // The headers have already arrived.
1709 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]16ba7742014-08-22 00:57:251710 ASSERT_TRUE(response_.headers.get());
1711 EXPECT_EQ(200, response_.headers->response_code());
1712 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1713
1714 // Send the response body.
1715 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431716 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171717 ProcessPacket(
1718 ConstructServerDataPacket(3, false, kFin, header + kResponseBody));
[email protected]16ba7742014-08-22 00:57:251719
rchb27683c2015-07-29 23:53:501720 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251721 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1722 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1723 callback_.callback()));
1724
1725 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1726 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101727
1728 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451729 // headers and payload.
1730 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1731 stream_->GetTotalSentBytes());
1732 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411733 strlen(kResponseBody) + header.length()),
sclittle1edeeb22015-09-02 20:46:101734 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251735}
1736
Bence Békye3c6f122020-05-08 01:09:471737TEST_P(QuicHttpStreamTest, SendChunkedPostRequestAbortedByResetStream) {
1738 SetRequest("POST", "/", DEFAULT_PRIORITY);
1739 size_t chunk_size = strlen(kUploadData);
1740 size_t spdy_request_headers_frame_length;
1741 int packet_number = 1;
1742
1743 if (version_.UsesHttp3()) {
1744 AddWrite(ConstructInitialSettingsPacket(packet_number++));
1745 }
1746
1747 std::string header = ConstructDataHeader(chunk_size);
1748 if (version_.HasIetfQuicFrames()) {
1749 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1750 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1751 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1752 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjie Tangcd594f32020-07-11 20:18:341753 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
Renjie Tanga35322a2020-12-02 20:12:271754 AddWrite(client_maker_.MakeRstPacket(
1755 packet_number++, true, stream_id_, quic::QUIC_STREAM_NO_ERROR,
Renjie Tangcd594f32020-07-11 20:18:341756 /* include_stop_sending_if_v99 = */ false));
Bence Békye3c6f122020-05-08 01:09:471757 } else {
1758 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1759 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1760 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1761 &spdy_request_headers_frame_length, {kUploadData}));
Renjie Tangcd594f32020-07-11 20:18:341762 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
Bence Békye3c6f122020-05-08 01:09:471763 AddWrite(client_maker_.MakeAckAndRstPacket(
1764 packet_number++,
1765 /* include_version = */ false, stream_id_,
Renjie Tangcd594f32020-07-11 20:18:341766 quic::QUIC_RST_ACKNOWLEDGEMENT, 4, 1,
Bence Békye3c6f122020-05-08 01:09:471767 /* include_stop_sending_if_v99 = */ false));
1768 }
1769
1770 Initialize();
1771
1772 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
1773 auto* chunked_upload_stream =
1774 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1775 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
1776
1777 request_.method = "POST";
1778 request_.url = GURL("https://www.example.org/");
1779 request_.upload_data_stream = upload_data_stream_.get();
1780 ASSERT_THAT(request_.upload_data_stream->Init(
1781 TestCompletionCallback().callback(), NetLogWithSource()),
1782 IsOk());
1783 ASSERT_THAT(stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1784 net_log_.bound(), callback_.callback()),
1785 IsOk());
1786 ASSERT_THAT(stream_->SendRequest(headers_, &response_, callback_.callback()),
1787 IsError(ERR_IO_PENDING));
1788
1789 // Ack both packets in the request.
1790 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
1791
1792 // Send the response headers (but not the body).
1793 SetResponse("200 OK", string());
1794 size_t spdy_response_headers_frame_length;
1795 ProcessPacket(ConstructResponseHeadersPacket(
1796 2, !kFin, &spdy_response_headers_frame_length));
1797
1798 // Send the response body.
1799 const char kResponseBody[] = "Hello world!";
1800 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
1801 ProcessPacket(
1802 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
1803
Bence Béky050ec6d2021-02-25 22:07:051804 if (version_.HasIetfQuicFrames()) {
1805 // In IETF QUIC, the server uses a STOP_SENDING frame to notify the client
1806 // that it does not need any further data to fully process the request.
1807 ProcessPacket(server_maker_.MakeStopSendingPacket(
1808 4, /* include_version = */ false, stream_id_,
1809 quic::QUIC_STREAM_NO_ERROR));
1810 } else {
1811 // Server resets stream with H3_NO_ERROR before request body is complete.
1812 ProcessPacket(server_maker_.MakeRstPacket(4, /* include_version = */ false,
1813 stream_id_,
1814 quic::QUIC_STREAM_NO_ERROR));
1815 }
Bence Békye3c6f122020-05-08 01:09:471816
1817 // Finish feeding request body to QuicHttpStream. Data will be discarded.
1818 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1819 EXPECT_THAT(callback_.WaitForResult(), IsOk());
1820
1821 // Verify response.
1822 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
1823 ASSERT_TRUE(response_.headers.get());
1824 EXPECT_EQ(200, response_.headers->response_code());
1825 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1826 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1827 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1828 callback_.callback()));
1829 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1830 EXPECT_TRUE(AtEof());
1831
1832 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
1833 // headers and payload.
1834 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
1835 strlen(kUploadData) + header.length()),
1836 stream_->GetTotalSentBytes());
1837 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1838 strlen(kResponseBody) + header2.length()),
1839 stream_->GetTotalReceivedBytes());
1840}
1841
[email protected]1e960032013-12-20 19:00:201842TEST_P(QuicHttpStreamTest, DestroyedEarly) {
1843 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451844 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231845 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251846 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231847 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371848 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231849 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1850 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1851 &spdy_request_headers_frame_length));
1852 AddWrite(ConstructAckAndRstStreamPacket(packet_number++));
[email protected]63534512012-12-23 18:49:001853 Initialize();
1854
1855 request_.method = "GET";
rchcd379012017-04-12 21:53:321856 request_.url = GURL("https://www.example.org/");
[email protected]63534512012-12-23 18:49:001857
xunjieli5fafe142016-03-23 23:32:541858 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271859 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541860 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021861 EXPECT_EQ(OK,
1862 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]63534512012-12-23 18:49:001863
1864 // Ack the request.
Renjie90e808e2019-01-24 07:24:041865 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
rchfb47f712017-05-21 03:24:001866 EXPECT_THAT(stream_->ReadResponseHeaders(
Yannic Bonenberger3c96beb2019-09-03 20:41:371867 base::BindOnce(&QuicHttpStreamTest::CloseStream,
1868 base::Unretained(this), stream_.get())),
robpercival214763f2016-07-01 23:27:011869 IsError(ERR_IO_PENDING));
[email protected]63534512012-12-23 18:49:001870
1871 // Send the response with a body.
[email protected]1e960032013-12-20 19:00:201872 SetResponse("404 OK", "hello world!");
[email protected]63534512012-12-23 18:49:001873 // In the course of processing this packet, the QuicHttpStream close itself.
rchfb47f712017-05-21 03:24:001874 size_t response_size = 0;
rch1bcfddf22017-06-03 00:26:291875 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin, &response_size));
[email protected]63534512012-12-23 18:49:001876
fdoray92e35a72016-06-10 15:54:551877 base::RunLoop().RunUntilIdle();
rchb27683c2015-07-29 23:53:501878
[email protected]63534512012-12-23 18:49:001879 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101880
1881 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451882 // headers and payload.
1883 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1884 stream_->GetTotalSentBytes());
rchfb47f712017-05-21 03:24:001885 // The stream was closed after receiving the headers.
1886 EXPECT_EQ(static_cast<int64_t>(response_size),
1887 stream_->GetTotalReceivedBytes());
[email protected]63534512012-12-23 18:49:001888}
1889
[email protected]1e960032013-12-20 19:00:201890TEST_P(QuicHttpStreamTest, Priority) {
1891 SetRequest("GET", "/", MEDIUM);
sclittlec4dc1a32015-09-24 00:15:451892 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231893 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251894 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231895 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371896 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231897 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1898 kIncludeVersion, kFin, MEDIUM, &spdy_request_headers_frame_length));
[email protected]24e5bc52013-09-18 15:36:581899 Initialize();
1900
1901 request_.method = "GET";
rchcd379012017-04-12 21:53:321902 request_.url = GURL("https://www.example.org/");
[email protected]24e5bc52013-09-18 15:36:581903
Steven Valdezb4ff0412018-01-18 22:39:271904 EXPECT_EQ(OK,
1905 stream_->InitializeStream(&request_, true, MEDIUM, net_log_.bound(),
1906 callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581907
rjshaded5ced072015-12-18 19:26:021908 EXPECT_EQ(OK,
1909 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581910
[email protected]24e5bc52013-09-18 15:36:581911 // Ack the request.
Renjie90e808e2019-01-24 07:24:041912 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011913 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1914 IsError(ERR_IO_PENDING));
[email protected]24e5bc52013-09-18 15:36:581915
1916 // Send the response with a body.
[email protected]1e960032013-12-20 19:00:201917 SetResponse("404 OK", "hello world!");
rchfb47f712017-05-21 03:24:001918 size_t response_size = 0;
1919 ProcessPacket(ConstructResponseHeadersPacket(2, kFin, &response_size));
[email protected]24e5bc52013-09-18 15:36:581920
rchfb47f712017-05-21 03:24:001921 EXPECT_EQ(OK, callback_.WaitForResult());
rchb27683c2015-07-29 23:53:501922
[email protected]24e5bc52013-09-18 15:36:581923 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101924
1925 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451926 // headers and payload.
1927 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1928 stream_->GetTotalSentBytes());
rchfb47f712017-05-21 03:24:001929 EXPECT_EQ(static_cast<int64_t>(response_size),
1930 stream_->GetTotalReceivedBytes());
[email protected]24e5bc52013-09-18 15:36:581931}
1932
xunjieli8dff50b2016-07-22 14:19:061933TEST_P(QuicHttpStreamTest, SessionClosedDuringDoLoop) {
1934 SetRequest("POST", "/", DEFAULT_PRIORITY);
1935 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231936 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251937 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231938 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431939 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:321940 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411941 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231942 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1943 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1944 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411945 } else {
1946 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231947 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1948 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1949 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411950 }
1951
xunjieli8dff50b2016-07-22 14:19:061952 // Second data write will result in a synchronous failure which will close
1953 // the session.
1954 AddWrite(SYNCHRONOUS, ERR_FAILED);
1955 Initialize();
1956
Jeremy Roman0579ed62017-08-29 15:56:191957 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121958 auto* chunked_upload_stream =
1959 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
xunjieli8dff50b2016-07-22 14:19:061960
1961 request_.method = "POST";
rchcd379012017-04-12 21:53:321962 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121963 request_.upload_data_stream = upload_data_stream_.get();
xunjieli8dff50b2016-07-22 14:19:061964 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201965 TestCompletionCallback().callback(), NetLogWithSource()));
xunjieli8dff50b2016-07-22 14:19:061966
1967 size_t chunk_size = strlen(kUploadData);
rch97827ee2017-05-24 23:49:121968 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
xunjieli8dff50b2016-07-22 14:19:061969 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271970 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli8dff50b2016-07-22 14:19:061971 net_log_.bound(), callback_.callback()));
1972 QuicHttpStream* stream = stream_.get();
1973 DeleteStreamCallback delete_stream_callback(std::move(stream_));
1974 // SendRequest() completes asynchronously after the final chunk is added.
Yixin Wange7ecc472018-03-06 19:00:251975 // Error does not surface yet since packet write is triggered by a packet
1976 // flusher that tries to bundle request body writes.
xunjieli8dff50b2016-07-22 14:19:061977 ASSERT_EQ(ERR_IO_PENDING,
1978 stream->SendRequest(headers_, &response_, callback_.callback()));
rch97827ee2017-05-24 23:49:121979 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
xunjieli8dff50b2016-07-22 14:19:061980 int rv = callback_.WaitForResult();
Yixin Wange7ecc472018-03-06 19:00:251981 EXPECT_EQ(OK, rv);
1982 // Error will be surfaced once an attempt to read the response occurs.
1983 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1984 stream->ReadResponseHeaders(callback_.callback()));
xunjieli8dff50b2016-07-22 14:19:061985}
1986
rtenneti15656ae2016-01-23 03:05:031987TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersComplete) {
1988 SetRequest("POST", "/", DEFAULT_PRIORITY);
Victor Vasiliev7da08172019-10-14 06:04:251989 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231990 AddWrite(ConstructInitialSettingsPacket());
rtenneti15656ae2016-01-23 03:05:031991 AddWrite(SYNCHRONOUS, ERR_FAILED);
1992 Initialize();
1993
Jeremy Roman0579ed62017-08-29 15:56:191994 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
Yixin Wange7ecc472018-03-06 19:00:251995 auto* chunked_upload_stream =
1996 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
rtenneti15656ae2016-01-23 03:05:031997
1998 request_.method = "POST";
rchcd379012017-04-12 21:53:321999 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122000 request_.upload_data_stream = upload_data_stream_.get();
rtenneti15656ae2016-01-23 03:05:032001 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202002 TestCompletionCallback().callback(), NetLogWithSource()));
rtenneti15656ae2016-01-23 03:05:032003
xunjieli5fafe142016-03-23 23:32:542004 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272005 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542006 net_log_.bound(), callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252007 ASSERT_EQ(ERR_IO_PENDING,
rtenneti15656ae2016-01-23 03:05:032008 stream_->SendRequest(headers_, &response_, callback_.callback()));
mmenkeffff3642017-06-15 17:37:242009
Yixin Wange7ecc472018-03-06 19:00:252010 // Error will be surfaced once |upload_data_stream| triggers the next write.
2011 size_t chunk_size = strlen(kUploadData);
2012 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2013 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR, callback_.WaitForResult());
2014
2015 EXPECT_LE(0, stream_->GetTotalSentBytes());
2016 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2017}
2018
2019TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersCompleteReadResponse) {
2020 SetRequest("POST", "/", DEFAULT_PRIORITY);
Victor Vasiliev7da08172019-10-14 06:04:252021 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232022 AddWrite(ConstructInitialSettingsPacket());
Yixin Wange7ecc472018-03-06 19:00:252023 AddWrite(SYNCHRONOUS, ERR_FAILED);
2024 Initialize();
2025
2026 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
2027 auto* chunked_upload_stream =
2028 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
2029
2030 request_.method = "POST";
2031 request_.url = GURL("https://www.example.org/");
2032 request_.upload_data_stream = upload_data_stream_.get();
2033
2034 size_t chunk_size = strlen(kUploadData);
2035 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2036
2037 ASSERT_EQ(OK, request_.upload_data_stream->Init(
2038 TestCompletionCallback().callback(), NetLogWithSource()));
2039
2040 ASSERT_EQ(OK,
2041 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
2042 net_log_.bound(), callback_.callback()));
2043 ASSERT_EQ(OK,
2044 stream_->SendRequest(headers_, &response_, callback_.callback()));
2045
2046 // Error will be surfaced once an attempt to read the response occurs.
2047 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
2048 stream_->ReadResponseHeaders(callback_.callback()));
2049
mmenkeffff3642017-06-15 17:37:242050 EXPECT_LE(0, stream_->GetTotalSentBytes());
2051 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rtenneti15656ae2016-01-23 03:05:032052}
2053
2054TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBodyComplete) {
2055 SetRequest("POST", "/", DEFAULT_PRIORITY);
2056 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232057 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252058 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232059 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:372060 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:232061 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2062 kIncludeVersion, !kFin, DEFAULT_PRIORITY,
2063 &spdy_request_headers_frame_length));
rtenneti15656ae2016-01-23 03:05:032064 AddWrite(SYNCHRONOUS, ERR_FAILED);
2065 Initialize();
2066
Jeremy Roman0579ed62017-08-29 15:56:192067 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:122068 auto* chunked_upload_stream =
2069 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
rtenneti15656ae2016-01-23 03:05:032070
2071 request_.method = "POST";
rchcd379012017-04-12 21:53:322072 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122073 request_.upload_data_stream = upload_data_stream_.get();
rtenneti15656ae2016-01-23 03:05:032074 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202075 TestCompletionCallback().callback(), NetLogWithSource()));
rtenneti15656ae2016-01-23 03:05:032076
xunjieli5fafe142016-03-23 23:32:542077 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272078 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542079 net_log_.bound(), callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252080 ASSERT_EQ(ERR_IO_PENDING,
rtenneti15656ae2016-01-23 03:05:032081 stream_->SendRequest(headers_, &response_, callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252082
2083 size_t chunk_size = strlen(kUploadData);
2084 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2085 // Error does not surface yet since packet write is triggered by a packet
2086 // flusher that tries to bundle request body writes.
2087 ASSERT_EQ(OK, callback_.WaitForResult());
2088 // Error will be surfaced once an attempt to read the response occurs.
2089 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
2090 stream_->ReadResponseHeaders(callback_.callback()));
2091
2092 EXPECT_LE(0, stream_->GetTotalSentBytes());
2093 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2094}
2095
2096TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBundledBodyComplete) {
2097 SetRequest("POST", "/", DEFAULT_PRIORITY);
2098 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232099 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252100 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232101 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:432102 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:322103 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:412104 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:232105 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2106 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
2107 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:412108 } else {
2109 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:232110 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2111 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
2112 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:412113 }
2114
Yixin Wange7ecc472018-03-06 19:00:252115 AddWrite(SYNCHRONOUS, ERR_FAILED);
2116 Initialize();
2117
2118 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
2119 auto* chunked_upload_stream =
2120 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
2121
2122 request_.method = "POST";
2123 request_.url = GURL("https://www.example.org/");
2124 request_.upload_data_stream = upload_data_stream_.get();
2125
2126 size_t chunk_size = strlen(kUploadData);
2127 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
2128
2129 ASSERT_EQ(OK, request_.upload_data_stream->Init(
2130 TestCompletionCallback().callback(), NetLogWithSource()));
2131
2132 ASSERT_EQ(OK,
2133 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
2134 net_log_.bound(), callback_.callback()));
2135 ASSERT_EQ(ERR_IO_PENDING,
2136 stream_->SendRequest(headers_, &response_, callback_.callback()));
2137
2138 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2139
2140 // Error does not surface yet since packet write is triggered by a packet
2141 // flusher that tries to bundle request body writes.
2142 ASSERT_EQ(OK, callback_.WaitForResult());
2143 // Error will be surfaced once an attempt to read the response occurs.
2144 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
2145 stream_->ReadResponseHeaders(callback_.callback()));
2146
2147 EXPECT_LE(0, stream_->GetTotalSentBytes());
2148 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rtenneti15656ae2016-01-23 03:05:032149}
2150
ckrasic3865ee0f2016-02-29 22:04:562151TEST_P(QuicHttpStreamTest, ServerPushGetRequest) {
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()));
Renjie Tangaadb84b2019-08-31 01:00:232162 ASSERT_EQ(OK,
2163 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562164
2165 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2166 // packet, but does it matter?
2167 ReceivePromise(promise_id_);
2168 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2169
2170 request_.url = GURL(promise_url_);
2171
2172 // Make the second stream that will exercise the first step of the
2173 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272174 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2175 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2176 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562177
2178 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252179 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562180 size_t spdy_response_headers_frame_length;
2181 ProcessPacket(InnerConstructResponseHeadersPacket(
2182 1, promise_id_, false, &spdy_response_headers_frame_length));
2183
2184 // Receive the promised response body.
2185 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432186 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172187 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2188 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562189
2190 // Now sending a matching request will have successful rendezvous
2191 // with the promised stream.
Ryan Hamiltona1d1f4a2019-06-26 14:43:042192 ASSERT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
ckrasic3865ee0f2016-02-29 22:04:562193 callback_.callback()));
2194
2195 EXPECT_EQ(
2196 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2197 ->id(),
2198 promise_id_);
2199
2200 // The headers will be immediately available.
robpercival214763f2016-07-01 23:27:012201 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2202 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562203
2204 // As will be the body.
2205 EXPECT_EQ(
2206 static_cast<int>(strlen(kResponseBody)),
2207 promised_stream_->ReadResponseBody(
2208 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2209 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2210 EXPECT_TRUE(AtEof());
2211
ckrasic3865ee0f2016-02-29 22:04:562212 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2213 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412214 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562215 promised_stream_->GetTotalReceivedBytes());
2216}
2217
2218TEST_P(QuicHttpStreamTest, ServerPushGetRequestSlowResponse) {
2219 SetRequest("GET", "/", DEFAULT_PRIORITY);
2220 Initialize();
2221
2222 // Initialize the first stream, for receiving the promise on.
2223 request_.method = "GET";
rchcd379012017-04-12 21:53:322224 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562225
xunjieli5fafe142016-03-23 23:32:542226 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272227 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542228 net_log_.bound(), callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232229 ASSERT_EQ(OK,
2230 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562231
2232 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2233 // packet, but does it matter?
2234 ReceivePromise(promise_id_);
2235 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2236
2237 request_.url = GURL(promise_url_);
2238
2239 // Make the second stream that will exercise the first step of the
2240 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272241 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2242 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2243 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562244
2245 // Now sending a matching request will rendezvous with the promised
2246 // stream, but pending secondary validation.
2247 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2248 headers_, &response_, callback_.callback()));
2249
2250 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252251 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562252 size_t spdy_response_headers_frame_length;
2253 ProcessPacket(InnerConstructResponseHeadersPacket(
2254 1, promise_id_, false, &spdy_response_headers_frame_length));
2255
2256 // Receive the promised response body.
2257 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432258 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172259 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2260 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562261
fdoray92e35a72016-06-10 15:54:552262 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562263
2264 // Rendezvous should have succeeded now, so the promised stream
2265 // should point at our push stream, and we should be able read
2266 // headers and data from it.
robpercival214763f2016-07-01 23:27:012267 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562268
2269 EXPECT_EQ(
2270 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2271 ->id(),
2272 promise_id_);
2273
robpercival214763f2016-07-01 23:27:012274 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2275 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562276
2277 EXPECT_EQ(
2278 static_cast<int>(strlen(kResponseBody)),
2279 promised_stream_->ReadResponseBody(
2280 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2281
2282 // Callback should return
2283 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2284 EXPECT_TRUE(AtEof());
2285
ckrasic3865ee0f2016-02-29 22:04:562286 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2287 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412288 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562289 promised_stream_->GetTotalReceivedBytes());
2290}
2291
ckrasic2c63f9b2016-08-16 23:54:072292// Verify fix for crbug.com/637349
2293TEST_P(QuicHttpStreamTest, ServerPushCancelHttpStreamBeforeResponse) {
2294 SetRequest("GET", "/", DEFAULT_PRIORITY);
2295 Initialize();
2296
2297 // Initialize the first stream, for receiving the promise on.
2298 request_.method = "GET";
rchcd379012017-04-12 21:53:322299 request_.url = GURL("https://www.example.org/");
ckrasic2c63f9b2016-08-16 23:54:072300
2301 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272302 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
ckrasic2c63f9b2016-08-16 23:54:072303 net_log_.bound(), callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232304 ASSERT_EQ(OK,
2305 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic2c63f9b2016-08-16 23:54:072306
2307 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2308 // packet, but does it matter?
2309 ReceivePromise(promise_id_);
2310 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2311
2312 request_.url = GURL(promise_url_);
2313
2314 // Make the second stream that will exercise the first step of the
2315 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272316 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2317 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2318 callback_.callback()));
ckrasic2c63f9b2016-08-16 23:54:072319
2320 // Now sending a matching request will rendezvous with the promised
2321 // stream, but pending secondary validation.
2322 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2323 headers_, &response_, callback_.callback()));
2324
2325 base::RunLoop().RunUntilIdle();
2326
2327 // Cause of FinalValidation() crash as per bug.
2328 promised_stream_.reset();
2329
2330 // Receive the promised response headers.
2331 response_headers_ = promised_response_.Clone();
2332 size_t spdy_response_headers_frame_length;
2333 ProcessPacket(InnerConstructResponseHeadersPacket(
2334 1, promise_id_, false, &spdy_response_headers_frame_length));
2335}
2336
ckrasic3865ee0f2016-02-29 22:04:562337TEST_P(QuicHttpStreamTest, ServerPushCrossOriginOK) {
2338 SetRequest("GET", "/", DEFAULT_PRIORITY);
2339 Initialize();
2340
2341 // Initialize the first stream, for receiving the promise on.
2342 request_.method = "GET";
rchcd379012017-04-12 21:53:322343 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562344
xunjieli5fafe142016-03-23 23:32:542345 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272346 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542347 net_log_.bound(), callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232348 ASSERT_EQ(OK,
2349 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562350
2351 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2352 // packet, but does it matter?
2353
2354 push_promise_[":authority"] = "mail.example.org";
David Schinazi3f7465c2019-07-12 01:57:052355 promise_url_ =
2356 quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
ckrasic3865ee0f2016-02-29 22:04:562357
2358 ReceivePromise(promise_id_);
2359 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2360
2361 request_.url = GURL(promise_url_);
2362
2363 // Make the second stream that will exercise the first step of the
2364 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272365 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2366 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2367 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562368
2369 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252370 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562371 size_t spdy_response_headers_frame_length;
2372 ProcessPacket(InnerConstructResponseHeadersPacket(
2373 1, promise_id_, false, &spdy_response_headers_frame_length));
2374
2375 // Receive the promised response body.
2376 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432377 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172378 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2379 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562380
2381 // Now sending a matching request will have successful rendezvous
2382 // with the promised stream.
2383 EXPECT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
2384 callback_.callback()));
2385
2386 EXPECT_EQ(
2387 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2388 ->id(),
2389 promise_id_);
2390
2391 // The headers will be immediately available.
robpercival214763f2016-07-01 23:27:012392 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2393 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562394
2395 // As will be the body.
2396 EXPECT_EQ(
2397 static_cast<int>(strlen(kResponseBody)),
2398 promised_stream_->ReadResponseBody(
2399 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2400 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2401 EXPECT_TRUE(AtEof());
2402
ckrasic3865ee0f2016-02-29 22:04:562403 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2404 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412405 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562406 promised_stream_->GetTotalReceivedBytes());
2407}
2408
2409TEST_P(QuicHttpStreamTest, ServerPushCrossOriginFail) {
2410 SetRequest("GET", "/", DEFAULT_PRIORITY);
2411 Initialize();
2412
2413 // Initialize the first stream, for receiving the promise on.
2414 request_.method = "GET";
rchcd379012017-04-12 21:53:322415 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562416
xunjieli5fafe142016-03-23 23:32:542417 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272418 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542419 net_log_.bound(), callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232420 ASSERT_EQ(OK,
2421 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562422
2423 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2424 // packet, but does it matter?
2425 push_promise_[":authority"] = "www.notexample.org";
David Schinazi3f7465c2019-07-12 01:57:052426 promise_url_ =
2427 quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
ckrasic3865ee0f2016-02-29 22:04:562428
2429 ReceivePromise(promise_id_);
2430 // The promise will have been rejected because the cert doesn't
2431 // match.
2432 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
2433}
2434
2435TEST_P(QuicHttpStreamTest, ServerPushVaryCheckOK) {
2436 SetRequest("GET", "/", DEFAULT_PRIORITY);
2437 Initialize();
2438
2439 // Initialize the first stream, for receiving the promise on.
2440 request_.method = "GET";
rchcd379012017-04-12 21:53:322441 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562442
xunjieli5fafe142016-03-23 23:32:542443 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272444 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542445 net_log_.bound(), callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232446 ASSERT_EQ(OK,
2447 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562448
2449 push_promise_["accept-encoding"] = "gzip";
ckrasic3865ee0f2016-02-29 22:04:562450
2451 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2452 // packet, but does it matter?
2453 ReceivePromise(promise_id_);
2454 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2455
2456 request_.url = GURL(promise_url_);
2457
2458 // Make the second stream that will exercise the first step of the
2459 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272460 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2461 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2462 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562463
2464 headers_.SetHeader("accept-encoding", "gzip");
2465
2466 // Now sending a matching request will rendezvous with the promised
2467 // stream, but pending secondary validation.
2468 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2469 headers_, &response_, callback_.callback()));
2470
2471 // Receive the promised response headers.
2472 promised_response_["vary"] = "accept-encoding";
bnc94893a72016-06-30 13:45:252473 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562474 size_t spdy_response_headers_frame_length;
2475 ProcessPacket(InnerConstructResponseHeadersPacket(
2476 1, promise_id_, false, &spdy_response_headers_frame_length));
2477
2478 // Receive the promised response body.
2479 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432480 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172481 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2482 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562483
fdoray92e35a72016-06-10 15:54:552484 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562485
2486 // Rendezvous should have succeeded now, so the promised stream
2487 // should point at our push stream, and we should be able read
2488 // headers and data from it.
robpercival214763f2016-07-01 23:27:012489 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562490
2491 EXPECT_EQ(
2492 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2493 ->id(),
2494 promise_id_);
2495
robpercival214763f2016-07-01 23:27:012496 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2497 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562498
2499 EXPECT_EQ(
2500 static_cast<int>(strlen(kResponseBody)),
2501 promised_stream_->ReadResponseBody(
2502 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2503
2504 // Callback should return
2505 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2506 EXPECT_TRUE(AtEof());
2507
ckrasic3865ee0f2016-02-29 22:04:562508 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2509 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412510 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562511 promised_stream_->GetTotalReceivedBytes());
2512}
2513
2514TEST_P(QuicHttpStreamTest, ServerPushVaryCheckFail) {
2515 SetRequest("GET", "/", DEFAULT_PRIORITY);
2516 request_headers_[":scheme"] = "https";
2517 request_headers_[":path"] = "/bar";
2518 request_headers_["accept-encoding"] = "sdch";
2519
ckrasic3865ee0f2016-02-29 22:04:562520 Initialize();
2521
2522 // Initialize the first stream, for receiving the promise on.
2523 request_.method = "GET";
rchcd379012017-04-12 21:53:322524 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562525
xunjieli5fafe142016-03-23 23:32:542526 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272527 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542528 net_log_.bound(), callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232529 ASSERT_EQ(OK,
2530 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562531
2532 push_promise_["accept-encoding"] = "gzip";
ckrasic3865ee0f2016-02-29 22:04:562533
2534 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2535 // packet, but does it matter?
2536 ReceivePromise(promise_id_);
2537 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2538
2539 request_.url = GURL(promise_url_);
2540
2541 // Make the second stream that will exercise the first step of the
2542 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272543 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2544 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2545 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562546
2547 headers_.SetHeader("accept-encoding", "sdch");
2548
2549 // Now sending a matching request will rendezvous with the promised
2550 // stream, but pending secondary validation.
2551 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2552 headers_, &response_, callback_.callback()));
2553
2554 // Receive the promised response headers.
2555 promised_response_["vary"] = "accept-encoding";
bnc94893a72016-06-30 13:45:252556 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562557 size_t spdy_response_headers_frame_length;
2558 ProcessPacket(InnerConstructResponseHeadersPacket(
2559 1, promise_id_, false, &spdy_response_headers_frame_length));
2560
fdoray92e35a72016-06-10 15:54:552561 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562562
2563 // Rendezvous should have failed due to vary mismatch, so the
2564 // promised stream should have been aborted, and instead we have a
2565 // new, regular client initiated stream.
robpercival214763f2016-07-01 23:27:012566 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562567
2568 // Not a server-initiated stream.
2569 EXPECT_NE(
2570 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2571 ->id(),
2572 promise_id_);
2573
2574 // Instead, a new client-initiated stream.
2575 EXPECT_EQ(
2576 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2577 ->id(),
Nick Harper23290b82019-05-02 00:02:562578 stream_id_ + quic::QuicUtils::StreamIdDelta(version_.transport_version));
ckrasic3865ee0f2016-02-29 22:04:562579
2580 // After rendezvous failure, the push stream has been cancelled.
2581 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
2582
2583 // The rest of the test verifies that the retried as
2584 // client-initiated version of |promised_stream_| works as intended.
2585
2586 // Ack the request.
Renjie90e808e2019-01-24 07:24:042587 ProcessPacket(ConstructServerAckPacket(2, 1, 1, 1));
ckrasic3865ee0f2016-02-29 22:04:562588
bnc614a92d32016-04-04 13:56:072589 SetResponse("404 Not Found", string());
ckrasic3865ee0f2016-02-29 22:04:562590 size_t spdy_response_header_frame_length;
2591 ProcessPacket(InnerConstructResponseHeadersPacket(
Nick Harper23290b82019-05-02 00:02:562592 3,
2593 stream_id_ + quic::QuicUtils::StreamIdDelta(version_.transport_version),
2594 kFin, &spdy_response_header_frame_length));
ckrasic3865ee0f2016-02-29 22:04:562595
fdoray92e35a72016-06-10 15:54:552596 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562597
robpercival214763f2016-07-01 23:27:012598 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2599 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562600 ASSERT_TRUE(response_.headers.get());
2601 EXPECT_EQ(404, response_.headers->response_code());
2602 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
2603 EXPECT_FALSE(response_.response_time.is_null());
2604 EXPECT_FALSE(response_.request_time.is_null());
2605
2606 // There is no body, so this should return immediately.
2607 EXPECT_EQ(
2608 0, promised_stream_->ReadResponseBody(
2609 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2610 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2611
2612 stream_->Close(true);
2613
2614 EXPECT_TRUE(AtEof());
ckrasic3865ee0f2016-02-29 22:04:562615}
2616
maksim.sisov84e20c92016-06-23 08:49:342617TEST_P(QuicHttpStreamTest, DataReadErrorSynchronous) {
2618 SetRequest("POST", "/", DEFAULT_PRIORITY);
2619 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232620 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252621 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232622 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Yixin Wange7ecc472018-03-06 19:00:252623 AddWrite(ConstructRequestAndRstPacket(
Renjie Tangaadb84b2019-08-31 01:00:232624 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2625 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
2626 &spdy_request_headers_frame_length, quic::QUIC_ERROR_PROCESSING_STREAM));
maksim.sisov84e20c92016-06-23 08:49:342627
2628 Initialize();
2629
Jeremy Roman0579ed62017-08-29 15:56:192630 upload_data_stream_ = std::make_unique<ReadErrorUploadDataStream>(
maksim.sisov84e20c92016-06-23 08:49:342631 ReadErrorUploadDataStream::FailureMode::SYNC);
2632 request_.method = "POST";
rchcd379012017-04-12 21:53:322633 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122634 request_.upload_data_stream = upload_data_stream_.get();
maksim.sisov84e20c92016-06-23 08:49:342635 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202636 TestCompletionCallback().callback(), NetLogWithSource()));
maksim.sisov84e20c92016-06-23 08:49:342637
2638 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272639 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
maksim.sisov84e20c92016-06-23 08:49:342640 net_log_.bound(), callback_.callback()));
2641
2642 int result = stream_->SendRequest(headers_, &response_, callback_.callback());
robpercival214763f2016-07-01 23:27:012643 EXPECT_THAT(result, IsError(ERR_FAILED));
maksim.sisov84e20c92016-06-23 08:49:342644
2645 EXPECT_TRUE(AtEof());
2646
2647 // QuicHttpStream::GetTotalSent/ReceivedBytes includes only headers.
2648 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
2649 stream_->GetTotalSentBytes());
2650 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2651}
2652
2653TEST_P(QuicHttpStreamTest, DataReadErrorAsynchronous) {
2654 SetRequest("POST", "/", DEFAULT_PRIORITY);
2655 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232656 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252657 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232658 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:372659 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:232660 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2661 kIncludeVersion, !kFin, DEFAULT_PRIORITY,
2662 &spdy_request_headers_frame_length));
2663 AddWrite(
2664 ConstructClientRstStreamErrorPacket(packet_number++, !kIncludeVersion));
maksim.sisov84e20c92016-06-23 08:49:342665
2666 Initialize();
2667
Jeremy Roman0579ed62017-08-29 15:56:192668 upload_data_stream_ = std::make_unique<ReadErrorUploadDataStream>(
maksim.sisov84e20c92016-06-23 08:49:342669 ReadErrorUploadDataStream::FailureMode::ASYNC);
2670 request_.method = "POST";
rchcd379012017-04-12 21:53:322671 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122672 request_.upload_data_stream = upload_data_stream_.get();
maksim.sisov84e20c92016-06-23 08:49:342673 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202674 TestCompletionCallback().callback(), NetLogWithSource()));
maksim.sisov84e20c92016-06-23 08:49:342675
2676 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272677 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
maksim.sisov84e20c92016-06-23 08:49:342678 net_log_.bound(), callback_.callback()));
2679
2680 int result = stream_->SendRequest(headers_, &response_, callback_.callback());
2681
Renjie90e808e2019-01-24 07:24:042682 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
maksim.sisov84e20c92016-06-23 08:49:342683 SetResponse("200 OK", string());
2684
robpercival214763f2016-07-01 23:27:012685 EXPECT_THAT(result, IsError(ERR_IO_PENDING));
2686 EXPECT_THAT(callback_.GetResult(result), IsError(ERR_FAILED));
maksim.sisov84e20c92016-06-23 08:49:342687
2688 EXPECT_TRUE(AtEof());
2689
2690 // QuicHttpStream::GetTotalSent/ReceivedBytes includes only headers.
2691 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
2692 stream_->GetTotalSentBytes());
2693 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2694}
2695
Bence Béky97ec688c2021-03-16 13:48:502696TEST_P(QuicHttpStreamTest, GetAcceptChViaAlps) {
2697 AddWrite(ConstructInitialSettingsPacket());
2698 Initialize();
2699
2700 if (!VersionUsesHttp3(version_.transport_version)) {
2701 // ALPS is only implemented for HTTP/3.
2702 return;
2703 }
2704
2705 base::HistogramTester histogram_tester;
2706
2707 session_->OnAcceptChFrameReceivedViaAlps(
2708 {{{"https://www.example.org", "Sec-UA-CH-Platform"}}});
2709
2710 request_.method = "GET";
2711 request_.url = GURL("https://www.example.org/foo");
2712
2713 EXPECT_EQ(OK,
2714 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
2715 net_log_.bound(), callback_.callback()));
2716 EXPECT_EQ("Sec-UA-CH-Platform", stream_->GetAcceptChViaAlps());
2717 EXPECT_TRUE(AtEof());
2718
2719 histogram_tester.ExpectBucketCount(
2720 "Net.QuicSession.AcceptChFrameReceivedViaAlps", 1, 1);
2721 histogram_tester.ExpectTotalCount(
2722 "Net.QuicSession.AcceptChFrameReceivedViaAlps", 1);
2723 histogram_tester.ExpectBucketCount("Net.QuicSession.AcceptChForOrigin", 1, 1);
2724 histogram_tester.ExpectTotalCount("Net.QuicSession.AcceptChForOrigin", 1);
2725}
2726
[email protected]f702d572012-12-04 15:56:202727} // namespace test
[email protected]f702d572012-12-04 15:56:202728} // namespace net