blob: adbc9828f36642a06e8797aa87d2737d242c844a [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"
Keishi Hattori0e45c022021-11-27 09:25:5214#include "base/memory/raw_ptr.h"
fdoray92e35a72016-06-10 15:54:5515#include "base/run_loop.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"
Ben Schwartz3ff4dc1e62021-04-27 21:15:2330#include "net/dns/public/secure_dns_policy.h"
[email protected]f702d572012-12-04 15:56:2031#include "net/http/http_response_headers.h"
[email protected]5db452202014-08-19 05:22:1532#include "net/http/transport_security_state.h"
Matt Reichhoff0049a0b72021-10-20 20:44:2633#include "net/log/net_log.h"
mikecirone8b85c432016-09-08 19:11:0034#include "net/log/net_log_event_type.h"
xunjieli5fafe142016-03-23 23:32:5435#include "net/log/test_net_log.h"
36#include "net/log/test_net_log_util.h"
Victor Vasiliev4f6fb892019-05-31 16:58:3137#include "net/quic/address_utils.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0838#include "net/quic/crypto/proof_verifier_chromium.h"
39#include "net/quic/mock_crypto_client_stream_factory.h"
40#include "net/quic/quic_chromium_alarm_factory.h"
41#include "net/quic/quic_chromium_connection_helper.h"
42#include "net/quic/quic_chromium_packet_reader.h"
43#include "net/quic/quic_chromium_packet_writer.h"
Matt Menkefca05b62019-09-20 23:15:5644#include "net/quic/quic_crypto_client_config_handle.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0845#include "net/quic/quic_http_utils.h"
46#include "net/quic/quic_server_info.h"
47#include "net/quic/quic_stream_factory.h"
48#include "net/quic/quic_test_packet_maker.h"
Ryan Hamilton0d65a8c2019-06-07 00:46:0249#include "net/quic/quic_test_packet_printer.h"
Matt Menkefca05b62019-09-20 23:15:5650#include "net/quic/test_quic_crypto_client_config_handle.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0851#include "net/quic/test_task_runner.h"
tbansalca83c002016-04-28 20:56:2852#include "net/socket/socket_performance_watcher.h"
[email protected]f702d572012-12-04 15:56:2053#include "net/socket/socket_test_util.h"
Bence Béky94658bf2018-05-11 19:22:5854#include "net/spdy/spdy_http_utils.h"
rch03b7a202016-02-05 00:54:2055#include "net/test/cert_test_util.h"
robpercival214763f2016-07-01 23:27:0156#include "net/test/gtest_util.h"
rsleevia69c79a2016-06-22 03:28:4357#include "net/test/test_data_directory.h"
Gabriel Charettec7108742019-08-23 03:31:4058#include "net/test/test_with_task_environment.h"
Ryan Hamiltonea4fa192022-04-12 18:30:4959#include "net/third_party/quiche/src/quiche/quic/core/congestion_control/send_algorithm_interface.h"
60#include "net/third_party/quiche/src/quiche/quic/core/crypto/crypto_protocol.h"
61#include "net/third_party/quiche/src/quiche/quic/core/crypto/quic_decrypter.h"
62#include "net/third_party/quiche/src/quiche/quic/core/crypto/quic_encrypter.h"
63#include "net/third_party/quiche/src/quiche/quic/core/http/spdy_server_push_utils.h"
64#include "net/third_party/quiche/src/quiche/quic/core/quic_connection.h"
65#include "net/third_party/quiche/src/quiche/quic/core/quic_utils.h"
66#include "net/third_party/quiche/src/quiche/quic/core/quic_write_blocked_list.h"
67#include "net/third_party/quiche/src/quiche/quic/core/tls_client_handshaker.h"
68#include "net/third_party/quiche/src/quiche/quic/platform/api/quic_flags.h"
69#include "net/third_party/quiche/src/quiche/quic/test_tools/crypto_test_utils.h"
70#include "net/third_party/quiche/src/quiche/quic/test_tools/mock_clock.h"
71#include "net/third_party/quiche/src/quiche/quic/test_tools/mock_random.h"
72#include "net/third_party/quiche/src/quiche/quic/test_tools/qpack/qpack_test_utils.h"
73#include "net/third_party/quiche/src/quiche/quic/test_tools/quic_connection_peer.h"
74#include "net/third_party/quiche/src/quiche/quic/test_tools/quic_spdy_session_peer.h"
75#include "net/third_party/quiche/src/quiche/quic/test_tools/quic_test_utils.h"
76#include "net/third_party/quiche/src/quiche/spdy/core/spdy_frame_builder.h"
77#include "net/third_party/quiche/src/quiche/spdy/core/spdy_framer.h"
78#include "net/third_party/quiche/src/quiche/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"
Dan McArdle68a5f622021-07-09 20:56:5382#include "url/scheme_host_port.h"
83#include "url/url_constants.h"
[email protected]f702d572012-12-04 15:56:2084
bnc614a92d32016-04-04 13:56:0785using std::string;
[email protected]f702d572012-12-04 15:56:2086using testing::_;
[email protected]06ff5152013-08-29 01:03:0587using testing::AnyNumber;
88using testing::Return;
[email protected]f702d572012-12-04 15:56:2089
Tsuyoshi Horo4f516be2022-06-14 11:53:1390namespace net::test {
[email protected]f702d572012-12-04 15:56:2091namespace {
92
[email protected]16ba7742014-08-22 00:57:2593const char kUploadData[] = "Really nifty data!";
rch9ae5b3b2016-02-11 00:36:2994const char kDefaultServerHostName[] = "www.example.org";
rchcd379012017-04-12 21:53:3295const uint16_t kDefaultServerPort = 443;
[email protected]f702d572012-12-04 15:56:2096
David Schinazi09e9a6012019-10-03 17:37:5797struct TestParams {
98 quic::ParsedQuicVersion version;
99 bool client_headers_include_h2_stream_dependency;
100};
101
102// Used by ::testing::PrintToStringParamName().
103std::string PrintToString(const TestParams& p) {
Victor Vasiliev62c09dc2020-11-06 18:18:29104 return base::StrCat(
105 {ParsedQuicVersionToString(p.version), "_",
106 (p.client_headers_include_h2_stream_dependency ? "" : "No"),
107 "Dependency"});
David Schinazi09e9a6012019-10-03 17:37:57108}
109
110std::vector<TestParams> GetTestParams() {
111 std::vector<TestParams> params;
112 quic::ParsedQuicVersionVector all_supported_versions =
113 quic::AllSupportedVersions();
114 for (const auto& version : all_supported_versions) {
115 params.push_back(TestParams{version, false});
116 params.push_back(TestParams{version, true});
117 }
118 return params;
119}
120
Bence Békye0d3747d2020-08-28 23:16:40121// Returns true if |params| is a dict, has an entry with key "headers", that
122// entry is a list of strings, which when interpreted as colon-separated
123// key-value pairs has exactly one entry with |key| and that entry has value
124// |expected_value|.
125bool CheckHeader(const base::Value& params,
126 base::StringPiece key,
127 base::StringPiece expected_value) {
128 if (!params.is_dict()) {
129 return false;
130 }
Matt Menke355d7b1e2022-05-27 23:19:53131 const base::Value::List* headers = params.GetDict().FindList("headers");
Bence Békye0d3747d2020-08-28 23:16:40132 if (!headers) {
133 return false;
134 }
135
136 std::string header_prefix = base::StrCat({key, ": "});
137 std::string expected_header = base::StrCat({header_prefix, expected_value});
138
Bence Békye0d3747d2020-08-28 23:16:40139 bool header_found = false;
Matt Menke355d7b1e2022-05-27 23:19:53140 for (const auto& header_value : *headers) {
141 const std::string* header = header_value.GetIfString();
142 if (!header) {
Bence Békye0d3747d2020-08-28 23:16:40143 return false;
144 }
Matt Menke355d7b1e2022-05-27 23:19:53145 if (base::StartsWith(*header, header_prefix)) {
Bence Békye0d3747d2020-08-28 23:16:40146 if (header_found) {
147 return false;
148 }
Matt Menke355d7b1e2022-05-27 23:19:53149 if (*header != expected_header) {
Bence Békye0d3747d2020-08-28 23:16:40150 return false;
151 }
152 header_found = true;
153 }
Bence Békye0d3747d2020-08-28 23:16:40154 }
155 return header_found;
156}
157
Ryan Hamilton8d9ee76e2018-05-29 23:52:52158class TestQuicConnection : public quic::QuicConnection {
[email protected]f702d572012-12-04 15:56:20159 public:
Ryan Hamilton8d9ee76e2018-05-29 23:52:52160 TestQuicConnection(const quic::ParsedQuicVersionVector& versions,
161 quic::QuicConnectionId connection_id,
[email protected]f702d572012-12-04 15:56:20162 IPEndPoint address,
rch12fef552016-01-15 16:26:31163 QuicChromiumConnectionHelper* helper,
rch16c74d1d2016-04-22 06:14:07164 QuicChromiumAlarmFactory* alarm_factory,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52165 quic::QuicPacketWriter* writer)
Victor Vasiliev4f6fb892019-05-31 16:58:31166 : quic::QuicConnection(connection_id,
Nick Harperd049f192020-10-02 02:56:10167 quic::QuicSocketAddress(),
Victor Vasiliev4f6fb892019-05-31 16:58:31168 ToQuicSocketAddress(address),
169 helper,
170 alarm_factory,
171 writer,
172 true /* owns_writer */,
173 quic::Perspective::IS_CLIENT,
174 versions) {}
[email protected]f702d572012-12-04 15:56:20175
Ryan Hamilton8d9ee76e2018-05-29 23:52:52176 void SetSendAlgorithm(quic::SendAlgorithmInterface* send_algorithm) {
177 quic::test::QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
[email protected]f702d572012-12-04 15:56:20178 }
179};
180
maksim.sisov84e20c92016-06-23 08:49:34181// UploadDataStream that always returns errors on data read.
182class ReadErrorUploadDataStream : public UploadDataStream {
183 public:
184 enum class FailureMode { SYNC, ASYNC };
185
186 explicit ReadErrorUploadDataStream(FailureMode mode)
Jeremy Romand54000b22019-07-08 18:40:16187 : UploadDataStream(true, 0), async_(mode) {}
Peter Boström293b1342021-09-22 17:31:43188
189 ReadErrorUploadDataStream(const ReadErrorUploadDataStream&) = delete;
190 ReadErrorUploadDataStream& operator=(const ReadErrorUploadDataStream&) =
191 delete;
192
Tsuyoshi Horo07c3f0e2022-06-16 07:30:47193 ~ReadErrorUploadDataStream() override = default;
maksim.sisov84e20c92016-06-23 08:49:34194
195 private:
196 void CompleteRead() { UploadDataStream::OnReadCompleted(ERR_FAILED); }
197
198 // UploadDataStream implementation:
tfarina42834112016-09-22 13:38:20199 int InitInternal(const NetLogWithSource& net_log) override { return OK; }
maksim.sisov84e20c92016-06-23 08:49:34200
201 int ReadInternal(IOBuffer* buf, int buf_len) override {
202 if (async_ == FailureMode::ASYNC) {
203 base::ThreadTaskRunnerHandle::Get()->PostTask(
kylecharf4fe5172019-02-15 18:53:49204 FROM_HERE, base::BindOnce(&ReadErrorUploadDataStream::CompleteRead,
205 weak_factory_.GetWeakPtr()));
maksim.sisov84e20c92016-06-23 08:49:34206 return ERR_IO_PENDING;
207 }
208 return ERR_FAILED;
209 }
210
211 void ResetInternal() override {}
212
213 const FailureMode async_;
214
Jeremy Romand54000b22019-07-08 18:40:16215 base::WeakPtrFactory<ReadErrorUploadDataStream> weak_factory_{this};
maksim.sisov84e20c92016-06-23 08:49:34216};
217
Bence Béky8ddc2492018-06-13 01:02:04218// A helper class that will delete |stream| when the callback is invoked.
xunjieli8dff50b2016-07-22 14:19:06219class DeleteStreamCallback : public TestCompletionCallbackBase {
220 public:
Bence Béky8ddc2492018-06-13 01:02:04221 explicit DeleteStreamCallback(std::unique_ptr<QuicHttpStream> stream)
222 : stream_(std::move(stream)) {}
xunjieli8dff50b2016-07-22 14:19:06223
Bence Béky8ddc2492018-06-13 01:02:04224 CompletionOnceCallback callback() {
225 return base::BindOnce(&DeleteStreamCallback::DeleteStream,
226 base::Unretained(this));
227 }
xunjieli8dff50b2016-07-22 14:19:06228
229 private:
230 void DeleteStream(int result) {
231 stream_.reset();
232 SetResult(result);
233 }
234
235 std::unique_ptr<QuicHttpStream> stream_;
xunjieli8dff50b2016-07-22 14:19:06236};
237
[email protected]f702d572012-12-04 15:56:20238} // namespace
239
[email protected]24e5bc52013-09-18 15:36:58240class QuicHttpStreamPeer {
241 public:
rch08e198572017-05-09 16:56:55242 static QuicChromiumClientStream::Handle* GetQuicChromiumClientStream(
[email protected]24e5bc52013-09-18 15:36:58243 QuicHttpStream* stream) {
rch08e198572017-05-09 16:56:55244 return stream->stream_.get();
[email protected]24e5bc52013-09-18 15:36:58245 }
246};
247
David Schinazi09e9a6012019-10-03 17:37:57248class QuicHttpStreamTest : public ::testing::TestWithParam<TestParams>,
Gabriel Charette694c3c332019-08-19 14:53:05249 public WithTaskEnvironment {
rchfb47f712017-05-21 03:24:00250 public:
251 void CloseStream(QuicHttpStream* stream, int /*rv*/) { stream->Close(false); }
252
[email protected]f702d572012-12-04 15:56:20253 protected:
[email protected]1e960032013-12-20 19:00:20254 static const bool kFin = true;
255 static const bool kIncludeVersion = true;
[email protected]1e960032013-12-20 19:00:20256
[email protected]f702d572012-12-04 15:56:20257 // Holds a packet to be written to the wire, and the IO mode that should
258 // be used by the mock socket when performing the write.
259 struct PacketToWrite {
Ryan Hamilton8d9ee76e2018-05-29 23:52:52260 PacketToWrite(IoMode mode, quic::QuicReceivedPacket* packet)
rjshaded5ced072015-12-18 19:26:02261 : mode(mode), packet(packet) {}
rtenneti15656ae2016-01-23 03:05:03262 PacketToWrite(IoMode mode, int rv) : mode(mode), packet(nullptr), rv(rv) {}
[email protected]f702d572012-12-04 15:56:20263 IoMode mode;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52264 quic::QuicReceivedPacket* packet;
rtenneti15656ae2016-01-23 03:05:03265 int rv;
[email protected]f702d572012-12-04 15:56:20266 };
267
268 QuicHttpStreamTest()
David Schinazi09e9a6012019-10-03 17:37:57269 : version_(GetParam().version),
270 client_headers_include_h2_stream_dependency_(
271 GetParam().client_headers_include_h2_stream_dependency),
Nick Harpera598fc5f2019-06-21 08:46:50272 crypto_config_(
273 quic::test::crypto_test_utils::ProofVerifierForTesting()),
Victor Costan9c7302b2018-08-27 16:39:44274 read_buffer_(base::MakeRefCounted<IOBufferWithSize>(4096)),
Fan Yang32c5a112018-12-10 20:06:33275 promise_id_(GetNthServerInitiatedUnidirectionalStreamId(0)),
276 stream_id_(GetNthClientInitiatedBidirectionalStreamId(0)),
David Schinazic8281052019-01-24 06:14:17277 connection_id_(quic::test::TestConnectionId(2)),
Yixin Wang079ad542018-01-11 04:06:05278 client_maker_(version_,
alyssar2adf3ac2016-05-03 17:12:58279 connection_id_,
280 &clock_,
281 kDefaultServerHostName,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52282 quic::Perspective::IS_CLIENT,
Yixin Wang079ad542018-01-11 04:06:05283 client_headers_include_h2_stream_dependency_),
284 server_maker_(version_,
zhongyi5dbfdd42017-06-20 05:22:15285 connection_id_,
alyssar2adf3ac2016-05-03 17:12:58286 &clock_,
287 kDefaultServerHostName,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52288 quic::Perspective::IS_SERVER,
Yixin Wang079ad542018-01-11 04:06:05289 false),
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
Tsuyoshi Horobfd85672022-06-17 01:37:38301 ~QuicHttpStreamTest() override {
Renjieba55fae2018-09-20 03:05:16302 session_->CloseSessionOnError(ERR_ABORTED, quic::QUIC_INTERNAL_ERROR,
303 quic::ConnectionCloseBehavior::SILENT_CLOSE);
Tsuyoshi Horo17ef47d02022-06-30 10:58:27304 for (auto& write : writes_) {
305 delete write.packet;
[email protected]f702d572012-12-04 15:56:20306 }
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) {
Tsuyoshi Horoebc507882022-06-30 11:16:45311 writes_.emplace_back(SYNCHRONOUS, packet.release());
[email protected]f702d572012-12-04 15:56:20312 }
313
Tsuyoshi Horoebc507882022-06-30 11:16:45314 void AddWrite(IoMode mode, int rv) { writes_.emplace_back(mode, rv); }
rtenneti15656ae2016-01-23 03:05:03315
[email protected]f702d572012-12-04 15:56:20316 // Returns the packet to be written at position |pos|.
Ryan Hamilton8d9ee76e2018-05-29 23:52:52317 quic::QuicReceivedPacket* GetWrite(size_t pos) { return writes_[pos].packet; }
[email protected]f702d572012-12-04 15:56:20318
319 bool AtEof() {
rch37de576c2015-05-17 20:28:17320 return socket_data_->AllReadDataConsumed() &&
321 socket_data_->AllWriteDataConsumed();
[email protected]f702d572012-12-04 15:56:20322 }
323
Ryan Hamilton8d9ee76e2018-05-29 23:52:52324 void ProcessPacket(std::unique_ptr<quic::QuicReceivedPacket> packet) {
Victor Vasiliev4f6fb892019-05-31 16:58:31325 connection_->ProcessUdpPacket(ToQuicSocketAddress(self_addr_),
326 ToQuicSocketAddress(peer_addr_), *packet);
[email protected]f702d572012-12-04 15:56:20327 }
328
329 // Configures the test fixture to use the list of expected writes.
330 void Initialize() {
Renjie Tang6ff9a9b2021-02-03 22:11:09331 mock_writes_ = std::make_unique<MockWrite[]>(writes_.size());
[email protected]f702d572012-12-04 15:56:20332 for (size_t i = 0; i < writes_.size(); i++) {
rtenneti15656ae2016-01-23 03:05:03333 if (writes_[i].packet == nullptr) {
334 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].rv, i);
335 } else {
336 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].packet->data(),
337 writes_[i].packet->length());
338 }
bnc614a92d32016-04-04 13:56:07339 }
[email protected]f702d572012-12-04 15:56:20340
Renjie Tang6ff9a9b2021-02-03 22:11:09341 socket_data_ = std::make_unique<StaticSocketDataProvider>(
Ryan Sleevib8d7ea02018-05-07 20:01:01342 base::span<MockRead>(),
Renjie Tang6ff9a9b2021-02-03 22:11:09343 base::make_span(mock_writes_.get(), writes_.size()));
Ryan Hamilton0d65a8c2019-06-07 00:46:02344 socket_data_->set_printer(&printer_);
[email protected]f702d572012-12-04 15:56:20345
Tsuyoshi Horof8861cb2022-07-05 23:50:20346 auto socket = std::make_unique<MockUDPClientSocket>(socket_data_.get(),
347 NetLog::Get());
[email protected]e13201d82012-12-12 05:00:32348 socket->Connect(peer_addr_);
[email protected]f702d572012-12-04 15:56:20349 runner_ = new TestTaskRunner(&clock_);
Ryan Hamilton8d9ee76e2018-05-29 23:52:52350 send_algorithm_ = new quic::test::MockSendAlgorithm();
rch7dd15702015-07-01 18:57:57351 EXPECT_CALL(*send_algorithm_, InRecovery()).WillRepeatedly(Return(false));
352 EXPECT_CALL(*send_algorithm_, InSlowStart()).WillRepeatedly(Return(false));
Victor Vasiliev7da08172019-10-14 06:04:25353 if (VersionUsesHttp3(version_.transport_version)) {
Renjie Tangaadb84b2019-08-31 01:00:23354 EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
355 .Times(testing::AtLeast(1));
356 }
Ryan Hamiltona1d1f4a2019-06-26 14:43:04357 EXPECT_CALL(*send_algorithm_, OnCongestionEvent(_, _, _, _, _))
358 .Times(AnyNumber());
rtenneti44f4a2e2015-08-07 14:00:07359 EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
Zhongyi Shica576df2019-04-12 17:43:40360 .WillRepeatedly(Return(quic::kMaxOutgoingPacketSize));
jokulik0e0a00c32016-06-13 21:51:58361 EXPECT_CALL(*send_algorithm_, PacingRate(_))
Ryan Hamilton8d9ee76e2018-05-29 23:52:52362 .WillRepeatedly(Return(quic::QuicBandwidth::Zero()));
Michael Warres74ee3ce2017-10-09 15:26:37363 EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true));
rtenneti44f4a2e2015-08-07 14:00:07364 EXPECT_CALL(*send_algorithm_, BandwidthEstimate())
Ryan Hamilton8d9ee76e2018-05-29 23:52:52365 .WillRepeatedly(Return(quic::QuicBandwidth::Zero()));
rch1e543ec2015-03-29 07:04:40366 EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(AnyNumber());
rch08cae032017-03-29 00:59:15367 EXPECT_CALL(*send_algorithm_, OnApplicationLimited(_)).Times(AnyNumber());
rch0d5bcf62017-05-24 22:48:45368 EXPECT_CALL(*send_algorithm_, GetCongestionControlType())
369 .Times(AnyNumber());
Renjie Tang6ff9a9b2021-02-03 22:11:09370 helper_ = std::make_unique<QuicChromiumConnectionHelper>(
371 &clock_, &random_generator_);
372 alarm_factory_ =
373 std::make_unique<QuicChromiumAlarmFactory>(runner_.get(), &clock_);
rch16c74d1d2016-04-22 06:14:07374
Michael Warres74ee3ce2017-10-09 15:26:37375 connection_ = new TestQuicConnection(
Nick Harper23290b82019-05-02 00:02:56376 quic::test::SupportedVersions(version_), connection_id_, peer_addr_,
377 helper_.get(), alarm_factory_.get(),
Ryan Hamilton9edcf1a2017-11-22 05:55:17378 new QuicChromiumPacketWriter(
379 socket.get(), base::ThreadTaskRunnerHandle::Get().get()));
[email protected]f702d572012-12-04 15:56:20380 connection_->set_visitor(&visitor_);
[email protected]fee17f72013-02-03 07:47:41381 connection_->SetSendAlgorithm(send_algorithm_);
rch03b7a202016-02-05 00:54:20382
383 // Load a certificate that is valid for *.example.org
384 scoped_refptr<X509Certificate> test_cert(
385 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
386 EXPECT_TRUE(test_cert.get());
387
388 verify_details_.cert_verify_result.verified_cert = test_cert;
389 verify_details_.cert_verify_result.is_issued_by_known_root = true;
390 crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details_);
391
xunjieli84adaab2016-09-20 01:12:28392 base::TimeTicks dns_end = base::TimeTicks::Now();
Peter Kastinge5a38ed2021-10-02 03:06:35393 base::TimeTicks dns_start = dns_end - base::Milliseconds(1);
Renjie Tang6ff9a9b2021-02-03 22:11:09394 session_ = std::make_unique<QuicChromiumClientSession>(
xunjielib53b38c2016-03-24 15:54:36395 connection_, std::move(socket),
rtenneti1cd3b162015-09-29 02:58:28396 /*stream_factory=*/nullptr, &crypto_client_stream_factory_, &clock_,
Nick Harper89bc7212018-07-31 19:07:57397 &transport_security_state_, /*ssl_config_service=*/nullptr,
danakjad1777e2016-04-16 00:56:42398 base::WrapUnique(static_cast<QuicServerInfo*>(nullptr)),
Paul Jensen8e3c5d32018-02-19 17:06:33399 QuicSessionKey(kDefaultServerHostName, kDefaultServerPort,
dalyk51ab46b2019-10-15 15:14:34400 PRIVACY_MODE_DISABLED, SocketTag(),
Tsuyoshi Horo7acebce2022-05-12 06:13:23401 NetworkIsolationKey(), SecureDnsPolicy::kAllow,
402 /*require_dns_https_alpn=*/false),
Bence Béky1ceba552019-07-19 17:11:05403 /*require_confirmation=*/false,
Bence Béky1ceba552019-07-19 17:11:05404 /*migrate_session_early_v2=*/false,
Zhongyi Shi757fcce2018-06-27 05:41:27405 /*migrate_session_on_network_change_v2=*/false,
406 /*default_network=*/NetworkChangeNotifier::kInvalidNetworkHandle,
Zhongyi Shie01f2db2019-02-22 19:53:23407 quic::QuicTime::Delta::FromMilliseconds(
Ryan Sleevi2e8255b2019-07-17 21:02:21408 kDefaultRetransmittableOnWireTimeout.InMilliseconds()),
Zhongyi Shiaf38c4e42019-08-29 22:49:05409 /*migrate_idle_session=*/false, /*allow_port_migration=*/false,
410 kDefaultIdleSessionMigrationPeriod, kMaxTimeOnNonDefaultNetwork,
Zhongyi Shiee760762018-08-01 00:54:29411 kMaxMigrationsToNonDefaultNetworkOnWriteError,
Zhongyi Shi8b1e43f2017-12-13 20:46:30412 kMaxMigrationsToNonDefaultNetworkOnPathDegrading,
Zhongyi Shi5f587cc2017-11-21 23:24:17413 kQuicYieldAfterPacketsRead,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52414 quic::QuicTime::Delta::FromMilliseconds(
415 kQuicYieldAfterDurationMilliseconds),
Yixin Wang079ad542018-01-11 04:06:05416 client_headers_include_h2_stream_dependency_, /*cert_verify_flags=*/0,
Matt Menkefca05b62019-09-20 23:15:56417 quic::test::DefaultQuicConfig(),
418 std::make_unique<TestQuicCryptoClientConfigHandle>(&crypto_config_),
Matt Menked804aaf2020-07-21 21:25:48419 "CONNECTION_UNKNOWN", dns_start, dns_end,
420 std::make_unique<quic::QuicClientPushPromiseIndex>(), nullptr,
Zhongyi Shic16b4102019-02-12 00:37:40421 base::DefaultTickClock::GetInstance(),
xunjieli84adaab2016-09-20 01:12:28422 base::ThreadTaskRunnerHandle::Get().get(),
Matt Reichhoff0049a0b72021-10-20 20:44:26423 /*socket_performance_watcher=*/nullptr, NetLog::Get());
rtennetid39bd762015-06-12 01:05:52424 session_->Initialize();
rchf0b18c8a2017-05-05 19:31:57425
Bence Béky6e243aa2019-12-13 19:01:07426 // Blackhole QPACK decoder stream instead of constructing mock writes.
427 if (VersionUsesHttp3(version_.transport_version)) {
428 session_->qpack_decoder()->set_qpack_stream_sender_delegate(
429 &noop_qpack_stream_sender_delegate_);
430 }
431
432 TestCompletionCallback callback;
rch433bf5f2017-02-14 04:10:47433 session_->CryptoConnect(callback.callback());
Ryan Hamilton6c2a2a82017-12-15 02:06:28434 stream_ = std::make_unique<QuicHttpStream>(
Dan McArdle68a5f622021-07-09 20:56:53435 session_->CreateHandle(
436 url::SchemeHostPort(url::kHttpsScheme, "www.example.org", 443)),
Eric Orthac661912022-01-10 21:44:17437 /*dns_aliases=*/std::set<std::string>());
Ryan Hamilton6c2a2a82017-12-15 02:06:28438 promised_stream_ = std::make_unique<QuicHttpStream>(
Dan McArdle68a5f622021-07-09 20:56:53439 session_->CreateHandle(
440 url::SchemeHostPort(url::kHttpsScheme, "www.example.org", 443)),
Eric Orthac661912022-01-10 21:44:17441 /*dns_aliases=*/std::set<std::string>());
ckrasic3865ee0f2016-02-29 22:04:56442 push_promise_[":path"] = "/bar";
443 push_promise_[":authority"] = "www.example.org";
444 push_promise_[":version"] = "HTTP/1.1";
445 push_promise_[":method"] = "GET";
446 push_promise_[":scheme"] = "https";
447
Kenichi Ishibashif8634ab2021-03-16 23:41:28448 promised_response_[":status"] = "200";
ckrasic3865ee0f2016-02-29 22:04:56449 promised_response_[":version"] = "HTTP/1.1";
450 promised_response_["content-type"] = "text/plain";
451
David Schinazi3f7465c2019-07-12 01:57:05452 promise_url_ =
453 quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
[email protected]6cca996b2013-01-25 07:43:36454 }
455
bnc614a92d32016-04-04 13:56:07456 void SetRequest(const string& method,
457 const string& path,
[email protected]1e960032013-12-20 19:00:20458 RequestPriority priority) {
rchcd379012017-04-12 21:53:32459 request_headers_ = client_maker_.GetRequestHeaders(method, "https", path);
[email protected]6cca996b2013-01-25 07:43:36460 }
461
bnc614a92d32016-04-04 13:56:07462 void SetResponse(const string& status, const string& body) {
alyssar2adf3ac2016-05-03 17:12:58463 response_headers_ = server_maker_.GetResponseHeaders(status);
[email protected]92bf17c2014-03-03 21:14:03464 response_data_ = body;
[email protected]6cca996b2013-01-25 07:43:36465 }
[email protected]f702d572012-12-04 15:56:20466
Ryan Hamilton8d9ee76e2018-05-29 23:52:52467 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientDataPacket(
Fan Yangac867502019-01-28 21:10:23468 uint64_t packet_number,
[email protected]e8ff26842013-03-22 21:02:05469 bool should_include_version,
[email protected]f702d572012-12-04 15:56:20470 bool fin,
Victor Vasiliev47ecb6a2020-10-14 17:22:10471 absl::string_view data) {
Ryan Hamilton7505eb92019-06-08 00:22:17472 return client_maker_.MakeDataPacket(packet_number, stream_id_,
473 should_include_version, fin, data);
alyssar2adf3ac2016-05-03 17:12:58474 }
475
Ryan Hamilton8d9ee76e2018-05-29 23:52:52476 std::unique_ptr<quic::QuicReceivedPacket> ConstructServerDataPacket(
Fan Yangac867502019-01-28 21:10:23477 uint64_t packet_number,
alyssar2adf3ac2016-05-03 17:12:58478 bool should_include_version,
479 bool fin,
Victor Vasiliev47ecb6a2020-10-14 17:22:10480 absl::string_view data) {
Ryan Hamilton7505eb92019-06-08 00:22:17481 return server_maker_.MakeDataPacket(packet_number, stream_id_,
482 should_include_version, fin, data);
ckrasic3865ee0f2016-02-29 22:04:56483 }
484
Ryan Hamilton8d9ee76e2018-05-29 23:52:52485 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23486 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52487 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56488 bool should_include_version,
489 bool fin,
490 RequestPriority request_priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02491 size_t* spdy_headers_frame_length) {
Yixin Wang7a3f1b8d2018-01-17 21:40:48492 return InnerConstructRequestHeadersPacket(
493 packet_number, stream_id, should_include_version, fin, request_priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02494 0, spdy_headers_frame_length);
Yixin Wang7a3f1b8d2018-01-17 21:40:48495 }
496
Ryan Hamilton8d9ee76e2018-05-29 23:52:52497 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23498 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52499 quic::QuicStreamId stream_id,
Yixin Wang7a3f1b8d2018-01-17 21:40:48500 bool should_include_version,
501 bool fin,
502 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52503 quic::QuicStreamId parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02504 size_t* spdy_headers_frame_length) {
Ryan Hamilton0239aac2018-05-19 00:03:13505 spdy::SpdyPriority priority =
ckrasic3865ee0f2016-02-29 22:04:56506 ConvertRequestPriorityToQuicPriority(request_priority);
alyssar2adf3ac2016-05-03 17:12:58507 return client_maker_.MakeRequestHeadersPacket(
ckrasic3865ee0f2016-02-29 22:04:56508 packet_number, stream_id, should_include_version, fin, priority,
Yixin Wang7a3f1b8d2018-01-17 21:40:48509 std::move(request_headers_), parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02510 spdy_headers_frame_length);
[email protected]f702d572012-12-04 15:56:20511 }
512
Ryan Hamilton8d9ee76e2018-05-29 23:52:52513 std::unique_ptr<quic::QuicReceivedPacket>
Yixin Wange7ecc472018-03-06 19:00:25514 ConstructRequestHeadersAndDataFramesPacket(
Fan Yangac867502019-01-28 21:10:23515 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52516 quic::QuicStreamId stream_id,
Yixin Wange7ecc472018-03-06 19:00:25517 bool should_include_version,
518 bool fin,
519 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52520 quic::QuicStreamId parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25521 size_t* spdy_headers_frame_length,
522 const std::vector<std::string>& data_writes) {
Ryan Hamilton0239aac2018-05-19 00:03:13523 spdy::SpdyPriority priority =
Yixin Wange7ecc472018-03-06 19:00:25524 ConvertRequestPriorityToQuicPriority(request_priority);
525 return client_maker_.MakeRequestHeadersAndMultipleDataFramesPacket(
526 packet_number, stream_id, should_include_version, fin, priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02527 std::move(request_headers_), parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25528 spdy_headers_frame_length, data_writes);
529 }
530
Ryan Hamilton8d9ee76e2018-05-29 23:52:52531 std::unique_ptr<quic::QuicReceivedPacket> ConstructRequestAndRstPacket(
Fan Yangac867502019-01-28 21:10:23532 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52533 quic::QuicStreamId stream_id,
Yixin Wange7ecc472018-03-06 19:00:25534 bool should_include_version,
535 bool fin,
536 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52537 quic::QuicStreamId parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25538 size_t* spdy_headers_frame_length,
Ryan Hamiltonb5d4c5a2019-06-21 22:08:41539 quic::QuicRstStreamErrorCode error_code) {
Ryan Hamilton0239aac2018-05-19 00:03:13540 spdy::SpdyPriority priority =
Yixin Wange7ecc472018-03-06 19:00:25541 ConvertRequestPriorityToQuicPriority(request_priority);
542 return client_maker_.MakeRequestHeadersAndRstPacket(
543 packet_number, stream_id, should_include_version, fin, priority,
544 std::move(request_headers_), parent_stream_id,
Ryan Hamiltonb5d4c5a2019-06-21 22:08:41545 spdy_headers_frame_length, error_code);
Yixin Wange7ecc472018-03-06 19:00:25546 }
547
Ryan Hamilton8d9ee76e2018-05-29 23:52:52548 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructResponseHeadersPacket(
Fan Yangac867502019-01-28 21:10:23549 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52550 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56551 bool fin,
552 size_t* spdy_headers_frame_length) {
alyssar2adf3ac2016-05-03 17:12:58553 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26554 packet_number, stream_id, !kIncludeVersion, fin,
Ryan Hamilton0d65a8c2019-06-07 00:46:02555 std::move(response_headers_), spdy_headers_frame_length);
[email protected]1e960032013-12-20 19:00:20556 }
557
Ryan Hamilton8d9ee76e2018-05-29 23:52:52558 std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseHeadersPacket(
Fan Yangac867502019-01-28 21:10:23559 uint64_t packet_number,
sclittlec4dc1a32015-09-24 00:15:45560 bool fin,
561 size_t* spdy_headers_frame_length) {
ckrasic3865ee0f2016-02-29 22:04:56562 return InnerConstructResponseHeadersPacket(packet_number, stream_id_, fin,
563 spdy_headers_frame_length);
[email protected]1e960032013-12-20 19:00:20564 }
565
Ryan Hamilton8d9ee76e2018-05-29 23:52:52566 std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseTrailersPacket(
Fan Yangac867502019-01-28 21:10:23567 uint64_t packet_number,
xunjieli34291fe12016-03-02 13:58:38568 bool fin,
Bence Béky4c325e52020-10-22 20:48:01569 spdy::Http2HeaderBlock trailers,
Ryan Hamilton0d65a8c2019-06-07 00:46:02570 size_t* spdy_headers_frame_length) {
alyssar2adf3ac2016-05-03 17:12:58571 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26572 packet_number, stream_id_, !kIncludeVersion, fin, std::move(trailers),
Ryan Hamilton0d65a8c2019-06-07 00:46:02573 spdy_headers_frame_length);
xunjieli34291fe12016-03-02 13:58:38574 }
575
Ryan Hamilton8d9ee76e2018-05-29 23:52:52576 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientRstStreamErrorPacket(
Fan Yangac867502019-01-28 21:10:23577 uint64_t packet_number,
maksim.sisov84e20c92016-06-23 08:49:34578 bool include_version) {
579 return client_maker_.MakeRstPacket(packet_number, include_version,
580 stream_id_,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52581 quic::QUIC_ERROR_PROCESSING_STREAM);
maksim.sisov84e20c92016-06-23 08:49:34582 }
583
Ryan Hamilton8d9ee76e2018-05-29 23:52:52584 std::unique_ptr<quic::QuicReceivedPacket> ConstructAckAndRstStreamPacket(
Fan Yangac867502019-01-28 21:10:23585 uint64_t packet_number) {
Renjie Tangcd594f32020-07-11 20:18:34586 return client_maker_.MakeAckAndRstPacket(packet_number, !kIncludeVersion,
587 stream_id_,
588 quic::QUIC_STREAM_CANCELLED, 2, 1);
[email protected]c5e1aca2014-01-30 04:03:04589 }
590
Ryan Hamilton8d9ee76e2018-05-29 23:52:52591 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientAckPacket(
Fan Yangac867502019-01-28 21:10:23592 uint64_t packet_number,
593 uint64_t largest_received,
Renjie Tangcd594f32020-07-11 20:18:34594 uint64_t smallest_received) {
alyssar2adf3ac2016-05-03 17:12:58595 return client_maker_.MakeAckPacket(packet_number, largest_received,
Renjie Tangcd594f32020-07-11 20:18:34596 smallest_received);
alyssar2adf3ac2016-05-03 17:12:58597 }
598
Ryan Hamilton8d9ee76e2018-05-29 23:52:52599 std::unique_ptr<quic::QuicReceivedPacket> ConstructServerAckPacket(
Fan Yangac867502019-01-28 21:10:23600 uint64_t packet_number,
601 uint64_t largest_received,
602 uint64_t smallest_received,
603 uint64_t least_unacked) {
alyssar2adf3ac2016-05-03 17:12:58604 return server_maker_.MakeAckPacket(packet_number, largest_received,
Bence Béky7a45d4d2020-05-08 01:59:23605 smallest_received, least_unacked);
[email protected]63534512012-12-23 18:49:00606 }
607
Ryan Hamilton0d65a8c2019-06-07 00:46:02608 std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket() {
609 return client_maker_.MakeInitialSettingsPacket(1);
fayang3bcb8b502016-12-07 21:44:37610 }
611
Renjie Tangaadb84b2019-08-31 01:00:23612 std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket(
613 int packet_number) {
614 return client_maker_.MakeInitialSettingsPacket(packet_number);
615 }
616
Victor Vasiliev076657c2019-03-12 02:46:43617 std::string ConstructDataHeader(size_t body_len) {
Nick Harperc6cb7a612020-02-24 20:03:32618 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:41619 return "";
620 }
Victor Vasilievc617d452022-03-07 15:54:25621 quiche::QuicheBuffer buffer = quic::HttpEncoder::SerializeDataFrameHeader(
622 body_len, quiche::SimpleBufferAllocator::Get());
Ian Swett17d4d1c02021-06-08 19:52:41623 return std::string(buffer.data(), buffer.size());
Renjief49758b2019-01-11 23:32:41624 }
625
Ryan Hamilton8d9ee76e2018-05-29 23:52:52626 void ReceivePromise(quic::QuicStreamId id) {
627 auto headers = quic::test::AsHeaderList(push_promise_);
rch08e198572017-05-09 16:56:55628 QuicChromiumClientStream::Handle* stream =
ckrasic3865ee0f2016-02-29 22:04:56629 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
ckrasic32b17dcd2016-10-31 06:15:35630 stream->OnPromiseHeaderList(id, headers.uncompressed_header_bytes(),
631 headers);
ckrasic3865ee0f2016-02-29 22:04:56632 }
633
xunjieli84adaab2016-09-20 01:12:28634 void ExpectLoadTimingValid(const LoadTimingInfo& load_timing_info,
xunjieli100937eb52016-09-15 20:09:37635 bool session_reused) {
636 EXPECT_EQ(session_reused, load_timing_info.socket_reused);
xunjieli84adaab2016-09-20 01:12:28637 if (session_reused) {
638 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
639 } else {
640 ExpectConnectTimingHasTimes(
641 load_timing_info.connect_timing,
642 CONNECT_TIMING_HAS_SSL_TIMES | CONNECT_TIMING_HAS_DNS_TIMES);
643 }
644 ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info);
xunjieli100937eb52016-09-15 20:09:37645 }
646
Fan Yang32c5a112018-12-10 20:06:33647 quic::QuicStreamId GetNthClientInitiatedBidirectionalStreamId(int n) {
Nick Harper23290b82019-05-02 00:02:56648 return quic::test::GetNthClientInitiatedBidirectionalStreamId(
649 version_.transport_version, n);
ckrasicbf2f59c2017-05-04 23:54:36650 }
651
Fan Yang32c5a112018-12-10 20:06:33652 quic::QuicStreamId GetNthServerInitiatedUnidirectionalStreamId(int n) {
Nick Harper23290b82019-05-02 00:02:56653 return quic::test::GetNthServerInitiatedUnidirectionalStreamId(
654 version_.transport_version, n);
ckrasicbf2f59c2017-05-04 23:54:36655 }
656
Patrick Meenan0041f332022-05-19 23:48:35657 quic::test::QuicFlagSaver saver_;
Ryan Hamiltona1d1f4a2019-06-26 14:43:04658
Nick Harper23290b82019-05-02 00:02:56659 const quic::ParsedQuicVersion version_;
Yixin Wang079ad542018-01-11 04:06:05660 const bool client_headers_include_h2_stream_dependency_;
661
Matt Reichhoff0049a0b72021-10-20 20:44:26662 NetLogWithSource net_log_with_source_{
663 NetLogWithSource::Make(NetLog::Get(), NetLogSourceType::NONE)};
664 RecordingNetLogObserver net_log_observer_;
Keishi Hattori0e45c022021-11-27 09:25:52665 raw_ptr<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_;
Keishi Hattori0e45c022021-11-27 09:25:52669 raw_ptr<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_;
Tsuyoshi Horo432981d52022-06-09 09:50:13701 quic::test::MockRandom random_generator_{0};
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();
Ali Beyada0b1a1c2022-04-08 20:08:14728 stream_->RegisterRequest(&request_);
729 EXPECT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:26730 net_log_with_source_,
731 callback_.callback()));
rch08e198572017-05-09 16:56:55732 QuicChromiumClientStream::Handle* client_stream =
jri231c2972016-03-08 19:50:11733 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
Zhongyi Shibb28b1f2018-07-18 02:41:26734 EXPECT_FALSE(client_stream->can_migrate_to_cellular_network());
jri231c2972016-03-08 19:50:11735}
736
[email protected]1e960032013-12-20 19:00:20737TEST_P(QuicHttpStreamTest, GetRequest) {
738 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:45739 size_t spdy_request_header_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:23740 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:25741 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:23742 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:37743 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23744 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
745 kIncludeVersion, kFin, DEFAULT_PRIORITY,
746 &spdy_request_header_frame_length));
fayang3bcb8b502016-12-07 21:44:37747
[email protected]f702d572012-12-04 15:56:20748 Initialize();
749
750 request_.method = "GET";
rchcd379012017-04-12 21:53:32751 request_.url = GURL("https://www.example.org/");
[email protected]f702d572012-12-04 15:56:20752
xunjieli100937eb52016-09-15 20:09:37753 // Make sure getting load timing from the stream early does not crash.
754 LoadTimingInfo load_timing_info;
755 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
Ali Beyada0b1a1c2022-04-08 20:08:14756 stream_->RegisterRequest(&request_);
757 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:26758 net_log_with_source_,
759 callback_.callback()));
rjshaded5ced072015-12-18 19:26:02760 EXPECT_EQ(OK,
761 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20762
763 // Ack the request.
Renjie90e808e2019-01-24 07:24:04764 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]f702d572012-12-04 15:56:20765
robpercival214763f2016-07-01 23:27:01766 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
767 IsError(ERR_IO_PENDING));
[email protected]f702d572012-12-04 15:56:20768
Kenichi Ishibashif8634ab2021-03-16 23:41:28769 SetResponse("404", string());
sclittlec4dc1a32015-09-24 00:15:45770 size_t spdy_response_header_frame_length;
771 ProcessPacket(ConstructResponseHeadersPacket(
772 2, kFin, &spdy_response_header_frame_length));
[email protected]f702d572012-12-04 15:56:20773
774 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:01775 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]cadac622013-06-11 16:46:36776 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:20777 EXPECT_EQ(404, response_.headers->response_code());
778 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
[email protected]6ed67432014-06-24 01:53:53779 EXPECT_FALSE(response_.response_time.is_null());
780 EXPECT_FALSE(response_.request_time.is_null());
[email protected]f702d572012-12-04 15:56:20781
782 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:02783 EXPECT_EQ(0,
784 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
785 callback_.callback()));
[email protected]f702d572012-12-04 15:56:20786 EXPECT_TRUE(stream_->IsResponseBodyComplete());
787 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:10788
xunjieli100937eb52016-09-15 20:09:37789 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
xunjieli84adaab2016-09-20 01:12:28790 ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
xunjieli100937eb52016-09-15 20:09:37791
sclittle1edeeb22015-09-02 20:46:10792 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:45793 // headers and payload.
794 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
795 stream_->GetTotalSentBytes());
796 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length),
797 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:20798}
799
xunjieli100937eb52016-09-15 20:09:37800TEST_P(QuicHttpStreamTest, LoadTimingTwoRequests) {
801 SetRequest("GET", "/", DEFAULT_PRIORITY);
802 size_t spdy_request_header_frame_length;
803
Renjie Tangaadb84b2019-08-31 01:00:23804 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:25805 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:23806 AddWrite(ConstructInitialSettingsPacket(packet_number++));
xunjieli100937eb52016-09-15 20:09:37807 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23808 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
809 kIncludeVersion, kFin, DEFAULT_PRIORITY,
810 &spdy_request_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37811
812 // SetRequest() again for second request as |request_headers_| was moved.
813 SetRequest("GET", "/", DEFAULT_PRIORITY);
814 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23815 packet_number++, GetNthClientInitiatedBidirectionalStreamId(1),
816 kIncludeVersion, kFin, DEFAULT_PRIORITY,
817 GetNthClientInitiatedBidirectionalStreamId(0),
Ryan Hamilton0d65a8c2019-06-07 00:46:02818 &spdy_request_header_frame_length));
Renjie Tangcd594f32020-07-11 20:18:34819 AddWrite(
820 ConstructClientAckPacket(packet_number++, 3, 1)); // Ack the responses.
xunjieli100937eb52016-09-15 20:09:37821
822 Initialize();
823
824 request_.method = "GET";
rchcd379012017-04-12 21:53:32825 request_.url = GURL("https://www.example.org/");
xunjieli100937eb52016-09-15 20:09:37826 // Start first request.
Ali Beyada0b1a1c2022-04-08 20:08:14827 stream_->RegisterRequest(&request_);
828 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:26829 net_log_with_source_,
830 callback_.callback()));
xunjieli100937eb52016-09-15 20:09:37831 EXPECT_EQ(OK,
832 stream_->SendRequest(headers_, &response_, callback_.callback()));
833
834 // Start a second request.
Dan McArdle68a5f622021-07-09 20:56:53835 QuicHttpStream stream2(session_->CreateHandle(url::SchemeHostPort(
836 url::kHttpsScheme, "www.example.org", 443)),
837 {} /* dns_aliases */);
xunjieli100937eb52016-09-15 20:09:37838 TestCompletionCallback callback2;
Ali Beyada0b1a1c2022-04-08 20:08:14839 stream2.RegisterRequest(&request_);
Matt Reichhoff0049a0b72021-10-20 20:44:26840 EXPECT_EQ(
Ali Beyada0b1a1c2022-04-08 20:08:14841 OK, stream2.InitializeStream(true, DEFAULT_PRIORITY, net_log_with_source_,
842 callback2.callback()));
xunjieli100937eb52016-09-15 20:09:37843 EXPECT_EQ(OK,
844 stream2.SendRequest(headers_, &response_, callback2.callback()));
845
846 // Ack both requests.
Renjie90e808e2019-01-24 07:24:04847 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
xunjieli100937eb52016-09-15 20:09:37848
849 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
850 IsError(ERR_IO_PENDING));
851 size_t spdy_response_header_frame_length;
Kenichi Ishibashif8634ab2021-03-16 23:41:28852 SetResponse("200", string());
xunjieli100937eb52016-09-15 20:09:37853 ProcessPacket(InnerConstructResponseHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33854 2, GetNthClientInitiatedBidirectionalStreamId(0), kFin,
ckrasicbf2f59c2017-05-04 23:54:36855 &spdy_response_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37856
857 // Now that the headers have been processed, the callback will return.
858 EXPECT_THAT(callback_.WaitForResult(), IsOk());
859 EXPECT_EQ(200, response_.headers->response_code());
860
861 // There is no body, so this should return immediately.
862 EXPECT_EQ(0,
863 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
864 callback_.callback()));
865 EXPECT_TRUE(stream_->IsResponseBodyComplete());
866
867 LoadTimingInfo load_timing_info;
868 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
xunjieli84adaab2016-09-20 01:12:28869 ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
xunjieli100937eb52016-09-15 20:09:37870
871 // SetResponse() again for second request as |response_headers_| was moved.
Kenichi Ishibashif8634ab2021-03-16 23:41:28872 SetResponse("200", string());
xunjieli100937eb52016-09-15 20:09:37873 EXPECT_THAT(stream2.ReadResponseHeaders(callback2.callback()),
874 IsError(ERR_IO_PENDING));
875
876 ProcessPacket(InnerConstructResponseHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33877 3, GetNthClientInitiatedBidirectionalStreamId(1), kFin,
ckrasicbf2f59c2017-05-04 23:54:36878 &spdy_response_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37879
880 EXPECT_THAT(callback2.WaitForResult(), IsOk());
881
882 // There is no body, so this should return immediately.
883 EXPECT_EQ(0,
884 stream2.ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
885 callback2.callback()));
886 EXPECT_TRUE(stream2.IsResponseBodyComplete());
887
888 LoadTimingInfo load_timing_info2;
889 EXPECT_TRUE(stream2.GetLoadTimingInfo(&load_timing_info2));
xunjieli84adaab2016-09-20 01:12:28890 ExpectLoadTimingValid(load_timing_info2, /*session_reused=*/true);
xunjieli100937eb52016-09-15 20:09:37891}
892
xunjieli34291fe12016-03-02 13:58:38893// QuicHttpStream does not currently support trailers. It should ignore
894// trailers upon receiving them.
895TEST_P(QuicHttpStreamTest, GetRequestWithTrailers) {
896 SetRequest("GET", "/", DEFAULT_PRIORITY);
897 size_t spdy_request_header_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:23898 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:25899 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:23900 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:37901 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23902 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
903 kIncludeVersion, kFin, DEFAULT_PRIORITY,
904 &spdy_request_header_frame_length));
Renjie Tangcd594f32020-07-11 20:18:34905 AddWrite(
906 ConstructClientAckPacket(packet_number++, 3, 1)); // Ack the data packet.
xunjieli34291fe12016-03-02 13:58:38907
908 Initialize();
909
910 request_.method = "GET";
rchcd379012017-04-12 21:53:32911 request_.url = GURL("https://www.example.org/");
Ali Beyada0b1a1c2022-04-08 20:08:14912 stream_->RegisterRequest(&request_);
913 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:26914 net_log_with_source_,
915 callback_.callback()));
xunjieli5fafe142016-03-23 23:32:54916
xunjieli34291fe12016-03-02 13:58:38917 EXPECT_EQ(OK,
918 stream_->SendRequest(headers_, &response_, callback_.callback()));
xunjieli34291fe12016-03-02 13:58:38919 // Ack the request.
Renjie90e808e2019-01-24 07:24:04920 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
xunjieli34291fe12016-03-02 13:58:38921
robpercival214763f2016-07-01 23:27:01922 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
923 IsError(ERR_IO_PENDING));
xunjieli34291fe12016-03-02 13:58:38924
Kenichi Ishibashif8634ab2021-03-16 23:41:28925 SetResponse("200", string());
xunjieli34291fe12016-03-02 13:58:38926
927 // Send the response headers.
928 size_t spdy_response_header_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:02929 ProcessPacket(ConstructResponseHeadersPacket(
930 2, !kFin, &spdy_response_header_frame_length));
xunjieli34291fe12016-03-02 13:58:38931 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:01932 EXPECT_THAT(callback_.WaitForResult(), IsOk());
xunjieli34291fe12016-03-02 13:58:38933 ASSERT_TRUE(response_.headers.get());
934 EXPECT_EQ(200, response_.headers->response_code());
935 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
936 EXPECT_FALSE(response_.response_time.is_null());
937 EXPECT_FALSE(response_.request_time.is_null());
938
939 // Send the response body.
940 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:43941 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:17942 ProcessPacket(
943 ConstructServerDataPacket(3, false, !kFin, header + kResponseBody));
Bence Béky4c325e52020-10-22 20:48:01944 spdy::Http2HeaderBlock trailers;
xunjieli34291fe12016-03-02 13:58:38945 size_t spdy_trailers_frame_length;
946 trailers["foo"] = "bar";
Victor Vasiliev7da08172019-10-14 06:04:25947 if (!quic::VersionUsesHttp3(version_.transport_version)) {
Ryan Hamiltona1d1f4a2019-06-26 14:43:04948 trailers[quic::kFinalOffsetHeaderKey] =
949 base::NumberToString(strlen(kResponseBody) + header.length());
950 }
Ryan Hamilton0d65a8c2019-06-07 00:46:02951 ProcessPacket(ConstructResponseTrailersPacket(4, kFin, std::move(trailers),
952 &spdy_trailers_frame_length));
xunjieli34291fe12016-03-02 13:58:38953
954 // Make sure trailers are processed.
fdoray92e35a72016-06-10 15:54:55955 base::RunLoop().RunUntilIdle();
xunjieli34291fe12016-03-02 13:58:38956
957 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
958 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
959 callback_.callback()));
960 EXPECT_TRUE(stream_->IsResponseBodyComplete());
961
962 EXPECT_EQ(OK,
963 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
964 callback_.callback()));
965
966 EXPECT_TRUE(stream_->IsResponseBodyComplete());
967 EXPECT_TRUE(AtEof());
968
969 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
970 // headers and payload.
971 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
972 stream_->GetTotalSentBytes());
Renjief49758b2019-01-11 23:32:41973 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length +
974 strlen(kResponseBody) + header.length() +
975 +spdy_trailers_frame_length),
976 stream_->GetTotalReceivedBytes());
xunjieli5fafe142016-03-23 23:32:54977 // Check that NetLog was filled as expected.
Matt Reichhoff0049a0b72021-10-20 20:44:26978 auto entries = net_log_observer_.GetEntries();
xunjieli5fafe142016-03-23 23:32:54979 size_t pos = ExpectLogContainsSomewhere(
980 entries, /*min_offset=*/0,
mikecirone8b85c432016-09-08 19:11:00981 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
982 NetLogEventPhase::NONE);
xunjieli5fafe142016-03-23 23:32:54983 pos = ExpectLogContainsSomewhere(
984 entries, /*min_offset=*/pos,
mikecirone8b85c432016-09-08 19:11:00985 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
986 NetLogEventPhase::NONE);
xunjieli5fafe142016-03-23 23:32:54987 ExpectLogContainsSomewhere(
988 entries, /*min_offset=*/pos,
mikecirone8b85c432016-09-08 19:11:00989 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
990 NetLogEventPhase::NONE);
xunjieli34291fe12016-03-02 13:58:38991}
992
Bence Béky6c2c78f2020-08-28 16:49:06993TEST_P(QuicHttpStreamTest, ElideHeadersInNetLog) {
994 Initialize();
995
996 // QuicHttp3Logger is only used with HTTP/3.
997 if (!VersionUsesHttp3(version_.transport_version)) {
998 return;
999 }
1000
Matt Reichhoff0049a0b72021-10-20 20:44:261001 net_log_observer_.SetObserverCaptureMode(NetLogCaptureMode::kDefault);
Bence Béky6c2c78f2020-08-28 16:49:061002
Bence Békye0d3747d2020-08-28 23:16:401003 // Send first request.
Bence Béky6c2c78f2020-08-28 16:49:061004 SetRequest("GET", "/", DEFAULT_PRIORITY);
1005 request_.method = "GET";
1006 request_.url = GURL("https://www.example.org/");
1007 headers_.SetHeader(HttpRequestHeaders::kCookie, "secret");
1008
1009 size_t spdy_request_header_frame_length;
Bence Békye0d3747d2020-08-28 23:16:401010 int outgoing_packet_number = 1;
1011 AddWrite(ConstructInitialSettingsPacket(outgoing_packet_number++));
Bence Béky6c2c78f2020-08-28 16:49:061012 AddWrite(InnerConstructRequestHeadersPacket(
Bence Békye0d3747d2020-08-28 23:16:401013 outgoing_packet_number++, stream_id_, kIncludeVersion, kFin,
1014 DEFAULT_PRIORITY, &spdy_request_header_frame_length));
Bence Béky6c2c78f2020-08-28 16:49:061015
Ali Beyada0b1a1c2022-04-08 20:08:141016 stream_->RegisterRequest(&request_);
Matt Reichhoff0049a0b72021-10-20 20:44:261017 EXPECT_THAT(
Ali Beyada0b1a1c2022-04-08 20:08:141018 stream_->InitializeStream(true, DEFAULT_PRIORITY, net_log_with_source_,
1019 callback_.callback()),
Matt Reichhoff0049a0b72021-10-20 20:44:261020 IsOk());
Bence Béky6c2c78f2020-08-28 16:49:061021 EXPECT_THAT(stream_->SendRequest(headers_, &response_, callback_.callback()),
1022 IsOk());
Bence Békye0d3747d2020-08-28 23:16:401023 int incoming_packet_number = 1;
1024 ProcessPacket(ConstructServerAckPacket(incoming_packet_number++, 1, 1,
1025 1)); // Ack the request.
Bence Béky6c2c78f2020-08-28 16:49:061026
Bence Békye0d3747d2020-08-28 23:16:401027 // Process first response.
Kenichi Ishibashif8634ab2021-03-16 23:41:281028 SetResponse("200", string());
Bence Béky6c2c78f2020-08-28 16:49:061029 response_headers_["set-cookie"] = "secret";
1030 size_t spdy_response_header_frame_length;
1031 ProcessPacket(ConstructResponseHeadersPacket(
Bence Békye0d3747d2020-08-28 23:16:401032 incoming_packet_number++, kFin, &spdy_response_header_frame_length));
Bence Béky6c2c78f2020-08-28 16:49:061033 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
Bence Béky6c2c78f2020-08-28 16:49:061034
1035 ASSERT_TRUE(response_.headers.get());
1036 EXPECT_EQ(200, response_.headers->response_code());
1037 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1038 EXPECT_TRUE(response_.headers->HasHeaderValue("set-cookie", "secret"));
1039
Matt Reichhoff0049a0b72021-10-20 20:44:261040 net_log_observer_.SetObserverCaptureMode(
1041 NetLogCaptureMode::kIncludeSensitive);
Bence Béky6c2c78f2020-08-28 16:49:061042
Bence Békye0d3747d2020-08-28 23:16:401043 // Send second request.
1044 quic::QuicStreamId stream_id = GetNthClientInitiatedBidirectionalStreamId(1);
1045 request_.url = GURL("https://www.example.org/foo");
Bence Béky6c2c78f2020-08-28 16:49:061046
Bence Békye0d3747d2020-08-28 23:16:401047 AddWrite(InnerConstructRequestHeadersPacket(
1048 outgoing_packet_number++, stream_id, kIncludeVersion, kFin,
1049 DEFAULT_PRIORITY, &spdy_request_header_frame_length));
Bence Béky6c2c78f2020-08-28 16:49:061050
Bence Békye0d3747d2020-08-28 23:16:401051 auto stream = std::make_unique<QuicHttpStream>(
Dan McArdle68a5f622021-07-09 20:56:531052 session_->CreateHandle(
1053 url::SchemeHostPort(url::kHttpsScheme, "www.example.org/foo", 443)),
Eric Orthac661912022-01-10 21:44:171054 /*dns_aliases=*/std::set<std::string>());
Ali Beyada0b1a1c2022-04-08 20:08:141055 stream->RegisterRequest(&request_);
Matt Reichhoff0049a0b72021-10-20 20:44:261056 EXPECT_THAT(
Ali Beyada0b1a1c2022-04-08 20:08:141057 stream->InitializeStream(true, DEFAULT_PRIORITY, net_log_with_source_,
1058 callback_.callback()),
Matt Reichhoff0049a0b72021-10-20 20:44:261059 IsOk());
Bence Békye0d3747d2020-08-28 23:16:401060 EXPECT_THAT(stream->SendRequest(headers_, &response_, callback_.callback()),
1061 IsOk());
1062 ProcessPacket(ConstructServerAckPacket(incoming_packet_number++, 1, 1,
1063 1)); // Ack the request.
Bence Béky6c2c78f2020-08-28 16:49:061064
Bence Békye0d3747d2020-08-28 23:16:401065 // Process second response.
Kenichi Ishibashif8634ab2021-03-16 23:41:281066 SetResponse("200", string());
Bence Békye0d3747d2020-08-28 23:16:401067 response_headers_["set-cookie"] = "secret";
1068 ProcessPacket(InnerConstructResponseHeadersPacket(
1069 incoming_packet_number++, stream_id, kFin,
1070 &spdy_response_header_frame_length));
1071 EXPECT_THAT(stream->ReadResponseHeaders(callback_.callback()), IsOk());
Bence Béky6c2c78f2020-08-28 16:49:061072
Bence Békye0d3747d2020-08-28 23:16:401073 ASSERT_TRUE(response_.headers.get());
1074 EXPECT_EQ(200, response_.headers->response_code());
1075 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1076 EXPECT_TRUE(response_.headers->HasHeaderValue("set-cookie", "secret"));
1077
1078 EXPECT_TRUE(AtEof());
1079
1080 // Check that sensitive header value were stripped
1081 // for the first transaction (logged with NetLogCaptureMode::kDefault)
1082 // but not for the second (logged with NetLogCaptureMode::kIncludeSensitive).
1083 auto entries =
Matt Reichhoff0049a0b72021-10-20 20:44:261084 net_log_observer_.GetEntriesWithType(NetLogEventType::HTTP3_HEADERS_SENT);
Bence Békye0d3747d2020-08-28 23:16:401085 ASSERT_EQ(2u, entries.size());
1086 EXPECT_TRUE(
1087 CheckHeader(entries[0].params, "cookie", "[6 bytes were stripped]"));
1088 EXPECT_TRUE(CheckHeader(entries[1].params, "cookie", "secret"));
1089
Matt Reichhoff0049a0b72021-10-20 20:44:261090 entries = net_log_observer_.GetEntriesWithType(
1091 NetLogEventType::HTTP3_HEADERS_DECODED);
Bence Békye0d3747d2020-08-28 23:16:401092 ASSERT_EQ(2u, entries.size());
1093 EXPECT_TRUE(
1094 CheckHeader(entries[0].params, "set-cookie", "[6 bytes were stripped]"));
1095 EXPECT_TRUE(CheckHeader(entries[1].params, "set-cookie", "secret"));
Bence Béky6c2c78f2020-08-28 16:49:061096}
1097
[email protected]3e7dca62013-09-10 16:14:231098// Regression test for http://crbug.com/288128
[email protected]1e960032013-12-20 19:00:201099TEST_P(QuicHttpStreamTest, GetRequestLargeResponse) {
1100 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451101 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231102 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251103 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231104 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371105 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231106 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1107 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1108 &spdy_request_headers_frame_length));
[email protected]3e7dca62013-09-10 16:14:231109 Initialize();
1110
1111 request_.method = "GET";
rchcd379012017-04-12 21:53:321112 request_.url = GURL("https://www.example.org/");
[email protected]3e7dca62013-09-10 16:14:231113
Ali Beyada0b1a1c2022-04-08 20:08:141114 stream_->RegisterRequest(&request_);
1115 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261116 net_log_with_source_,
1117 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021118 EXPECT_EQ(OK,
1119 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:231120
1121 // Ack the request.
Renjie90e808e2019-01-24 07:24:041122 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]3e7dca62013-09-10 16:14:231123
robpercival214763f2016-07-01 23:27:011124 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1125 IsError(ERR_IO_PENDING));
[email protected]3e7dca62013-09-10 16:14:231126
Kenichi Ishibashif8634ab2021-03-16 23:41:281127 response_headers_[":status"] = "200";
bnc086b39e12016-06-24 13:05:261128 response_headers_[":version"] = "HTTP/1.1";
1129 response_headers_["content-type"] = "text/plain";
1130 response_headers_["big6"] = string(1000, 'x'); // Lots of x's.
[email protected]3e7dca62013-09-10 16:14:231131
sclittlec4dc1a32015-09-24 00:15:451132 size_t spdy_response_headers_frame_length;
1133 ProcessPacket(ConstructResponseHeadersPacket(
1134 2, kFin, &spdy_response_headers_frame_length));
[email protected]3e7dca62013-09-10 16:14:231135
1136 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:011137 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]3e7dca62013-09-10 16:14:231138 ASSERT_TRUE(response_.headers.get());
1139 EXPECT_EQ(200, response_.headers->response_code());
1140 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1141
1142 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:021143 EXPECT_EQ(0,
1144 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1145 callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:231146 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1147 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101148
1149 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451150 // headers and payload.
1151 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1152 stream_->GetTotalSentBytes());
1153 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length),
1154 stream_->GetTotalReceivedBytes());
[email protected]3e7dca62013-09-10 16:14:231155}
1156
rchf9f103cbc2014-08-30 05:28:041157// Regression test for http://crbug.com/409101
1158TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendRequest) {
1159 SetRequest("GET", "/", DEFAULT_PRIORITY);
1160 Initialize();
1161
1162 request_.method = "GET";
rchcd379012017-04-12 21:53:321163 request_.url = GURL("https://www.example.org/");
rchf9f103cbc2014-08-30 05:28:041164
Ali Beyada0b1a1c2022-04-08 20:08:141165 stream_->RegisterRequest(&request_);
1166 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261167 net_log_with_source_,
1168 callback_.callback()));
rchf9f103cbc2014-08-30 05:28:041169
jri78ec06a2016-03-31 18:19:401170 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521171 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rchf9f103cbc2014-08-30 05:28:041172
1173 EXPECT_EQ(ERR_CONNECTION_CLOSED,
rjshaded5ced072015-12-18 19:26:021174 stream_->SendRequest(headers_, &response_, callback_.callback()));
sclittle1edeeb22015-09-02 20:46:101175
1176 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1177 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rchf9f103cbc2014-08-30 05:28:041178}
1179
rch03b7a202016-02-05 00:54:201180// Regression test for http://crbug.com/584441
1181TEST_P(QuicHttpStreamTest, GetSSLInfoAfterSessionClosed) {
1182 SetRequest("GET", "/", DEFAULT_PRIORITY);
1183 Initialize();
1184
1185 request_.method = "GET";
rchcd379012017-04-12 21:53:321186 request_.url = GURL("https://www.example.org/");
rch03b7a202016-02-05 00:54:201187
Ali Beyada0b1a1c2022-04-08 20:08:141188 stream_->RegisterRequest(&request_);
1189 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261190 net_log_with_source_,
1191 callback_.callback()));
rch03b7a202016-02-05 00:54:201192
1193 SSLInfo ssl_info;
rch11565e02016-02-09 20:13:471194 EXPECT_FALSE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:201195 stream_->GetSSLInfo(&ssl_info);
rch11565e02016-02-09 20:13:471196 EXPECT_TRUE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:201197
jri78ec06a2016-03-31 18:19:401198 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521199 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rch03b7a202016-02-05 00:54:201200
rch11565e02016-02-09 20:13:471201 SSLInfo ssl_info2;
1202 stream_->GetSSLInfo(&ssl_info2);
1203 EXPECT_TRUE(ssl_info2.is_valid());
rch03b7a202016-02-05 00:54:201204}
1205
rchcd379012017-04-12 21:53:321206TEST_P(QuicHttpStreamTest, GetAlternativeService) {
1207 SetRequest("GET", "/", DEFAULT_PRIORITY);
1208 Initialize();
1209
1210 request_.method = "GET";
1211 request_.url = GURL("https://www.example.org/");
1212
Ali Beyada0b1a1c2022-04-08 20:08:141213 stream_->RegisterRequest(&request_);
1214 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261215 net_log_with_source_,
1216 callback_.callback()));
rchcd379012017-04-12 21:53:321217
1218 AlternativeService alternative_service;
1219 EXPECT_TRUE(stream_->GetAlternativeService(&alternative_service));
1220 EXPECT_EQ(AlternativeService(kProtoQUIC, "www.example.org", 443),
1221 alternative_service);
1222
1223 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521224 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rchcd379012017-04-12 21:53:321225
1226 AlternativeService alternative_service2;
1227 EXPECT_TRUE(stream_->GetAlternativeService(&alternative_service2));
1228 EXPECT_EQ(AlternativeService(kProtoQUIC, "www.example.org", 443),
1229 alternative_service2);
1230}
1231
zhongyica364fbb2015-12-12 03:39:121232TEST_P(QuicHttpStreamTest, LogGranularQuicConnectionError) {
1233 SetRequest("GET", "/", DEFAULT_PRIORITY);
1234 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231235 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251236 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231237 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371238 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231239 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1240 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1241 &spdy_request_headers_frame_length));
fayang3bcb8b502016-12-07 21:44:371242 AddWrite(ConstructAckAndRstStreamPacket(3));
zhongyica364fbb2015-12-12 03:39:121243 Initialize();
1244
1245 request_.method = "GET";
rchcd379012017-04-12 21:53:321246 request_.url = GURL("https://www.example.org/");
zhongyica364fbb2015-12-12 03:39:121247
Ali Beyada0b1a1c2022-04-08 20:08:141248 stream_->RegisterRequest(&request_);
1249 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261250 net_log_with_source_,
1251 callback_.callback()));
zhongyica364fbb2015-12-12 03:39:121252 EXPECT_EQ(OK,
1253 stream_->SendRequest(headers_, &response_, callback_.callback()));
1254
1255 // Ack the request.
Renjie90e808e2019-01-24 07:24:041256 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011257 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1258 IsError(ERR_IO_PENDING));
zhongyica364fbb2015-12-12 03:39:121259
Ryan Hamilton8d9ee76e2018-05-29 23:52:521260 quic::QuicConnectionCloseFrame frame;
Zhongyi Shica576df2019-04-12 17:43:401261 frame.quic_error_code = quic::QUIC_PEER_GOING_AWAY;
rch1c5b74a2016-06-23 22:10:551262 session_->connection()->OnConnectionCloseFrame(frame);
zhongyica364fbb2015-12-12 03:39:121263
1264 NetErrorDetails details;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521265 EXPECT_EQ(quic::QUIC_NO_ERROR, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121266 stream_->PopulateNetErrorDetails(&details);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521267 EXPECT_EQ(quic::QUIC_PEER_GOING_AWAY, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121268}
1269
Ryan Hamiltone316e482017-08-17 02:48:531270TEST_P(QuicHttpStreamTest, LogGranularQuicErrorIfHandshakeNotConfirmed) {
rch617e0652017-04-26 17:57:511271 // By default the test setup defaults handshake to be confirmed. Manually set
1272 // it to be not confirmed.
rch617e0652017-04-26 17:57:511273 crypto_client_stream_factory_.set_handshake_mode(
Ryan Hamilton9835e662018-08-02 05:36:271274 MockCryptoClientStream::ZERO_RTT);
rch617e0652017-04-26 17:57:511275
zhongyica364fbb2015-12-12 03:39:121276 SetRequest("GET", "/", DEFAULT_PRIORITY);
1277 size_t spdy_request_headers_frame_length;
Michael Warres167db3e2019-03-01 21:38:031278 client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
Nick Harper057264a82019-09-12 23:33:491279 client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
1280 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251281 if (VersionUsesHttp3(version_.transport_version))
Nick Harper057264a82019-09-12 23:33:491282 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371283 AddWrite(InnerConstructRequestHeadersPacket(
Nick Harper057264a82019-09-12 23:33:491284 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1285 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1286 &spdy_request_headers_frame_length));
zhongyica364fbb2015-12-12 03:39:121287 Initialize();
1288
1289 request_.method = "GET";
rchcd379012017-04-12 21:53:321290 request_.url = GURL("https://www.example.org/");
zhongyica364fbb2015-12-12 03:39:121291
Ali Beyada0b1a1c2022-04-08 20:08:141292 stream_->RegisterRequest(&request_);
1293 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261294 net_log_with_source_,
1295 callback_.callback()));
zhongyica364fbb2015-12-12 03:39:121296 EXPECT_EQ(OK,
1297 stream_->SendRequest(headers_, &response_, callback_.callback()));
1298
1299 // Ack the request.
Renjie90e808e2019-01-24 07:24:041300 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011301 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1302 IsError(ERR_IO_PENDING));
zhongyica364fbb2015-12-12 03:39:121303
Ryan Hamilton8d9ee76e2018-05-29 23:52:521304 quic::QuicConnectionCloseFrame frame;
Zhongyi Shica576df2019-04-12 17:43:401305 frame.quic_error_code = quic::QUIC_PEER_GOING_AWAY;
rch1c5b74a2016-06-23 22:10:551306 session_->connection()->OnConnectionCloseFrame(frame);
zhongyica364fbb2015-12-12 03:39:121307
1308 NetErrorDetails details;
zhongyica364fbb2015-12-12 03:39:121309 stream_->PopulateNetErrorDetails(&details);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521310 EXPECT_EQ(quic::QUIC_PEER_GOING_AWAY, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121311}
1312
rch11a114a2014-09-04 23:41:591313// Regression test for http://crbug.com/409871
1314TEST_P(QuicHttpStreamTest, SessionClosedBeforeReadResponseHeaders) {
1315 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451316 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231317 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251318 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231319 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371320 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231321 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1322 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1323 &spdy_request_headers_frame_length));
rch11a114a2014-09-04 23:41:591324 Initialize();
1325
1326 request_.method = "GET";
rchcd379012017-04-12 21:53:321327 request_.url = GURL("https://www.example.org/");
rch11a114a2014-09-04 23:41:591328
Ali Beyada0b1a1c2022-04-08 20:08:141329 stream_->RegisterRequest(&request_);
1330 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261331 net_log_with_source_,
1332 callback_.callback()));
rch11a114a2014-09-04 23:41:591333
rjshaded5ced072015-12-18 19:26:021334 EXPECT_EQ(OK,
1335 stream_->SendRequest(headers_, &response_, callback_.callback()));
rch11a114a2014-09-04 23:41:591336
jri78ec06a2016-03-31 18:19:401337 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521338 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rch11a114a2014-09-04 23:41:591339
1340 EXPECT_NE(OK, stream_->ReadResponseHeaders(callback_.callback()));
sclittle1edeeb22015-09-02 20:46:101341
1342 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451343 // headers and payload.
1344 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1345 stream_->GetTotalSentBytes());
sclittle1edeeb22015-09-02 20:46:101346 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rch11a114a2014-09-04 23:41:591347}
1348
[email protected]1e960032013-12-20 19:00:201349TEST_P(QuicHttpStreamTest, SendPostRequest) {
1350 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451351 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231352 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251353 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231354 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Yixin Wange7ecc472018-03-06 19:00:251355
Victor Vasiliev076657c2019-03-12 02:46:431356 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:321357 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411358 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231359 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1360 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1361 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411362 } else {
1363 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231364 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1365 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1366 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411367 }
Yixin Wange7ecc472018-03-06 19:00:251368
Renjie Tangcd594f32020-07-11 20:18:341369 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]f702d572012-12-04 15:56:201370
1371 Initialize();
1372
danakjad1777e2016-04-16 00:56:421373 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:191374 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
ricea2deef682016-09-09 08:04:071375 kUploadData, strlen(kUploadData)));
rch97827ee2017-05-24 23:49:121376 upload_data_stream_ =
Jeremy Roman0579ed62017-08-29 15:56:191377 std::make_unique<ElementsUploadDataStream>(std::move(element_readers), 0);
[email protected]f702d572012-12-04 15:56:201378 request_.method = "POST";
rchcd379012017-04-12 21:53:321379 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121380 request_.upload_data_stream = upload_data_stream_.get();
Bence Békyd8a21fc32018-06-27 18:29:581381 ASSERT_THAT(request_.upload_data_stream->Init(CompletionOnceCallback(),
tfarina42834112016-09-22 13:38:201382 NetLogWithSource()),
1383 IsOk());
[email protected]f702d572012-12-04 15:56:201384
Ali Beyada0b1a1c2022-04-08 20:08:141385 stream_->RegisterRequest(&request_);
1386 EXPECT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261387 net_log_with_source_,
1388 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021389 EXPECT_EQ(OK,
1390 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:201391
1392 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041393 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]f702d572012-12-04 15:56:201394
1395 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281396 SetResponse("200", string());
sclittlec4dc1a32015-09-24 00:15:451397 size_t spdy_response_headers_frame_length;
1398 ProcessPacket(ConstructResponseHeadersPacket(
1399 2, !kFin, &spdy_response_headers_frame_length));
[email protected]f702d572012-12-04 15:56:201400
rchfb47f712017-05-21 03:24:001401 // The headers have already arrived.
1402 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]cadac622013-06-11 16:46:361403 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:201404 EXPECT_EQ(200, response_.headers->response_code());
1405 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1406
1407 // Send the response body.
1408 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431409 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:411410 ProcessPacket(
Ryan Hamilton7505eb92019-06-08 00:22:171411 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
[email protected]f702d572012-12-04 15:56:201412 // Since the body has already arrived, this should return immediately.
1413 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
1414 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1415 callback_.callback()));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291416 EXPECT_EQ(0,
1417 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1418 callback_.callback()));
1419
1420 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1421 EXPECT_TRUE(AtEof());
1422
1423 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
1424 // headers and payload.
1425 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411426 strlen(kUploadData) + header.length()),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291427 stream_->GetTotalSentBytes());
1428 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411429 strlen(kResponseBody) + header2.length()),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291430 stream_->GetTotalReceivedBytes());
1431}
1432
1433TEST_P(QuicHttpStreamTest, SendPostRequestAndReceiveSoloFin) {
1434 SetRequest("POST", "/", DEFAULT_PRIORITY);
1435 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231436 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251437 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231438 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431439 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:321440 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411441 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231442 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1443 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1444 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411445 } else {
1446 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231447 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1448 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1449 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411450 }
1451
Renjie Tangcd594f32020-07-11 20:18:341452 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291453
1454 Initialize();
1455
1456 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:191457 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
Ryan Hamilton2ef0a9c2017-07-25 03:18:291458 kUploadData, strlen(kUploadData)));
1459 upload_data_stream_ =
Jeremy Roman0579ed62017-08-29 15:56:191460 std::make_unique<ElementsUploadDataStream>(std::move(element_readers), 0);
Ryan Hamilton2ef0a9c2017-07-25 03:18:291461 request_.method = "POST";
1462 request_.url = GURL("https://www.example.org/");
1463 request_.upload_data_stream = upload_data_stream_.get();
Bence Békyd8a21fc32018-06-27 18:29:581464 ASSERT_THAT(request_.upload_data_stream->Init(CompletionOnceCallback(),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291465 NetLogWithSource()),
1466 IsOk());
1467
Ali Beyada0b1a1c2022-04-08 20:08:141468 stream_->RegisterRequest(&request_);
1469 EXPECT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261470 net_log_with_source_,
1471 callback_.callback()));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291472 EXPECT_EQ(OK,
1473 stream_->SendRequest(headers_, &response_, callback_.callback()));
1474
1475 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041476 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291477
1478 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281479 SetResponse("200", string());
Ryan Hamilton2ef0a9c2017-07-25 03:18:291480 size_t spdy_response_headers_frame_length;
1481 ProcessPacket(ConstructResponseHeadersPacket(
1482 2, !kFin, &spdy_response_headers_frame_length));
1483
1484 // The headers have already arrived.
1485 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
1486 ASSERT_TRUE(response_.headers.get());
1487 EXPECT_EQ(200, response_.headers->response_code());
1488 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1489
1490 // Send the response body.
1491 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431492 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:411493 ProcessPacket(
Ryan Hamilton7505eb92019-06-08 00:22:171494 ConstructServerDataPacket(3, false, !kFin, header2 + kResponseBody));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291495 // Since the body has already arrived, this should return immediately.
1496 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
1497 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1498 callback_.callback()));
Ryan Hamilton7505eb92019-06-08 00:22:171499 ProcessPacket(ConstructServerDataPacket(4, false, kFin, ""));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291500 EXPECT_EQ(0,
1501 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1502 callback_.callback()));
[email protected]f702d572012-12-04 15:56:201503
1504 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1505 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101506
1507 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451508 // headers and payload.
1509 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411510 strlen(kUploadData) + header.length()),
sclittle1edeeb22015-09-02 20:46:101511 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451512 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411513 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101514 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:201515}
1516
[email protected]1e960032013-12-20 19:00:201517TEST_P(QuicHttpStreamTest, SendChunkedPostRequest) {
1518 SetRequest("POST", "/", DEFAULT_PRIORITY);
[email protected]c9e49a02013-02-26 05:56:471519 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:451520 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231521 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251522 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231523 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431524 std::string header = ConstructDataHeader(chunk_size);
Nick Harperc6cb7a612020-02-24 20:03:321525 if (version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411526 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231527 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1528 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1529 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjie Tangd5133972019-12-06 00:20:281530 AddWrite(ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin,
1531 {header + kUploadData}));
Renjief49758b2019-01-11 23:32:411532 } else {
1533 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231534 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1535 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1536 &spdy_request_headers_frame_length, {kUploadData}));
1537 AddWrite(ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin,
1538 kUploadData));
Renjief49758b2019-01-11 23:32:411539 }
1540
Renjie Tangcd594f32020-07-11 20:18:341541 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]c9e49a02013-02-26 05:56:471542 Initialize();
1543
Jeremy Roman0579ed62017-08-29 15:56:191544 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121545 auto* chunked_upload_stream =
1546 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1547 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
[email protected]c9e49a02013-02-26 05:56:471548
1549 request_.method = "POST";
rchcd379012017-04-12 21:53:321550 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121551 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071552 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201553 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]c9e49a02013-02-26 05:56:471554
Ali Beyada0b1a1c2022-04-08 20:08:141555 stream_->RegisterRequest(&request_);
1556 ASSERT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261557 net_log_with_source_,
1558 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021559 ASSERT_EQ(ERR_IO_PENDING,
1560 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]c9e49a02013-02-26 05:56:471561
rch97827ee2017-05-24 23:49:121562 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
robpercival214763f2016-07-01 23:27:011563 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]c9e49a02013-02-26 05:56:471564
1565 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041566 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]c9e49a02013-02-26 05:56:471567
1568 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281569 SetResponse("200", string());
sclittlec4dc1a32015-09-24 00:15:451570 size_t spdy_response_headers_frame_length;
1571 ProcessPacket(ConstructResponseHeadersPacket(
1572 2, !kFin, &spdy_response_headers_frame_length));
[email protected]c9e49a02013-02-26 05:56:471573
rchfb47f712017-05-21 03:24:001574 // The headers have already arrived.
1575 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]cadac622013-06-11 16:46:361576 ASSERT_TRUE(response_.headers.get());
[email protected]c9e49a02013-02-26 05:56:471577 EXPECT_EQ(200, response_.headers->response_code());
1578 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1579
1580 // Send the response body.
1581 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431582 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171583 ProcessPacket(
1584 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
[email protected]c9e49a02013-02-26 05:56:471585
1586 // Since the body has already arrived, this should return immediately.
1587 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1588 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1589 callback_.callback()));
1590
1591 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1592 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101593
1594 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451595 // headers and payload.
1596 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411597 strlen(kUploadData) * 2 + header.length() * 2),
sclittle1edeeb22015-09-02 20:46:101598 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451599 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411600 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101601 stream_->GetTotalReceivedBytes());
[email protected]c9e49a02013-02-26 05:56:471602}
1603
[email protected]16ba7742014-08-22 00:57:251604TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithFinalEmptyDataPacket) {
1605 SetRequest("POST", "/", DEFAULT_PRIORITY);
1606 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:451607 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231608 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251609 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231610 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431611 std::string header = ConstructDataHeader(chunk_size);
Renjief49758b2019-01-11 23:32:411612
Nick Harperc6cb7a612020-02-24 20:03:321613 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411614 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231615 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1616 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1617 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411618 } else {
1619 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231620 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1621 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1622 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411623 }
Renjie Tangaadb84b2019-08-31 01:00:231624 AddWrite(
1625 ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin, ""));
Renjie Tangcd594f32020-07-11 20:18:341626 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]16ba7742014-08-22 00:57:251627 Initialize();
1628
Jeremy Roman0579ed62017-08-29 15:56:191629 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121630 auto* chunked_upload_stream =
1631 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1632 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
[email protected]16ba7742014-08-22 00:57:251633
1634 request_.method = "POST";
rchcd379012017-04-12 21:53:321635 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121636 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071637 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201638 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]16ba7742014-08-22 00:57:251639
Ali Beyada0b1a1c2022-04-08 20:08:141640 stream_->RegisterRequest(&request_);
1641 ASSERT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261642 net_log_with_source_,
1643 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021644 ASSERT_EQ(ERR_IO_PENDING,
1645 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251646
rch97827ee2017-05-24 23:49:121647 chunked_upload_stream->AppendData(nullptr, 0, true);
robpercival214763f2016-07-01 23:27:011648 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]16ba7742014-08-22 00:57:251649
Renjie90e808e2019-01-24 07:24:041650 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]16ba7742014-08-22 00:57:251651
1652 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281653 SetResponse("200", string());
sclittlec4dc1a32015-09-24 00:15:451654 size_t spdy_response_headers_frame_length;
1655 ProcessPacket(ConstructResponseHeadersPacket(
1656 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251657
rchfb47f712017-05-21 03:24:001658 // The headers have already arrived.
1659 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]16ba7742014-08-22 00:57:251660 ASSERT_TRUE(response_.headers.get());
1661 EXPECT_EQ(200, response_.headers->response_code());
1662 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1663
1664 // Send the response body.
1665 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431666 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171667 ProcessPacket(
1668 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
[email protected]16ba7742014-08-22 00:57:251669
rchb27683c2015-07-29 23:53:501670 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251671 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1672 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1673 callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251674 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1675 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101676
1677 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451678 // headers and payload.
1679 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411680 strlen(kUploadData) + header.length()),
sclittle1edeeb22015-09-02 20:46:101681 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451682 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411683 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101684 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251685}
1686
1687TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithOneEmptyDataPacket) {
1688 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451689 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231690 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251691 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231692 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371693 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231694 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1695 kIncludeVersion, !kFin, DEFAULT_PRIORITY,
1696 &spdy_request_headers_frame_length));
1697 AddWrite(
1698 ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin, ""));
Renjie Tangcd594f32020-07-11 20:18:341699 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]16ba7742014-08-22 00:57:251700 Initialize();
1701
Jeremy Roman0579ed62017-08-29 15:56:191702 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121703 auto* chunked_upload_stream =
1704 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
[email protected]16ba7742014-08-22 00:57:251705
1706 request_.method = "POST";
rchcd379012017-04-12 21:53:321707 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121708 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071709 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201710 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]16ba7742014-08-22 00:57:251711
Ali Beyada0b1a1c2022-04-08 20:08:141712 stream_->RegisterRequest(&request_);
1713 ASSERT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261714 net_log_with_source_,
1715 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021716 ASSERT_EQ(ERR_IO_PENDING,
1717 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251718
rch97827ee2017-05-24 23:49:121719 chunked_upload_stream->AppendData(nullptr, 0, true);
robpercival214763f2016-07-01 23:27:011720 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]16ba7742014-08-22 00:57:251721
Renjie90e808e2019-01-24 07:24:041722 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]16ba7742014-08-22 00:57:251723
1724 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281725 SetResponse("200", string());
sclittlec4dc1a32015-09-24 00:15:451726 size_t spdy_response_headers_frame_length;
1727 ProcessPacket(ConstructResponseHeadersPacket(
1728 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251729
rchfb47f712017-05-21 03:24:001730 // The headers have already arrived.
1731 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]16ba7742014-08-22 00:57:251732 ASSERT_TRUE(response_.headers.get());
1733 EXPECT_EQ(200, response_.headers->response_code());
1734 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1735
1736 // Send the response body.
1737 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431738 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171739 ProcessPacket(
1740 ConstructServerDataPacket(3, false, kFin, header + kResponseBody));
[email protected]16ba7742014-08-22 00:57:251741
rchb27683c2015-07-29 23:53:501742 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251743 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1744 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1745 callback_.callback()));
1746
1747 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1748 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101749
1750 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451751 // headers and payload.
1752 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1753 stream_->GetTotalSentBytes());
1754 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411755 strlen(kResponseBody) + header.length()),
sclittle1edeeb22015-09-02 20:46:101756 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251757}
1758
Bence Békye3c6f122020-05-08 01:09:471759TEST_P(QuicHttpStreamTest, SendChunkedPostRequestAbortedByResetStream) {
1760 SetRequest("POST", "/", DEFAULT_PRIORITY);
1761 size_t chunk_size = strlen(kUploadData);
1762 size_t spdy_request_headers_frame_length;
1763 int packet_number = 1;
1764
1765 if (version_.UsesHttp3()) {
1766 AddWrite(ConstructInitialSettingsPacket(packet_number++));
1767 }
1768
1769 std::string header = ConstructDataHeader(chunk_size);
1770 if (version_.HasIetfQuicFrames()) {
1771 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1772 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1773 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1774 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjie Tangcd594f32020-07-11 20:18:341775 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
Fan Yang8d4177792021-07-16 17:48:531776 AddWrite(client_maker_.MakeAckAndRstPacket(
1777 packet_number++, true, stream_id_, quic::QUIC_STREAM_NO_ERROR, 4, 1,
Renjie Tangcd594f32020-07-11 20:18:341778 /* include_stop_sending_if_v99 = */ false));
Bence Békye3c6f122020-05-08 01:09:471779 } else {
1780 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1781 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1782 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1783 &spdy_request_headers_frame_length, {kUploadData}));
Renjie Tangcd594f32020-07-11 20:18:341784 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
Bence Békye3c6f122020-05-08 01:09:471785 AddWrite(client_maker_.MakeAckAndRstPacket(
1786 packet_number++,
1787 /* include_version = */ false, stream_id_,
Renjie Tangcd594f32020-07-11 20:18:341788 quic::QUIC_RST_ACKNOWLEDGEMENT, 4, 1,
Bence Békye3c6f122020-05-08 01:09:471789 /* include_stop_sending_if_v99 = */ false));
1790 }
1791
1792 Initialize();
1793
1794 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
1795 auto* chunked_upload_stream =
1796 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1797 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
1798
1799 request_.method = "POST";
1800 request_.url = GURL("https://www.example.org/");
1801 request_.upload_data_stream = upload_data_stream_.get();
1802 ASSERT_THAT(request_.upload_data_stream->Init(
1803 TestCompletionCallback().callback(), NetLogWithSource()),
1804 IsOk());
Ali Beyada0b1a1c2022-04-08 20:08:141805 stream_->RegisterRequest(&request_);
Matt Reichhoff0049a0b72021-10-20 20:44:261806 ASSERT_THAT(
Ali Beyada0b1a1c2022-04-08 20:08:141807 stream_->InitializeStream(false, DEFAULT_PRIORITY, net_log_with_source_,
1808 callback_.callback()),
Matt Reichhoff0049a0b72021-10-20 20:44:261809 IsOk());
Bence Békye3c6f122020-05-08 01:09:471810 ASSERT_THAT(stream_->SendRequest(headers_, &response_, callback_.callback()),
1811 IsError(ERR_IO_PENDING));
1812
1813 // Ack both packets in the request.
1814 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
1815
1816 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281817 SetResponse("200", string());
Bence Békye3c6f122020-05-08 01:09:471818 size_t spdy_response_headers_frame_length;
1819 ProcessPacket(ConstructResponseHeadersPacket(
1820 2, !kFin, &spdy_response_headers_frame_length));
1821
1822 // Send the response body.
1823 const char kResponseBody[] = "Hello world!";
1824 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
1825 ProcessPacket(
1826 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
1827
Bence Béky050ec6d2021-02-25 22:07:051828 if (version_.HasIetfQuicFrames()) {
1829 // In IETF QUIC, the server uses a STOP_SENDING frame to notify the client
1830 // that it does not need any further data to fully process the request.
1831 ProcessPacket(server_maker_.MakeStopSendingPacket(
1832 4, /* include_version = */ false, stream_id_,
1833 quic::QUIC_STREAM_NO_ERROR));
1834 } else {
1835 // Server resets stream with H3_NO_ERROR before request body is complete.
1836 ProcessPacket(server_maker_.MakeRstPacket(4, /* include_version = */ false,
1837 stream_id_,
1838 quic::QUIC_STREAM_NO_ERROR));
1839 }
Bence Békye3c6f122020-05-08 01:09:471840
1841 // Finish feeding request body to QuicHttpStream. Data will be discarded.
1842 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1843 EXPECT_THAT(callback_.WaitForResult(), IsOk());
1844
1845 // Verify response.
1846 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
1847 ASSERT_TRUE(response_.headers.get());
1848 EXPECT_EQ(200, response_.headers->response_code());
1849 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1850 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1851 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1852 callback_.callback()));
1853 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1854 EXPECT_TRUE(AtEof());
1855
1856 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
1857 // headers and payload.
1858 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
1859 strlen(kUploadData) + header.length()),
1860 stream_->GetTotalSentBytes());
1861 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1862 strlen(kResponseBody) + header2.length()),
1863 stream_->GetTotalReceivedBytes());
1864}
1865
[email protected]1e960032013-12-20 19:00:201866TEST_P(QuicHttpStreamTest, DestroyedEarly) {
1867 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451868 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231869 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251870 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231871 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371872 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231873 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1874 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1875 &spdy_request_headers_frame_length));
1876 AddWrite(ConstructAckAndRstStreamPacket(packet_number++));
[email protected]63534512012-12-23 18:49:001877 Initialize();
1878
1879 request_.method = "GET";
rchcd379012017-04-12 21:53:321880 request_.url = GURL("https://www.example.org/");
[email protected]63534512012-12-23 18:49:001881
Ali Beyada0b1a1c2022-04-08 20:08:141882 stream_->RegisterRequest(&request_);
1883 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261884 net_log_with_source_,
1885 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021886 EXPECT_EQ(OK,
1887 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]63534512012-12-23 18:49:001888
1889 // Ack the request.
Renjie90e808e2019-01-24 07:24:041890 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
rchfb47f712017-05-21 03:24:001891 EXPECT_THAT(stream_->ReadResponseHeaders(
Yannic Bonenberger3c96beb2019-09-03 20:41:371892 base::BindOnce(&QuicHttpStreamTest::CloseStream,
1893 base::Unretained(this), stream_.get())),
robpercival214763f2016-07-01 23:27:011894 IsError(ERR_IO_PENDING));
[email protected]63534512012-12-23 18:49:001895
1896 // Send the response with a body.
Kenichi Ishibashif8634ab2021-03-16 23:41:281897 SetResponse("404", "hello world!");
[email protected]63534512012-12-23 18:49:001898 // In the course of processing this packet, the QuicHttpStream close itself.
rchfb47f712017-05-21 03:24:001899 size_t response_size = 0;
rch1bcfddf22017-06-03 00:26:291900 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin, &response_size));
[email protected]63534512012-12-23 18:49:001901
fdoray92e35a72016-06-10 15:54:551902 base::RunLoop().RunUntilIdle();
rchb27683c2015-07-29 23:53:501903
[email protected]63534512012-12-23 18:49:001904 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101905
1906 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451907 // headers and payload.
1908 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1909 stream_->GetTotalSentBytes());
rchfb47f712017-05-21 03:24:001910 // The stream was closed after receiving the headers.
1911 EXPECT_EQ(static_cast<int64_t>(response_size),
1912 stream_->GetTotalReceivedBytes());
[email protected]63534512012-12-23 18:49:001913}
1914
[email protected]1e960032013-12-20 19:00:201915TEST_P(QuicHttpStreamTest, Priority) {
1916 SetRequest("GET", "/", MEDIUM);
sclittlec4dc1a32015-09-24 00:15:451917 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231918 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251919 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231920 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371921 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231922 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1923 kIncludeVersion, kFin, MEDIUM, &spdy_request_headers_frame_length));
[email protected]24e5bc52013-09-18 15:36:581924 Initialize();
1925
1926 request_.method = "GET";
rchcd379012017-04-12 21:53:321927 request_.url = GURL("https://www.example.org/");
[email protected]24e5bc52013-09-18 15:36:581928
Ali Beyada0b1a1c2022-04-08 20:08:141929 stream_->RegisterRequest(&request_);
1930 EXPECT_EQ(OK, stream_->InitializeStream(true, MEDIUM, net_log_with_source_,
Matt Reichhoff0049a0b72021-10-20 20:44:261931 callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581932
rjshaded5ced072015-12-18 19:26:021933 EXPECT_EQ(OK,
1934 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581935
[email protected]24e5bc52013-09-18 15:36:581936 // Ack the request.
Renjie90e808e2019-01-24 07:24:041937 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011938 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1939 IsError(ERR_IO_PENDING));
[email protected]24e5bc52013-09-18 15:36:581940
1941 // Send the response with a body.
Kenichi Ishibashif8634ab2021-03-16 23:41:281942 SetResponse("404", "hello world!");
rchfb47f712017-05-21 03:24:001943 size_t response_size = 0;
1944 ProcessPacket(ConstructResponseHeadersPacket(2, kFin, &response_size));
[email protected]24e5bc52013-09-18 15:36:581945
rchfb47f712017-05-21 03:24:001946 EXPECT_EQ(OK, callback_.WaitForResult());
rchb27683c2015-07-29 23:53:501947
[email protected]24e5bc52013-09-18 15:36:581948 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101949
1950 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451951 // headers and payload.
1952 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1953 stream_->GetTotalSentBytes());
rchfb47f712017-05-21 03:24:001954 EXPECT_EQ(static_cast<int64_t>(response_size),
1955 stream_->GetTotalReceivedBytes());
[email protected]24e5bc52013-09-18 15:36:581956}
1957
xunjieli8dff50b2016-07-22 14:19:061958TEST_P(QuicHttpStreamTest, SessionClosedDuringDoLoop) {
1959 SetRequest("POST", "/", DEFAULT_PRIORITY);
1960 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231961 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251962 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231963 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431964 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:321965 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411966 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231967 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1968 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1969 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411970 } else {
1971 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231972 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1973 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1974 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411975 }
1976
xunjieli8dff50b2016-07-22 14:19:061977 // Second data write will result in a synchronous failure which will close
1978 // the session.
1979 AddWrite(SYNCHRONOUS, ERR_FAILED);
1980 Initialize();
1981
Jeremy Roman0579ed62017-08-29 15:56:191982 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121983 auto* chunked_upload_stream =
1984 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
xunjieli8dff50b2016-07-22 14:19:061985
1986 request_.method = "POST";
rchcd379012017-04-12 21:53:321987 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121988 request_.upload_data_stream = upload_data_stream_.get();
xunjieli8dff50b2016-07-22 14:19:061989 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201990 TestCompletionCallback().callback(), NetLogWithSource()));
xunjieli8dff50b2016-07-22 14:19:061991
1992 size_t chunk_size = strlen(kUploadData);
rch97827ee2017-05-24 23:49:121993 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
Ali Beyada0b1a1c2022-04-08 20:08:141994 stream_->RegisterRequest(&request_);
1995 ASSERT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261996 net_log_with_source_,
1997 callback_.callback()));
xunjieli8dff50b2016-07-22 14:19:061998 QuicHttpStream* stream = stream_.get();
1999 DeleteStreamCallback delete_stream_callback(std::move(stream_));
2000 // SendRequest() completes asynchronously after the final chunk is added.
Yixin Wange7ecc472018-03-06 19:00:252001 // Error does not surface yet since packet write is triggered by a packet
2002 // flusher that tries to bundle request body writes.
xunjieli8dff50b2016-07-22 14:19:062003 ASSERT_EQ(ERR_IO_PENDING,
2004 stream->SendRequest(headers_, &response_, callback_.callback()));
rch97827ee2017-05-24 23:49:122005 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
xunjieli8dff50b2016-07-22 14:19:062006 int rv = callback_.WaitForResult();
Yixin Wange7ecc472018-03-06 19:00:252007 EXPECT_EQ(OK, rv);
2008 // Error will be surfaced once an attempt to read the response occurs.
2009 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
2010 stream->ReadResponseHeaders(callback_.callback()));
xunjieli8dff50b2016-07-22 14:19:062011}
2012
rtenneti15656ae2016-01-23 03:05:032013TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersComplete) {
2014 SetRequest("POST", "/", DEFAULT_PRIORITY);
Victor Vasiliev7da08172019-10-14 06:04:252015 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232016 AddWrite(ConstructInitialSettingsPacket());
rtenneti15656ae2016-01-23 03:05:032017 AddWrite(SYNCHRONOUS, ERR_FAILED);
2018 Initialize();
2019
Jeremy Roman0579ed62017-08-29 15:56:192020 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
Yixin Wange7ecc472018-03-06 19:00:252021 auto* chunked_upload_stream =
2022 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
rtenneti15656ae2016-01-23 03:05:032023
2024 request_.method = "POST";
rchcd379012017-04-12 21:53:322025 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122026 request_.upload_data_stream = upload_data_stream_.get();
rtenneti15656ae2016-01-23 03:05:032027 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202028 TestCompletionCallback().callback(), NetLogWithSource()));
rtenneti15656ae2016-01-23 03:05:032029
Ali Beyada0b1a1c2022-04-08 20:08:142030 stream_->RegisterRequest(&request_);
2031 ASSERT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262032 net_log_with_source_,
2033 callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252034 ASSERT_EQ(ERR_IO_PENDING,
rtenneti15656ae2016-01-23 03:05:032035 stream_->SendRequest(headers_, &response_, callback_.callback()));
mmenkeffff3642017-06-15 17:37:242036
Yixin Wange7ecc472018-03-06 19:00:252037 // Error will be surfaced once |upload_data_stream| triggers the next write.
2038 size_t chunk_size = strlen(kUploadData);
2039 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2040 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR, callback_.WaitForResult());
2041
2042 EXPECT_LE(0, stream_->GetTotalSentBytes());
2043 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2044}
2045
2046TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersCompleteReadResponse) {
2047 SetRequest("POST", "/", DEFAULT_PRIORITY);
Victor Vasiliev7da08172019-10-14 06:04:252048 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232049 AddWrite(ConstructInitialSettingsPacket());
Yixin Wange7ecc472018-03-06 19:00:252050 AddWrite(SYNCHRONOUS, ERR_FAILED);
2051 Initialize();
2052
2053 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
2054 auto* chunked_upload_stream =
2055 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
2056
2057 request_.method = "POST";
2058 request_.url = GURL("https://www.example.org/");
2059 request_.upload_data_stream = upload_data_stream_.get();
2060
2061 size_t chunk_size = strlen(kUploadData);
2062 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2063
2064 ASSERT_EQ(OK, request_.upload_data_stream->Init(
2065 TestCompletionCallback().callback(), NetLogWithSource()));
2066
Ali Beyada0b1a1c2022-04-08 20:08:142067 stream_->RegisterRequest(&request_);
2068 ASSERT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262069 net_log_with_source_,
2070 callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252071 ASSERT_EQ(OK,
2072 stream_->SendRequest(headers_, &response_, callback_.callback()));
2073
2074 // Error will be surfaced once an attempt to read the response occurs.
2075 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
2076 stream_->ReadResponseHeaders(callback_.callback()));
2077
mmenkeffff3642017-06-15 17:37:242078 EXPECT_LE(0, stream_->GetTotalSentBytes());
2079 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rtenneti15656ae2016-01-23 03:05:032080}
2081
2082TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBodyComplete) {
2083 SetRequest("POST", "/", DEFAULT_PRIORITY);
2084 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232085 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252086 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232087 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:372088 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:232089 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2090 kIncludeVersion, !kFin, DEFAULT_PRIORITY,
2091 &spdy_request_headers_frame_length));
rtenneti15656ae2016-01-23 03:05:032092 AddWrite(SYNCHRONOUS, ERR_FAILED);
2093 Initialize();
2094
Jeremy Roman0579ed62017-08-29 15:56:192095 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:122096 auto* chunked_upload_stream =
2097 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
rtenneti15656ae2016-01-23 03:05:032098
2099 request_.method = "POST";
rchcd379012017-04-12 21:53:322100 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122101 request_.upload_data_stream = upload_data_stream_.get();
rtenneti15656ae2016-01-23 03:05:032102 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202103 TestCompletionCallback().callback(), NetLogWithSource()));
rtenneti15656ae2016-01-23 03:05:032104
Ali Beyada0b1a1c2022-04-08 20:08:142105 stream_->RegisterRequest(&request_);
2106 ASSERT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262107 net_log_with_source_,
2108 callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252109 ASSERT_EQ(ERR_IO_PENDING,
rtenneti15656ae2016-01-23 03:05:032110 stream_->SendRequest(headers_, &response_, callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252111
2112 size_t chunk_size = strlen(kUploadData);
2113 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2114 // Error does not surface yet since packet write is triggered by a packet
2115 // flusher that tries to bundle request body writes.
2116 ASSERT_EQ(OK, callback_.WaitForResult());
2117 // Error will be surfaced once an attempt to read the response occurs.
2118 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
2119 stream_->ReadResponseHeaders(callback_.callback()));
2120
2121 EXPECT_LE(0, stream_->GetTotalSentBytes());
2122 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2123}
2124
2125TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBundledBodyComplete) {
2126 SetRequest("POST", "/", DEFAULT_PRIORITY);
2127 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232128 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252129 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232130 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:432131 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:322132 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:412133 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:232134 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2135 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
2136 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:412137 } else {
2138 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:232139 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2140 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
2141 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:412142 }
2143
Yixin Wange7ecc472018-03-06 19:00:252144 AddWrite(SYNCHRONOUS, ERR_FAILED);
2145 Initialize();
2146
2147 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
2148 auto* chunked_upload_stream =
2149 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
2150
2151 request_.method = "POST";
2152 request_.url = GURL("https://www.example.org/");
2153 request_.upload_data_stream = upload_data_stream_.get();
2154
2155 size_t chunk_size = strlen(kUploadData);
2156 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
2157
2158 ASSERT_EQ(OK, request_.upload_data_stream->Init(
2159 TestCompletionCallback().callback(), NetLogWithSource()));
2160
Ali Beyada0b1a1c2022-04-08 20:08:142161 stream_->RegisterRequest(&request_);
2162 ASSERT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262163 net_log_with_source_,
2164 callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252165 ASSERT_EQ(ERR_IO_PENDING,
2166 stream_->SendRequest(headers_, &response_, callback_.callback()));
2167
2168 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2169
2170 // Error does not surface yet since packet write is triggered by a packet
2171 // flusher that tries to bundle request body writes.
2172 ASSERT_EQ(OK, callback_.WaitForResult());
2173 // Error will be surfaced once an attempt to read the response occurs.
2174 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
2175 stream_->ReadResponseHeaders(callback_.callback()));
2176
2177 EXPECT_LE(0, stream_->GetTotalSentBytes());
2178 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rtenneti15656ae2016-01-23 03:05:032179}
2180
ckrasic3865ee0f2016-02-29 22:04:562181TEST_P(QuicHttpStreamTest, ServerPushGetRequest) {
2182 SetRequest("GET", "/", DEFAULT_PRIORITY);
2183 Initialize();
2184
Bin Wue8408792021-08-24 23:25:162185 // Server push is not supported in HTTP/3.
2186 if (version_.UsesHttp3())
2187 return;
2188
ckrasic3865ee0f2016-02-29 22:04:562189 // Initialize the first stream, for receiving the promise on.
2190 request_.method = "GET";
rchcd379012017-04-12 21:53:322191 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562192
Ali Beyada0b1a1c2022-04-08 20:08:142193 stream_->RegisterRequest(&request_);
2194 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262195 net_log_with_source_,
2196 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232197 ASSERT_EQ(OK,
2198 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562199
2200 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2201 // packet, but does it matter?
2202 ReceivePromise(promise_id_);
2203 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2204
2205 request_.url = GURL(promise_url_);
2206
2207 // Make the second stream that will exercise the first step of the
2208 // server push rendezvous mechanism.
Ali Beyada0b1a1c2022-04-08 20:08:142209 promised_stream_->RegisterRequest(&request_);
2210 EXPECT_EQ(OK, promised_stream_->InitializeStream(true, DEFAULT_PRIORITY,
2211 net_log_with_source_,
2212 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562213
2214 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252215 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562216 size_t spdy_response_headers_frame_length;
2217 ProcessPacket(InnerConstructResponseHeadersPacket(
2218 1, promise_id_, false, &spdy_response_headers_frame_length));
2219
2220 // Receive the promised response body.
2221 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432222 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172223 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2224 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562225
2226 // Now sending a matching request will have successful rendezvous
2227 // with the promised stream.
Ryan Hamiltona1d1f4a2019-06-26 14:43:042228 ASSERT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
ckrasic3865ee0f2016-02-29 22:04:562229 callback_.callback()));
2230
2231 EXPECT_EQ(
2232 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2233 ->id(),
2234 promise_id_);
2235
2236 // The headers will be immediately available.
robpercival214763f2016-07-01 23:27:012237 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2238 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562239
2240 // As will be the body.
2241 EXPECT_EQ(
2242 static_cast<int>(strlen(kResponseBody)),
2243 promised_stream_->ReadResponseBody(
2244 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2245 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2246 EXPECT_TRUE(AtEof());
2247
ckrasic3865ee0f2016-02-29 22:04:562248 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2249 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412250 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562251 promised_stream_->GetTotalReceivedBytes());
2252}
2253
2254TEST_P(QuicHttpStreamTest, ServerPushGetRequestSlowResponse) {
2255 SetRequest("GET", "/", DEFAULT_PRIORITY);
2256 Initialize();
2257
Bin Wue8408792021-08-24 23:25:162258 // Server push is not supported in HTTP/3.
2259 if (version_.UsesHttp3())
2260 return;
2261
ckrasic3865ee0f2016-02-29 22:04:562262 // Initialize the first stream, for receiving the promise on.
2263 request_.method = "GET";
rchcd379012017-04-12 21:53:322264 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562265
Ali Beyada0b1a1c2022-04-08 20:08:142266 stream_->RegisterRequest(&request_);
2267 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262268 net_log_with_source_,
2269 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232270 ASSERT_EQ(OK,
2271 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562272
2273 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2274 // packet, but does it matter?
2275 ReceivePromise(promise_id_);
2276 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2277
2278 request_.url = GURL(promise_url_);
2279
2280 // Make the second stream that will exercise the first step of the
2281 // server push rendezvous mechanism.
Ali Beyada0b1a1c2022-04-08 20:08:142282 promised_stream_->RegisterRequest(&request_);
2283 EXPECT_EQ(OK, promised_stream_->InitializeStream(true, DEFAULT_PRIORITY,
2284 net_log_with_source_,
2285 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562286
2287 // Now sending a matching request will rendezvous with the promised
2288 // stream, but pending secondary validation.
2289 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2290 headers_, &response_, callback_.callback()));
2291
2292 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252293 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562294 size_t spdy_response_headers_frame_length;
2295 ProcessPacket(InnerConstructResponseHeadersPacket(
2296 1, promise_id_, false, &spdy_response_headers_frame_length));
2297
2298 // Receive the promised response body.
2299 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432300 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172301 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2302 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562303
fdoray92e35a72016-06-10 15:54:552304 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562305
2306 // Rendezvous should have succeeded now, so the promised stream
2307 // should point at our push stream, and we should be able read
2308 // headers and data from it.
robpercival214763f2016-07-01 23:27:012309 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562310
2311 EXPECT_EQ(
2312 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2313 ->id(),
2314 promise_id_);
2315
robpercival214763f2016-07-01 23:27:012316 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2317 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562318
2319 EXPECT_EQ(
2320 static_cast<int>(strlen(kResponseBody)),
2321 promised_stream_->ReadResponseBody(
2322 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2323
2324 // Callback should return
2325 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2326 EXPECT_TRUE(AtEof());
2327
ckrasic3865ee0f2016-02-29 22:04:562328 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2329 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412330 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562331 promised_stream_->GetTotalReceivedBytes());
2332}
2333
ckrasic2c63f9b2016-08-16 23:54:072334// Verify fix for crbug.com/637349
2335TEST_P(QuicHttpStreamTest, ServerPushCancelHttpStreamBeforeResponse) {
2336 SetRequest("GET", "/", DEFAULT_PRIORITY);
2337 Initialize();
2338
Bin Wue8408792021-08-24 23:25:162339 // Server push is not supported in HTTP/3.
2340 if (version_.UsesHttp3())
2341 return;
2342
ckrasic2c63f9b2016-08-16 23:54:072343 // Initialize the first stream, for receiving the promise on.
2344 request_.method = "GET";
rchcd379012017-04-12 21:53:322345 request_.url = GURL("https://www.example.org/");
ckrasic2c63f9b2016-08-16 23:54:072346
Ali Beyada0b1a1c2022-04-08 20:08:142347 stream_->RegisterRequest(&request_);
2348 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262349 net_log_with_source_,
2350 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232351 ASSERT_EQ(OK,
2352 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic2c63f9b2016-08-16 23:54:072353
2354 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2355 // packet, but does it matter?
2356 ReceivePromise(promise_id_);
2357 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2358
2359 request_.url = GURL(promise_url_);
2360
2361 // Make the second stream that will exercise the first step of the
2362 // server push rendezvous mechanism.
Ali Beyada0b1a1c2022-04-08 20:08:142363 promised_stream_->RegisterRequest(&request_);
2364 EXPECT_EQ(OK, promised_stream_->InitializeStream(true, DEFAULT_PRIORITY,
2365 net_log_with_source_,
2366 callback_.callback()));
ckrasic2c63f9b2016-08-16 23:54:072367
2368 // Now sending a matching request will rendezvous with the promised
2369 // stream, but pending secondary validation.
2370 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2371 headers_, &response_, callback_.callback()));
2372
2373 base::RunLoop().RunUntilIdle();
2374
2375 // Cause of FinalValidation() crash as per bug.
2376 promised_stream_.reset();
2377
2378 // Receive the promised response headers.
2379 response_headers_ = promised_response_.Clone();
2380 size_t spdy_response_headers_frame_length;
2381 ProcessPacket(InnerConstructResponseHeadersPacket(
2382 1, promise_id_, false, &spdy_response_headers_frame_length));
2383}
2384
ckrasic3865ee0f2016-02-29 22:04:562385TEST_P(QuicHttpStreamTest, ServerPushCrossOriginOK) {
2386 SetRequest("GET", "/", DEFAULT_PRIORITY);
2387 Initialize();
2388
Bin Wue8408792021-08-24 23:25:162389 // Server push is not supported in HTTP/3.
2390 if (version_.UsesHttp3())
2391 return;
2392
ckrasic3865ee0f2016-02-29 22:04:562393 // Initialize the first stream, for receiving the promise on.
2394 request_.method = "GET";
rchcd379012017-04-12 21:53:322395 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562396
Ali Beyada0b1a1c2022-04-08 20:08:142397 stream_->RegisterRequest(&request_);
2398 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262399 net_log_with_source_,
2400 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232401 ASSERT_EQ(OK,
2402 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562403
2404 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2405 // packet, but does it matter?
2406
2407 push_promise_[":authority"] = "mail.example.org";
David Schinazi3f7465c2019-07-12 01:57:052408 promise_url_ =
2409 quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
ckrasic3865ee0f2016-02-29 22:04:562410
2411 ReceivePromise(promise_id_);
2412 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2413
2414 request_.url = GURL(promise_url_);
2415
2416 // Make the second stream that will exercise the first step of the
2417 // server push rendezvous mechanism.
Ali Beyada0b1a1c2022-04-08 20:08:142418 promised_stream_->RegisterRequest(&request_);
2419 EXPECT_EQ(OK, promised_stream_->InitializeStream(true, DEFAULT_PRIORITY,
2420 net_log_with_source_,
2421 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562422
2423 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252424 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562425 size_t spdy_response_headers_frame_length;
2426 ProcessPacket(InnerConstructResponseHeadersPacket(
2427 1, promise_id_, false, &spdy_response_headers_frame_length));
2428
2429 // Receive the promised response body.
2430 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432431 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172432 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2433 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562434
2435 // Now sending a matching request will have successful rendezvous
2436 // with the promised stream.
2437 EXPECT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
2438 callback_.callback()));
2439
2440 EXPECT_EQ(
2441 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2442 ->id(),
2443 promise_id_);
2444
2445 // The headers will be immediately available.
robpercival214763f2016-07-01 23:27:012446 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2447 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562448
2449 // As will be the body.
2450 EXPECT_EQ(
2451 static_cast<int>(strlen(kResponseBody)),
2452 promised_stream_->ReadResponseBody(
2453 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2454 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2455 EXPECT_TRUE(AtEof());
2456
ckrasic3865ee0f2016-02-29 22:04:562457 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2458 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412459 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562460 promised_stream_->GetTotalReceivedBytes());
2461}
2462
2463TEST_P(QuicHttpStreamTest, ServerPushCrossOriginFail) {
2464 SetRequest("GET", "/", DEFAULT_PRIORITY);
2465 Initialize();
2466
Bin Wue8408792021-08-24 23:25:162467 // Server push is not supported in HTTP/3.
2468 if (version_.UsesHttp3())
2469 return;
2470
ckrasic3865ee0f2016-02-29 22:04:562471 // Initialize the first stream, for receiving the promise on.
2472 request_.method = "GET";
rchcd379012017-04-12 21:53:322473 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562474
Ali Beyada0b1a1c2022-04-08 20:08:142475 stream_->RegisterRequest(&request_);
2476 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262477 net_log_with_source_,
2478 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232479 ASSERT_EQ(OK,
2480 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562481
2482 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2483 // packet, but does it matter?
2484 push_promise_[":authority"] = "www.notexample.org";
David Schinazi3f7465c2019-07-12 01:57:052485 promise_url_ =
2486 quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
ckrasic3865ee0f2016-02-29 22:04:562487
2488 ReceivePromise(promise_id_);
2489 // The promise will have been rejected because the cert doesn't
2490 // match.
2491 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
2492}
2493
2494TEST_P(QuicHttpStreamTest, ServerPushVaryCheckOK) {
2495 SetRequest("GET", "/", DEFAULT_PRIORITY);
2496 Initialize();
2497
Bin Wue8408792021-08-24 23:25:162498 // Server push is not supported in HTTP/3.
2499 if (version_.UsesHttp3())
2500 return;
2501
ckrasic3865ee0f2016-02-29 22:04:562502 // Initialize the first stream, for receiving the promise on.
2503 request_.method = "GET";
rchcd379012017-04-12 21:53:322504 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562505
Ali Beyada0b1a1c2022-04-08 20:08:142506 stream_->RegisterRequest(&request_);
2507 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262508 net_log_with_source_,
2509 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232510 ASSERT_EQ(OK,
2511 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562512
2513 push_promise_["accept-encoding"] = "gzip";
ckrasic3865ee0f2016-02-29 22:04:562514
2515 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2516 // packet, but does it matter?
2517 ReceivePromise(promise_id_);
2518 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2519
2520 request_.url = GURL(promise_url_);
2521
2522 // Make the second stream that will exercise the first step of the
2523 // server push rendezvous mechanism.
Ali Beyada0b1a1c2022-04-08 20:08:142524 promised_stream_->RegisterRequest(&request_);
2525 EXPECT_EQ(OK, promised_stream_->InitializeStream(true, DEFAULT_PRIORITY,
2526 net_log_with_source_,
2527 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562528
2529 headers_.SetHeader("accept-encoding", "gzip");
2530
2531 // Now sending a matching request will rendezvous with the promised
2532 // stream, but pending secondary validation.
2533 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2534 headers_, &response_, callback_.callback()));
2535
2536 // Receive the promised response headers.
2537 promised_response_["vary"] = "accept-encoding";
bnc94893a72016-06-30 13:45:252538 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562539 size_t spdy_response_headers_frame_length;
2540 ProcessPacket(InnerConstructResponseHeadersPacket(
2541 1, promise_id_, false, &spdy_response_headers_frame_length));
2542
2543 // Receive the promised response body.
2544 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432545 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172546 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2547 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562548
fdoray92e35a72016-06-10 15:54:552549 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562550
2551 // Rendezvous should have succeeded now, so the promised stream
2552 // should point at our push stream, and we should be able read
2553 // headers and data from it.
robpercival214763f2016-07-01 23:27:012554 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562555
2556 EXPECT_EQ(
2557 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2558 ->id(),
2559 promise_id_);
2560
robpercival214763f2016-07-01 23:27:012561 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2562 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562563
2564 EXPECT_EQ(
2565 static_cast<int>(strlen(kResponseBody)),
2566 promised_stream_->ReadResponseBody(
2567 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2568
2569 // Callback should return
2570 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2571 EXPECT_TRUE(AtEof());
2572
ckrasic3865ee0f2016-02-29 22:04:562573 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2574 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412575 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562576 promised_stream_->GetTotalReceivedBytes());
2577}
2578
2579TEST_P(QuicHttpStreamTest, ServerPushVaryCheckFail) {
2580 SetRequest("GET", "/", DEFAULT_PRIORITY);
2581 request_headers_[":scheme"] = "https";
2582 request_headers_[":path"] = "/bar";
2583 request_headers_["accept-encoding"] = "sdch";
2584
ckrasic3865ee0f2016-02-29 22:04:562585 Initialize();
2586
Bin Wue8408792021-08-24 23:25:162587 // Server push is not supported in HTTP/3.
2588 if (version_.UsesHttp3())
2589 return;
2590
ckrasic3865ee0f2016-02-29 22:04:562591 // Initialize the first stream, for receiving the promise on.
2592 request_.method = "GET";
rchcd379012017-04-12 21:53:322593 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562594
Ali Beyada0b1a1c2022-04-08 20:08:142595 stream_->RegisterRequest(&request_);
2596 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262597 net_log_with_source_,
2598 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232599 ASSERT_EQ(OK,
2600 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562601
2602 push_promise_["accept-encoding"] = "gzip";
ckrasic3865ee0f2016-02-29 22:04:562603
2604 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2605 // packet, but does it matter?
2606 ReceivePromise(promise_id_);
2607 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2608
2609 request_.url = GURL(promise_url_);
2610
2611 // Make the second stream that will exercise the first step of the
2612 // server push rendezvous mechanism.
Ali Beyada0b1a1c2022-04-08 20:08:142613 promised_stream_->RegisterRequest(&request_);
2614 EXPECT_EQ(OK, promised_stream_->InitializeStream(true, DEFAULT_PRIORITY,
2615 net_log_with_source_,
2616 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562617
2618 headers_.SetHeader("accept-encoding", "sdch");
2619
2620 // Now sending a matching request will rendezvous with the promised
2621 // stream, but pending secondary validation.
2622 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2623 headers_, &response_, callback_.callback()));
2624
2625 // Receive the promised response headers.
2626 promised_response_["vary"] = "accept-encoding";
bnc94893a72016-06-30 13:45:252627 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562628 size_t spdy_response_headers_frame_length;
2629 ProcessPacket(InnerConstructResponseHeadersPacket(
2630 1, promise_id_, false, &spdy_response_headers_frame_length));
2631
fdoray92e35a72016-06-10 15:54:552632 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562633
2634 // Rendezvous should have failed due to vary mismatch, so the
2635 // promised stream should have been aborted, and instead we have a
2636 // new, regular client initiated stream.
robpercival214763f2016-07-01 23:27:012637 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562638
2639 // Not a server-initiated stream.
2640 EXPECT_NE(
2641 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2642 ->id(),
2643 promise_id_);
2644
2645 // Instead, a new client-initiated stream.
2646 EXPECT_EQ(
2647 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2648 ->id(),
Nick Harper23290b82019-05-02 00:02:562649 stream_id_ + quic::QuicUtils::StreamIdDelta(version_.transport_version));
ckrasic3865ee0f2016-02-29 22:04:562650
2651 // After rendezvous failure, the push stream has been cancelled.
2652 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
2653
2654 // The rest of the test verifies that the retried as
2655 // client-initiated version of |promised_stream_| works as intended.
2656
2657 // Ack the request.
Renjie90e808e2019-01-24 07:24:042658 ProcessPacket(ConstructServerAckPacket(2, 1, 1, 1));
ckrasic3865ee0f2016-02-29 22:04:562659
Kenichi Ishibashif8634ab2021-03-16 23:41:282660 SetResponse("404", string());
ckrasic3865ee0f2016-02-29 22:04:562661 size_t spdy_response_header_frame_length;
2662 ProcessPacket(InnerConstructResponseHeadersPacket(
Nick Harper23290b82019-05-02 00:02:562663 3,
2664 stream_id_ + quic::QuicUtils::StreamIdDelta(version_.transport_version),
2665 kFin, &spdy_response_header_frame_length));
ckrasic3865ee0f2016-02-29 22:04:562666
fdoray92e35a72016-06-10 15:54:552667 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562668
robpercival214763f2016-07-01 23:27:012669 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2670 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562671 ASSERT_TRUE(response_.headers.get());
2672 EXPECT_EQ(404, response_.headers->response_code());
2673 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
2674 EXPECT_FALSE(response_.response_time.is_null());
2675 EXPECT_FALSE(response_.request_time.is_null());
2676
2677 // There is no body, so this should return immediately.
2678 EXPECT_EQ(
2679 0, promised_stream_->ReadResponseBody(
2680 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2681 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2682
2683 stream_->Close(true);
2684
2685 EXPECT_TRUE(AtEof());
ckrasic3865ee0f2016-02-29 22:04:562686}
2687
maksim.sisov84e20c92016-06-23 08:49:342688TEST_P(QuicHttpStreamTest, DataReadErrorSynchronous) {
2689 SetRequest("POST", "/", DEFAULT_PRIORITY);
2690 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232691 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252692 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232693 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Yixin Wange7ecc472018-03-06 19:00:252694 AddWrite(ConstructRequestAndRstPacket(
Renjie Tangaadb84b2019-08-31 01:00:232695 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2696 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
2697 &spdy_request_headers_frame_length, quic::QUIC_ERROR_PROCESSING_STREAM));
maksim.sisov84e20c92016-06-23 08:49:342698
2699 Initialize();
2700
Jeremy Roman0579ed62017-08-29 15:56:192701 upload_data_stream_ = std::make_unique<ReadErrorUploadDataStream>(
maksim.sisov84e20c92016-06-23 08:49:342702 ReadErrorUploadDataStream::FailureMode::SYNC);
2703 request_.method = "POST";
rchcd379012017-04-12 21:53:322704 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122705 request_.upload_data_stream = upload_data_stream_.get();
maksim.sisov84e20c92016-06-23 08:49:342706 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202707 TestCompletionCallback().callback(), NetLogWithSource()));
maksim.sisov84e20c92016-06-23 08:49:342708
Ali Beyada0b1a1c2022-04-08 20:08:142709 stream_->RegisterRequest(&request_);
2710 EXPECT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262711 net_log_with_source_,
2712 callback_.callback()));
maksim.sisov84e20c92016-06-23 08:49:342713
2714 int result = stream_->SendRequest(headers_, &response_, callback_.callback());
robpercival214763f2016-07-01 23:27:012715 EXPECT_THAT(result, IsError(ERR_FAILED));
maksim.sisov84e20c92016-06-23 08:49:342716
2717 EXPECT_TRUE(AtEof());
2718
2719 // QuicHttpStream::GetTotalSent/ReceivedBytes includes only headers.
2720 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
2721 stream_->GetTotalSentBytes());
2722 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2723}
2724
2725TEST_P(QuicHttpStreamTest, DataReadErrorAsynchronous) {
2726 SetRequest("POST", "/", DEFAULT_PRIORITY);
2727 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232728 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252729 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232730 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:372731 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:232732 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2733 kIncludeVersion, !kFin, DEFAULT_PRIORITY,
2734 &spdy_request_headers_frame_length));
2735 AddWrite(
2736 ConstructClientRstStreamErrorPacket(packet_number++, !kIncludeVersion));
maksim.sisov84e20c92016-06-23 08:49:342737
2738 Initialize();
2739
Jeremy Roman0579ed62017-08-29 15:56:192740 upload_data_stream_ = std::make_unique<ReadErrorUploadDataStream>(
maksim.sisov84e20c92016-06-23 08:49:342741 ReadErrorUploadDataStream::FailureMode::ASYNC);
2742 request_.method = "POST";
rchcd379012017-04-12 21:53:322743 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122744 request_.upload_data_stream = upload_data_stream_.get();
maksim.sisov84e20c92016-06-23 08:49:342745 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202746 TestCompletionCallback().callback(), NetLogWithSource()));
maksim.sisov84e20c92016-06-23 08:49:342747
Ali Beyada0b1a1c2022-04-08 20:08:142748 stream_->RegisterRequest(&request_);
2749 EXPECT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262750 net_log_with_source_,
2751 callback_.callback()));
maksim.sisov84e20c92016-06-23 08:49:342752
2753 int result = stream_->SendRequest(headers_, &response_, callback_.callback());
2754
Renjie90e808e2019-01-24 07:24:042755 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
Kenichi Ishibashif8634ab2021-03-16 23:41:282756 SetResponse("200", string());
maksim.sisov84e20c92016-06-23 08:49:342757
robpercival214763f2016-07-01 23:27:012758 EXPECT_THAT(result, IsError(ERR_IO_PENDING));
2759 EXPECT_THAT(callback_.GetResult(result), IsError(ERR_FAILED));
maksim.sisov84e20c92016-06-23 08:49:342760
2761 EXPECT_TRUE(AtEof());
2762
2763 // QuicHttpStream::GetTotalSent/ReceivedBytes includes only headers.
2764 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
2765 stream_->GetTotalSentBytes());
2766 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2767}
2768
Bence Béky97ec688c2021-03-16 13:48:502769TEST_P(QuicHttpStreamTest, GetAcceptChViaAlps) {
2770 AddWrite(ConstructInitialSettingsPacket());
2771 Initialize();
2772
2773 if (!VersionUsesHttp3(version_.transport_version)) {
2774 // ALPS is only implemented for HTTP/3.
2775 return;
2776 }
2777
2778 base::HistogramTester histogram_tester;
2779
2780 session_->OnAcceptChFrameReceivedViaAlps(
Bence Béky41a34f02021-05-07 00:27:482781 {{{"https://www.example.org", "Sec-CH-UA-Platform"}}});
Bence Béky97ec688c2021-03-16 13:48:502782
2783 request_.method = "GET";
2784 request_.url = GURL("https://www.example.org/foo");
2785
Ali Beyada0b1a1c2022-04-08 20:08:142786 stream_->RegisterRequest(&request_);
2787 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262788 net_log_with_source_,
2789 callback_.callback()));
Bence Béky41a34f02021-05-07 00:27:482790 EXPECT_EQ("Sec-CH-UA-Platform", stream_->GetAcceptChViaAlps());
Bence Béky97ec688c2021-03-16 13:48:502791 EXPECT_TRUE(AtEof());
2792
2793 histogram_tester.ExpectBucketCount(
2794 "Net.QuicSession.AcceptChFrameReceivedViaAlps", 1, 1);
2795 histogram_tester.ExpectTotalCount(
2796 "Net.QuicSession.AcceptChFrameReceivedViaAlps", 1);
2797 histogram_tester.ExpectBucketCount("Net.QuicSession.AcceptChForOrigin", 1, 1);
2798 histogram_tester.ExpectTotalCount("Net.QuicSession.AcceptChForOrigin", 1);
2799}
2800
Tsuyoshi Horo4f516be2022-06-14 11:53:132801} // namespace net::test