blob: 84e671890a49e05ae4cd67429992fcf9fd0dd31c [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
90namespace net {
[email protected]f702d572012-12-04 15:56:2091namespace test {
[email protected]f702d572012-12-04 15:56:2092namespace {
93
[email protected]16ba7742014-08-22 00:57:2594const char kUploadData[] = "Really nifty data!";
rch9ae5b3b2016-02-11 00:36:2995const char kDefaultServerHostName[] = "www.example.org";
rchcd379012017-04-12 21:53:3296const uint16_t kDefaultServerPort = 443;
[email protected]f702d572012-12-04 15:56:2097
David Schinazi09e9a6012019-10-03 17:37:5798struct TestParams {
99 quic::ParsedQuicVersion version;
100 bool client_headers_include_h2_stream_dependency;
101};
102
103// Used by ::testing::PrintToStringParamName().
104std::string PrintToString(const TestParams& p) {
Victor Vasiliev62c09dc2020-11-06 18:18:29105 return base::StrCat(
106 {ParsedQuicVersionToString(p.version), "_",
107 (p.client_headers_include_h2_stream_dependency ? "" : "No"),
108 "Dependency"});
David Schinazi09e9a6012019-10-03 17:37:57109}
110
111std::vector<TestParams> GetTestParams() {
112 std::vector<TestParams> params;
113 quic::ParsedQuicVersionVector all_supported_versions =
114 quic::AllSupportedVersions();
115 for (const auto& version : all_supported_versions) {
116 params.push_back(TestParams{version, false});
117 params.push_back(TestParams{version, true});
118 }
119 return params;
120}
121
Bence Békye0d3747d2020-08-28 23:16:40122// Returns true if |params| is a dict, has an entry with key "headers", that
123// entry is a list of strings, which when interpreted as colon-separated
124// key-value pairs has exactly one entry with |key| and that entry has value
125// |expected_value|.
126bool CheckHeader(const base::Value& params,
127 base::StringPiece key,
128 base::StringPiece expected_value) {
129 if (!params.is_dict()) {
130 return false;
131 }
Matt Menke355d7b1e2022-05-27 23:19:53132 const base::Value::List* headers = params.GetDict().FindList("headers");
Bence Békye0d3747d2020-08-28 23:16:40133 if (!headers) {
134 return false;
135 }
136
137 std::string header_prefix = base::StrCat({key, ": "});
138 std::string expected_header = base::StrCat({header_prefix, expected_value});
139
Bence Békye0d3747d2020-08-28 23:16:40140 bool header_found = false;
Matt Menke355d7b1e2022-05-27 23:19:53141 for (const auto& header_value : *headers) {
142 const std::string* header = header_value.GetIfString();
143 if (!header) {
Bence Békye0d3747d2020-08-28 23:16:40144 return false;
145 }
Matt Menke355d7b1e2022-05-27 23:19:53146 if (base::StartsWith(*header, header_prefix)) {
Bence Békye0d3747d2020-08-28 23:16:40147 if (header_found) {
148 return false;
149 }
Matt Menke355d7b1e2022-05-27 23:19:53150 if (*header != expected_header) {
Bence Békye0d3747d2020-08-28 23:16:40151 return false;
152 }
153 header_found = true;
154 }
Bence Békye0d3747d2020-08-28 23:16:40155 }
156 return header_found;
157}
158
Ryan Hamilton8d9ee76e2018-05-29 23:52:52159class TestQuicConnection : public quic::QuicConnection {
[email protected]f702d572012-12-04 15:56:20160 public:
Ryan Hamilton8d9ee76e2018-05-29 23:52:52161 TestQuicConnection(const quic::ParsedQuicVersionVector& versions,
162 quic::QuicConnectionId connection_id,
[email protected]f702d572012-12-04 15:56:20163 IPEndPoint address,
rch12fef552016-01-15 16:26:31164 QuicChromiumConnectionHelper* helper,
rch16c74d1d2016-04-22 06:14:07165 QuicChromiumAlarmFactory* alarm_factory,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52166 quic::QuicPacketWriter* writer)
Victor Vasiliev4f6fb892019-05-31 16:58:31167 : quic::QuicConnection(connection_id,
Nick Harperd049f192020-10-02 02:56:10168 quic::QuicSocketAddress(),
Victor Vasiliev4f6fb892019-05-31 16:58:31169 ToQuicSocketAddress(address),
170 helper,
171 alarm_factory,
172 writer,
173 true /* owns_writer */,
174 quic::Perspective::IS_CLIENT,
175 versions) {}
[email protected]f702d572012-12-04 15:56:20176
Ryan Hamilton8d9ee76e2018-05-29 23:52:52177 void SetSendAlgorithm(quic::SendAlgorithmInterface* send_algorithm) {
178 quic::test::QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
[email protected]f702d572012-12-04 15:56:20179 }
180};
181
maksim.sisov84e20c92016-06-23 08:49:34182// UploadDataStream that always returns errors on data read.
183class ReadErrorUploadDataStream : public UploadDataStream {
184 public:
185 enum class FailureMode { SYNC, ASYNC };
186
187 explicit ReadErrorUploadDataStream(FailureMode mode)
Jeremy Romand54000b22019-07-08 18:40:16188 : UploadDataStream(true, 0), async_(mode) {}
Peter Boström293b1342021-09-22 17:31:43189
190 ReadErrorUploadDataStream(const ReadErrorUploadDataStream&) = delete;
191 ReadErrorUploadDataStream& operator=(const ReadErrorUploadDataStream&) =
192 delete;
193
maksim.sisov84e20c92016-06-23 08:49:34194 ~ReadErrorUploadDataStream() override {}
195
196 private:
197 void CompleteRead() { UploadDataStream::OnReadCompleted(ERR_FAILED); }
198
199 // UploadDataStream implementation:
tfarina42834112016-09-22 13:38:20200 int InitInternal(const NetLogWithSource& net_log) override { return OK; }
maksim.sisov84e20c92016-06-23 08:49:34201
202 int ReadInternal(IOBuffer* buf, int buf_len) override {
203 if (async_ == FailureMode::ASYNC) {
204 base::ThreadTaskRunnerHandle::Get()->PostTask(
kylecharf4fe5172019-02-15 18:53:49205 FROM_HERE, base::BindOnce(&ReadErrorUploadDataStream::CompleteRead,
206 weak_factory_.GetWeakPtr()));
maksim.sisov84e20c92016-06-23 08:49:34207 return ERR_IO_PENDING;
208 }
209 return ERR_FAILED;
210 }
211
212 void ResetInternal() override {}
213
214 const FailureMode async_;
215
Jeremy Romand54000b22019-07-08 18:40:16216 base::WeakPtrFactory<ReadErrorUploadDataStream> weak_factory_{this};
maksim.sisov84e20c92016-06-23 08:49:34217};
218
Bence Béky8ddc2492018-06-13 01:02:04219// A helper class that will delete |stream| when the callback is invoked.
xunjieli8dff50b2016-07-22 14:19:06220class DeleteStreamCallback : public TestCompletionCallbackBase {
221 public:
Bence Béky8ddc2492018-06-13 01:02:04222 explicit DeleteStreamCallback(std::unique_ptr<QuicHttpStream> stream)
223 : stream_(std::move(stream)) {}
xunjieli8dff50b2016-07-22 14:19:06224
Bence Béky8ddc2492018-06-13 01:02:04225 CompletionOnceCallback callback() {
226 return base::BindOnce(&DeleteStreamCallback::DeleteStream,
227 base::Unretained(this));
228 }
xunjieli8dff50b2016-07-22 14:19:06229
230 private:
231 void DeleteStream(int result) {
232 stream_.reset();
233 SetResult(result);
234 }
235
236 std::unique_ptr<QuicHttpStream> stream_;
xunjieli8dff50b2016-07-22 14:19:06237};
238
[email protected]f702d572012-12-04 15:56:20239} // namespace
240
[email protected]24e5bc52013-09-18 15:36:58241class QuicHttpStreamPeer {
242 public:
rch08e198572017-05-09 16:56:55243 static QuicChromiumClientStream::Handle* GetQuicChromiumClientStream(
[email protected]24e5bc52013-09-18 15:36:58244 QuicHttpStream* stream) {
rch08e198572017-05-09 16:56:55245 return stream->stream_.get();
[email protected]24e5bc52013-09-18 15:36:58246 }
247};
248
David Schinazi09e9a6012019-10-03 17:37:57249class QuicHttpStreamTest : public ::testing::TestWithParam<TestParams>,
Gabriel Charette694c3c332019-08-19 14:53:05250 public WithTaskEnvironment {
rchfb47f712017-05-21 03:24:00251 public:
252 void CloseStream(QuicHttpStream* stream, int /*rv*/) { stream->Close(false); }
253
[email protected]f702d572012-12-04 15:56:20254 protected:
[email protected]1e960032013-12-20 19:00:20255 static const bool kFin = true;
256 static const bool kIncludeVersion = true;
[email protected]1e960032013-12-20 19:00:20257
[email protected]f702d572012-12-04 15:56:20258 // Holds a packet to be written to the wire, and the IO mode that should
259 // be used by the mock socket when performing the write.
260 struct PacketToWrite {
Ryan Hamilton8d9ee76e2018-05-29 23:52:52261 PacketToWrite(IoMode mode, quic::QuicReceivedPacket* packet)
rjshaded5ced072015-12-18 19:26:02262 : mode(mode), packet(packet) {}
rtenneti15656ae2016-01-23 03:05:03263 PacketToWrite(IoMode mode, int rv) : mode(mode), packet(nullptr), rv(rv) {}
[email protected]f702d572012-12-04 15:56:20264 IoMode mode;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52265 quic::QuicReceivedPacket* packet;
rtenneti15656ae2016-01-23 03:05:03266 int rv;
[email protected]f702d572012-12-04 15:56:20267 };
268
269 QuicHttpStreamTest()
David Schinazi09e9a6012019-10-03 17:37:57270 : version_(GetParam().version),
271 client_headers_include_h2_stream_dependency_(
272 GetParam().client_headers_include_h2_stream_dependency),
Nick Harpera598fc5f2019-06-21 08:46:50273 crypto_config_(
274 quic::test::crypto_test_utils::ProofVerifierForTesting()),
Victor Costan9c7302b2018-08-27 16:39:44275 read_buffer_(base::MakeRefCounted<IOBufferWithSize>(4096)),
Fan Yang32c5a112018-12-10 20:06:33276 promise_id_(GetNthServerInitiatedUnidirectionalStreamId(0)),
277 stream_id_(GetNthClientInitiatedBidirectionalStreamId(0)),
David Schinazic8281052019-01-24 06:14:17278 connection_id_(quic::test::TestConnectionId(2)),
Yixin Wang079ad542018-01-11 04:06:05279 client_maker_(version_,
alyssar2adf3ac2016-05-03 17:12:58280 connection_id_,
281 &clock_,
282 kDefaultServerHostName,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52283 quic::Perspective::IS_CLIENT,
Yixin Wang079ad542018-01-11 04:06:05284 client_headers_include_h2_stream_dependency_),
285 server_maker_(version_,
zhongyi5dbfdd42017-06-20 05:22:15286 connection_id_,
alyssar2adf3ac2016-05-03 17:12:58287 &clock_,
288 kDefaultServerHostName,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52289 quic::Perspective::IS_SERVER,
Yixin Wang079ad542018-01-11 04:06:05290 false),
Ryan Hamilton0d65a8c2019-06-07 00:46:02291 printer_(version_) {
Renjie Tang98b4d512020-02-08 01:24:19292 FLAGS_quic_enable_http3_grease_randomness = false;
Zhongyi Shi49f8ad2fd2019-12-13 01:20:31293 quic::QuicEnableVersion(version_);
martijn21968ea2016-02-24 18:46:20294 IPAddress ip(192, 0, 2, 33);
[email protected]f702d572012-12-04 15:56:20295 peer_addr_ = IPEndPoint(ip, 443);
296 self_addr_ = IPEndPoint(ip, 8435);
Ryan Hamilton8d9ee76e2018-05-29 23:52:52297 clock_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(20));
Ramin Halavati683bcaa92018-02-14 08:42:39298 request_.traffic_annotation =
299 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f702d572012-12-04 15:56:20300 }
301
302 ~QuicHttpStreamTest() {
Renjieba55fae2018-09-20 03:05:16303 session_->CloseSessionOnError(ERR_ABORTED, quic::QUIC_INTERNAL_ERROR,
304 quic::ConnectionCloseBehavior::SILENT_CLOSE);
[email protected]f702d572012-12-04 15:56:20305 for (size_t i = 0; i < writes_.size(); i++) {
306 delete writes_[i].packet;
307 }
308 }
309
310 // Adds a packet to the list of expected writes.
Ryan Hamilton8d9ee76e2018-05-29 23:52:52311 void AddWrite(std::unique_ptr<quic::QuicReceivedPacket> packet) {
[email protected]1e960032013-12-20 19:00:20312 writes_.push_back(PacketToWrite(SYNCHRONOUS, packet.release()));
[email protected]f702d572012-12-04 15:56:20313 }
314
rtenneti15656ae2016-01-23 03:05:03315 void AddWrite(IoMode mode, int rv) {
316 writes_.push_back(PacketToWrite(mode, rv));
317 }
318
[email protected]f702d572012-12-04 15:56:20319 // Returns the packet to be written at position |pos|.
Ryan Hamilton8d9ee76e2018-05-29 23:52:52320 quic::QuicReceivedPacket* GetWrite(size_t pos) { return writes_[pos].packet; }
[email protected]f702d572012-12-04 15:56:20321
322 bool AtEof() {
rch37de576c2015-05-17 20:28:17323 return socket_data_->AllReadDataConsumed() &&
324 socket_data_->AllWriteDataConsumed();
[email protected]f702d572012-12-04 15:56:20325 }
326
Ryan Hamilton8d9ee76e2018-05-29 23:52:52327 void ProcessPacket(std::unique_ptr<quic::QuicReceivedPacket> packet) {
Victor Vasiliev4f6fb892019-05-31 16:58:31328 connection_->ProcessUdpPacket(ToQuicSocketAddress(self_addr_),
329 ToQuicSocketAddress(peer_addr_), *packet);
[email protected]f702d572012-12-04 15:56:20330 }
331
332 // Configures the test fixture to use the list of expected writes.
333 void Initialize() {
Renjie Tang6ff9a9b2021-02-03 22:11:09334 mock_writes_ = std::make_unique<MockWrite[]>(writes_.size());
[email protected]f702d572012-12-04 15:56:20335 for (size_t i = 0; i < writes_.size(); i++) {
rtenneti15656ae2016-01-23 03:05:03336 if (writes_[i].packet == nullptr) {
337 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].rv, i);
338 } else {
339 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].packet->data(),
340 writes_[i].packet->length());
341 }
bnc614a92d32016-04-04 13:56:07342 }
[email protected]f702d572012-12-04 15:56:20343
Renjie Tang6ff9a9b2021-02-03 22:11:09344 socket_data_ = std::make_unique<StaticSocketDataProvider>(
Ryan Sleevib8d7ea02018-05-07 20:01:01345 base::span<MockRead>(),
Renjie Tang6ff9a9b2021-02-03 22:11:09346 base::make_span(mock_writes_.get(), writes_.size()));
Ryan Hamilton0d65a8c2019-06-07 00:46:02347 socket_data_->set_printer(&printer_);
[email protected]f702d572012-12-04 15:56:20348
Matt Reichhoff0049a0b72021-10-20 20:44:26349 std::unique_ptr<MockUDPClientSocket> socket(
350 new MockUDPClientSocket(socket_data_.get(), NetLog::Get()));
[email protected]e13201d82012-12-12 05:00:32351 socket->Connect(peer_addr_);
[email protected]f702d572012-12-04 15:56:20352 runner_ = new TestTaskRunner(&clock_);
Ryan Hamilton8d9ee76e2018-05-29 23:52:52353 send_algorithm_ = new quic::test::MockSendAlgorithm();
rch7dd15702015-07-01 18:57:57354 EXPECT_CALL(*send_algorithm_, InRecovery()).WillRepeatedly(Return(false));
355 EXPECT_CALL(*send_algorithm_, InSlowStart()).WillRepeatedly(Return(false));
Victor Vasiliev7da08172019-10-14 06:04:25356 if (VersionUsesHttp3(version_.transport_version)) {
Renjie Tangaadb84b2019-08-31 01:00:23357 EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
358 .Times(testing::AtLeast(1));
359 }
Ryan Hamiltona1d1f4a2019-06-26 14:43:04360 EXPECT_CALL(*send_algorithm_, OnCongestionEvent(_, _, _, _, _))
361 .Times(AnyNumber());
rtenneti44f4a2e2015-08-07 14:00:07362 EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
Zhongyi Shica576df2019-04-12 17:43:40363 .WillRepeatedly(Return(quic::kMaxOutgoingPacketSize));
jokulik0e0a00c32016-06-13 21:51:58364 EXPECT_CALL(*send_algorithm_, PacingRate(_))
Ryan Hamilton8d9ee76e2018-05-29 23:52:52365 .WillRepeatedly(Return(quic::QuicBandwidth::Zero()));
Michael Warres74ee3ce2017-10-09 15:26:37366 EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true));
rtenneti44f4a2e2015-08-07 14:00:07367 EXPECT_CALL(*send_algorithm_, BandwidthEstimate())
Ryan Hamilton8d9ee76e2018-05-29 23:52:52368 .WillRepeatedly(Return(quic::QuicBandwidth::Zero()));
rch1e543ec2015-03-29 07:04:40369 EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(AnyNumber());
rch08cae032017-03-29 00:59:15370 EXPECT_CALL(*send_algorithm_, OnApplicationLimited(_)).Times(AnyNumber());
rch0d5bcf62017-05-24 22:48:45371 EXPECT_CALL(*send_algorithm_, GetCongestionControlType())
372 .Times(AnyNumber());
Renjie Tang6ff9a9b2021-02-03 22:11:09373 helper_ = std::make_unique<QuicChromiumConnectionHelper>(
374 &clock_, &random_generator_);
375 alarm_factory_ =
376 std::make_unique<QuicChromiumAlarmFactory>(runner_.get(), &clock_);
rch16c74d1d2016-04-22 06:14:07377
Michael Warres74ee3ce2017-10-09 15:26:37378 connection_ = new TestQuicConnection(
Nick Harper23290b82019-05-02 00:02:56379 quic::test::SupportedVersions(version_), connection_id_, peer_addr_,
380 helper_.get(), alarm_factory_.get(),
Ryan Hamilton9edcf1a2017-11-22 05:55:17381 new QuicChromiumPacketWriter(
382 socket.get(), base::ThreadTaskRunnerHandle::Get().get()));
[email protected]f702d572012-12-04 15:56:20383 connection_->set_visitor(&visitor_);
[email protected]fee17f72013-02-03 07:47:41384 connection_->SetSendAlgorithm(send_algorithm_);
rch03b7a202016-02-05 00:54:20385
386 // Load a certificate that is valid for *.example.org
387 scoped_refptr<X509Certificate> test_cert(
388 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
389 EXPECT_TRUE(test_cert.get());
390
391 verify_details_.cert_verify_result.verified_cert = test_cert;
392 verify_details_.cert_verify_result.is_issued_by_known_root = true;
393 crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details_);
394
xunjieli84adaab2016-09-20 01:12:28395 base::TimeTicks dns_end = base::TimeTicks::Now();
Peter Kastinge5a38ed2021-10-02 03:06:35396 base::TimeTicks dns_start = dns_end - base::Milliseconds(1);
Renjie Tang6ff9a9b2021-02-03 22:11:09397 session_ = std::make_unique<QuicChromiumClientSession>(
xunjielib53b38c2016-03-24 15:54:36398 connection_, std::move(socket),
rtenneti1cd3b162015-09-29 02:58:28399 /*stream_factory=*/nullptr, &crypto_client_stream_factory_, &clock_,
Nick Harper89bc7212018-07-31 19:07:57400 &transport_security_state_, /*ssl_config_service=*/nullptr,
danakjad1777e2016-04-16 00:56:42401 base::WrapUnique(static_cast<QuicServerInfo*>(nullptr)),
Paul Jensen8e3c5d32018-02-19 17:06:33402 QuicSessionKey(kDefaultServerHostName, kDefaultServerPort,
dalyk51ab46b2019-10-15 15:14:34403 PRIVACY_MODE_DISABLED, SocketTag(),
Tsuyoshi Horo7acebce2022-05-12 06:13:23404 NetworkIsolationKey(), SecureDnsPolicy::kAllow,
405 /*require_dns_https_alpn=*/false),
Bence Béky1ceba552019-07-19 17:11:05406 /*require_confirmation=*/false,
Bence Béky1ceba552019-07-19 17:11:05407 /*migrate_session_early_v2=*/false,
Zhongyi Shi757fcce2018-06-27 05:41:27408 /*migrate_session_on_network_change_v2=*/false,
409 /*default_network=*/NetworkChangeNotifier::kInvalidNetworkHandle,
Zhongyi Shie01f2db2019-02-22 19:53:23410 quic::QuicTime::Delta::FromMilliseconds(
Ryan Sleevi2e8255b2019-07-17 21:02:21411 kDefaultRetransmittableOnWireTimeout.InMilliseconds()),
Zhongyi Shiaf38c4e42019-08-29 22:49:05412 /*migrate_idle_session=*/false, /*allow_port_migration=*/false,
413 kDefaultIdleSessionMigrationPeriod, kMaxTimeOnNonDefaultNetwork,
Zhongyi Shiee760762018-08-01 00:54:29414 kMaxMigrationsToNonDefaultNetworkOnWriteError,
Zhongyi Shi8b1e43f2017-12-13 20:46:30415 kMaxMigrationsToNonDefaultNetworkOnPathDegrading,
Zhongyi Shi5f587cc2017-11-21 23:24:17416 kQuicYieldAfterPacketsRead,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52417 quic::QuicTime::Delta::FromMilliseconds(
418 kQuicYieldAfterDurationMilliseconds),
Yixin Wang079ad542018-01-11 04:06:05419 client_headers_include_h2_stream_dependency_, /*cert_verify_flags=*/0,
Matt Menkefca05b62019-09-20 23:15:56420 quic::test::DefaultQuicConfig(),
421 std::make_unique<TestQuicCryptoClientConfigHandle>(&crypto_config_),
Matt Menked804aaf2020-07-21 21:25:48422 "CONNECTION_UNKNOWN", dns_start, dns_end,
423 std::make_unique<quic::QuicClientPushPromiseIndex>(), nullptr,
Zhongyi Shic16b4102019-02-12 00:37:40424 base::DefaultTickClock::GetInstance(),
xunjieli84adaab2016-09-20 01:12:28425 base::ThreadTaskRunnerHandle::Get().get(),
Matt Reichhoff0049a0b72021-10-20 20:44:26426 /*socket_performance_watcher=*/nullptr, NetLog::Get());
rtennetid39bd762015-06-12 01:05:52427 session_->Initialize();
rchf0b18c8a2017-05-05 19:31:57428
Bence Béky6e243aa2019-12-13 19:01:07429 // Blackhole QPACK decoder stream instead of constructing mock writes.
430 if (VersionUsesHttp3(version_.transport_version)) {
431 session_->qpack_decoder()->set_qpack_stream_sender_delegate(
432 &noop_qpack_stream_sender_delegate_);
433 }
434
435 TestCompletionCallback callback;
rch433bf5f2017-02-14 04:10:47436 session_->CryptoConnect(callback.callback());
Ryan Hamilton6c2a2a82017-12-15 02:06:28437 stream_ = std::make_unique<QuicHttpStream>(
Dan McArdle68a5f622021-07-09 20:56:53438 session_->CreateHandle(
439 url::SchemeHostPort(url::kHttpsScheme, "www.example.org", 443)),
Eric Orthac661912022-01-10 21:44:17440 /*dns_aliases=*/std::set<std::string>());
Ryan Hamilton6c2a2a82017-12-15 02:06:28441 promised_stream_ = std::make_unique<QuicHttpStream>(
Dan McArdle68a5f622021-07-09 20:56:53442 session_->CreateHandle(
443 url::SchemeHostPort(url::kHttpsScheme, "www.example.org", 443)),
Eric Orthac661912022-01-10 21:44:17444 /*dns_aliases=*/std::set<std::string>());
ckrasic3865ee0f2016-02-29 22:04:56445 push_promise_[":path"] = "/bar";
446 push_promise_[":authority"] = "www.example.org";
447 push_promise_[":version"] = "HTTP/1.1";
448 push_promise_[":method"] = "GET";
449 push_promise_[":scheme"] = "https";
450
Kenichi Ishibashif8634ab2021-03-16 23:41:28451 promised_response_[":status"] = "200";
ckrasic3865ee0f2016-02-29 22:04:56452 promised_response_[":version"] = "HTTP/1.1";
453 promised_response_["content-type"] = "text/plain";
454
David Schinazi3f7465c2019-07-12 01:57:05455 promise_url_ =
456 quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
[email protected]6cca996b2013-01-25 07:43:36457 }
458
bnc614a92d32016-04-04 13:56:07459 void SetRequest(const string& method,
460 const string& path,
[email protected]1e960032013-12-20 19:00:20461 RequestPriority priority) {
rchcd379012017-04-12 21:53:32462 request_headers_ = client_maker_.GetRequestHeaders(method, "https", path);
[email protected]6cca996b2013-01-25 07:43:36463 }
464
bnc614a92d32016-04-04 13:56:07465 void SetResponse(const string& status, const string& body) {
alyssar2adf3ac2016-05-03 17:12:58466 response_headers_ = server_maker_.GetResponseHeaders(status);
[email protected]92bf17c2014-03-03 21:14:03467 response_data_ = body;
[email protected]6cca996b2013-01-25 07:43:36468 }
[email protected]f702d572012-12-04 15:56:20469
Ryan Hamilton8d9ee76e2018-05-29 23:52:52470 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientDataPacket(
Fan Yangac867502019-01-28 21:10:23471 uint64_t packet_number,
[email protected]e8ff26842013-03-22 21:02:05472 bool should_include_version,
[email protected]f702d572012-12-04 15:56:20473 bool fin,
Victor Vasiliev47ecb6a2020-10-14 17:22:10474 absl::string_view data) {
Ryan Hamilton7505eb92019-06-08 00:22:17475 return client_maker_.MakeDataPacket(packet_number, stream_id_,
476 should_include_version, fin, data);
alyssar2adf3ac2016-05-03 17:12:58477 }
478
Ryan Hamilton8d9ee76e2018-05-29 23:52:52479 std::unique_ptr<quic::QuicReceivedPacket> ConstructServerDataPacket(
Fan Yangac867502019-01-28 21:10:23480 uint64_t packet_number,
alyssar2adf3ac2016-05-03 17:12:58481 bool should_include_version,
482 bool fin,
Victor Vasiliev47ecb6a2020-10-14 17:22:10483 absl::string_view data) {
Ryan Hamilton7505eb92019-06-08 00:22:17484 return server_maker_.MakeDataPacket(packet_number, stream_id_,
485 should_include_version, fin, data);
ckrasic3865ee0f2016-02-29 22:04:56486 }
487
Ryan Hamilton8d9ee76e2018-05-29 23:52:52488 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23489 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52490 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56491 bool should_include_version,
492 bool fin,
493 RequestPriority request_priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02494 size_t* spdy_headers_frame_length) {
Yixin Wang7a3f1b8d2018-01-17 21:40:48495 return InnerConstructRequestHeadersPacket(
496 packet_number, stream_id, should_include_version, fin, request_priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02497 0, spdy_headers_frame_length);
Yixin Wang7a3f1b8d2018-01-17 21:40:48498 }
499
Ryan Hamilton8d9ee76e2018-05-29 23:52:52500 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23501 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52502 quic::QuicStreamId stream_id,
Yixin Wang7a3f1b8d2018-01-17 21:40:48503 bool should_include_version,
504 bool fin,
505 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52506 quic::QuicStreamId parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02507 size_t* spdy_headers_frame_length) {
Ryan Hamilton0239aac2018-05-19 00:03:13508 spdy::SpdyPriority priority =
ckrasic3865ee0f2016-02-29 22:04:56509 ConvertRequestPriorityToQuicPriority(request_priority);
alyssar2adf3ac2016-05-03 17:12:58510 return client_maker_.MakeRequestHeadersPacket(
ckrasic3865ee0f2016-02-29 22:04:56511 packet_number, stream_id, should_include_version, fin, priority,
Yixin Wang7a3f1b8d2018-01-17 21:40:48512 std::move(request_headers_), parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02513 spdy_headers_frame_length);
[email protected]f702d572012-12-04 15:56:20514 }
515
Ryan Hamilton8d9ee76e2018-05-29 23:52:52516 std::unique_ptr<quic::QuicReceivedPacket>
Yixin Wange7ecc472018-03-06 19:00:25517 ConstructRequestHeadersAndDataFramesPacket(
Fan Yangac867502019-01-28 21:10:23518 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52519 quic::QuicStreamId stream_id,
Yixin Wange7ecc472018-03-06 19:00:25520 bool should_include_version,
521 bool fin,
522 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52523 quic::QuicStreamId parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25524 size_t* spdy_headers_frame_length,
525 const std::vector<std::string>& data_writes) {
Ryan Hamilton0239aac2018-05-19 00:03:13526 spdy::SpdyPriority priority =
Yixin Wange7ecc472018-03-06 19:00:25527 ConvertRequestPriorityToQuicPriority(request_priority);
528 return client_maker_.MakeRequestHeadersAndMultipleDataFramesPacket(
529 packet_number, stream_id, should_include_version, fin, priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02530 std::move(request_headers_), parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25531 spdy_headers_frame_length, data_writes);
532 }
533
Ryan Hamilton8d9ee76e2018-05-29 23:52:52534 std::unique_ptr<quic::QuicReceivedPacket> ConstructRequestAndRstPacket(
Fan Yangac867502019-01-28 21:10:23535 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52536 quic::QuicStreamId stream_id,
Yixin Wange7ecc472018-03-06 19:00:25537 bool should_include_version,
538 bool fin,
539 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52540 quic::QuicStreamId parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25541 size_t* spdy_headers_frame_length,
Ryan Hamiltonb5d4c5a2019-06-21 22:08:41542 quic::QuicRstStreamErrorCode error_code) {
Ryan Hamilton0239aac2018-05-19 00:03:13543 spdy::SpdyPriority priority =
Yixin Wange7ecc472018-03-06 19:00:25544 ConvertRequestPriorityToQuicPriority(request_priority);
545 return client_maker_.MakeRequestHeadersAndRstPacket(
546 packet_number, stream_id, should_include_version, fin, priority,
547 std::move(request_headers_), parent_stream_id,
Ryan Hamiltonb5d4c5a2019-06-21 22:08:41548 spdy_headers_frame_length, error_code);
Yixin Wange7ecc472018-03-06 19:00:25549 }
550
Ryan Hamilton8d9ee76e2018-05-29 23:52:52551 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructResponseHeadersPacket(
Fan Yangac867502019-01-28 21:10:23552 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52553 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56554 bool fin,
555 size_t* spdy_headers_frame_length) {
alyssar2adf3ac2016-05-03 17:12:58556 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26557 packet_number, stream_id, !kIncludeVersion, fin,
Ryan Hamilton0d65a8c2019-06-07 00:46:02558 std::move(response_headers_), spdy_headers_frame_length);
[email protected]1e960032013-12-20 19:00:20559 }
560
Ryan Hamilton8d9ee76e2018-05-29 23:52:52561 std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseHeadersPacket(
Fan Yangac867502019-01-28 21:10:23562 uint64_t packet_number,
sclittlec4dc1a32015-09-24 00:15:45563 bool fin,
564 size_t* spdy_headers_frame_length) {
ckrasic3865ee0f2016-02-29 22:04:56565 return InnerConstructResponseHeadersPacket(packet_number, stream_id_, fin,
566 spdy_headers_frame_length);
[email protected]1e960032013-12-20 19:00:20567 }
568
Ryan Hamilton8d9ee76e2018-05-29 23:52:52569 std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseTrailersPacket(
Fan Yangac867502019-01-28 21:10:23570 uint64_t packet_number,
xunjieli34291fe12016-03-02 13:58:38571 bool fin,
Bence Béky4c325e52020-10-22 20:48:01572 spdy::Http2HeaderBlock trailers,
Ryan Hamilton0d65a8c2019-06-07 00:46:02573 size_t* spdy_headers_frame_length) {
alyssar2adf3ac2016-05-03 17:12:58574 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26575 packet_number, stream_id_, !kIncludeVersion, fin, std::move(trailers),
Ryan Hamilton0d65a8c2019-06-07 00:46:02576 spdy_headers_frame_length);
xunjieli34291fe12016-03-02 13:58:38577 }
578
Ryan Hamilton8d9ee76e2018-05-29 23:52:52579 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientRstStreamErrorPacket(
Fan Yangac867502019-01-28 21:10:23580 uint64_t packet_number,
maksim.sisov84e20c92016-06-23 08:49:34581 bool include_version) {
582 return client_maker_.MakeRstPacket(packet_number, include_version,
583 stream_id_,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52584 quic::QUIC_ERROR_PROCESSING_STREAM);
maksim.sisov84e20c92016-06-23 08:49:34585 }
586
Ryan Hamilton8d9ee76e2018-05-29 23:52:52587 std::unique_ptr<quic::QuicReceivedPacket> ConstructAckAndRstStreamPacket(
Fan Yangac867502019-01-28 21:10:23588 uint64_t packet_number) {
Renjie Tangcd594f32020-07-11 20:18:34589 return client_maker_.MakeAckAndRstPacket(packet_number, !kIncludeVersion,
590 stream_id_,
591 quic::QUIC_STREAM_CANCELLED, 2, 1);
[email protected]c5e1aca2014-01-30 04:03:04592 }
593
Ryan Hamilton8d9ee76e2018-05-29 23:52:52594 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientAckPacket(
Fan Yangac867502019-01-28 21:10:23595 uint64_t packet_number,
596 uint64_t largest_received,
Renjie Tangcd594f32020-07-11 20:18:34597 uint64_t smallest_received) {
alyssar2adf3ac2016-05-03 17:12:58598 return client_maker_.MakeAckPacket(packet_number, largest_received,
Renjie Tangcd594f32020-07-11 20:18:34599 smallest_received);
alyssar2adf3ac2016-05-03 17:12:58600 }
601
Ryan Hamilton8d9ee76e2018-05-29 23:52:52602 std::unique_ptr<quic::QuicReceivedPacket> ConstructServerAckPacket(
Fan Yangac867502019-01-28 21:10:23603 uint64_t packet_number,
604 uint64_t largest_received,
605 uint64_t smallest_received,
606 uint64_t least_unacked) {
alyssar2adf3ac2016-05-03 17:12:58607 return server_maker_.MakeAckPacket(packet_number, largest_received,
Bence Béky7a45d4d2020-05-08 01:59:23608 smallest_received, least_unacked);
[email protected]63534512012-12-23 18:49:00609 }
610
Ryan Hamilton0d65a8c2019-06-07 00:46:02611 std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket() {
612 return client_maker_.MakeInitialSettingsPacket(1);
fayang3bcb8b502016-12-07 21:44:37613 }
614
Renjie Tangaadb84b2019-08-31 01:00:23615 std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket(
616 int packet_number) {
617 return client_maker_.MakeInitialSettingsPacket(packet_number);
618 }
619
Victor Vasiliev076657c2019-03-12 02:46:43620 std::string ConstructDataHeader(size_t body_len) {
Nick Harperc6cb7a612020-02-24 20:03:32621 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:41622 return "";
623 }
Victor Vasilievc617d452022-03-07 15:54:25624 quiche::QuicheBuffer buffer = quic::HttpEncoder::SerializeDataFrameHeader(
625 body_len, quiche::SimpleBufferAllocator::Get());
Ian Swett17d4d1c02021-06-08 19:52:41626 return std::string(buffer.data(), buffer.size());
Renjief49758b2019-01-11 23:32:41627 }
628
Ryan Hamilton8d9ee76e2018-05-29 23:52:52629 void ReceivePromise(quic::QuicStreamId id) {
630 auto headers = quic::test::AsHeaderList(push_promise_);
rch08e198572017-05-09 16:56:55631 QuicChromiumClientStream::Handle* stream =
ckrasic3865ee0f2016-02-29 22:04:56632 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
ckrasic32b17dcd2016-10-31 06:15:35633 stream->OnPromiseHeaderList(id, headers.uncompressed_header_bytes(),
634 headers);
ckrasic3865ee0f2016-02-29 22:04:56635 }
636
xunjieli84adaab2016-09-20 01:12:28637 void ExpectLoadTimingValid(const LoadTimingInfo& load_timing_info,
xunjieli100937eb52016-09-15 20:09:37638 bool session_reused) {
639 EXPECT_EQ(session_reused, load_timing_info.socket_reused);
xunjieli84adaab2016-09-20 01:12:28640 if (session_reused) {
641 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
642 } else {
643 ExpectConnectTimingHasTimes(
644 load_timing_info.connect_timing,
645 CONNECT_TIMING_HAS_SSL_TIMES | CONNECT_TIMING_HAS_DNS_TIMES);
646 }
647 ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info);
xunjieli100937eb52016-09-15 20:09:37648 }
649
Fan Yang32c5a112018-12-10 20:06:33650 quic::QuicStreamId GetNthClientInitiatedBidirectionalStreamId(int n) {
Nick Harper23290b82019-05-02 00:02:56651 return quic::test::GetNthClientInitiatedBidirectionalStreamId(
652 version_.transport_version, n);
ckrasicbf2f59c2017-05-04 23:54:36653 }
654
Fan Yang32c5a112018-12-10 20:06:33655 quic::QuicStreamId GetNthServerInitiatedUnidirectionalStreamId(int n) {
Nick Harper23290b82019-05-02 00:02:56656 return quic::test::GetNthServerInitiatedUnidirectionalStreamId(
657 version_.transport_version, n);
ckrasicbf2f59c2017-05-04 23:54:36658 }
659
Patrick Meenan0041f332022-05-19 23:48:35660 quic::test::QuicFlagSaver saver_;
Ryan Hamiltona1d1f4a2019-06-26 14:43:04661
Nick Harper23290b82019-05-02 00:02:56662 const quic::ParsedQuicVersion version_;
Yixin Wang079ad542018-01-11 04:06:05663 const bool client_headers_include_h2_stream_dependency_;
664
Matt Reichhoff0049a0b72021-10-20 20:44:26665 NetLogWithSource net_log_with_source_{
666 NetLogWithSource::Make(NetLog::Get(), NetLogSourceType::NONE)};
667 RecordingNetLogObserver net_log_observer_;
Keishi Hattori0e45c022021-11-27 09:25:52668 raw_ptr<quic::test::MockSendAlgorithm> send_algorithm_;
[email protected]f702d572012-12-04 15:56:20669 scoped_refptr<TestTaskRunner> runner_;
danakjad1777e2016-04-16 00:56:42670 std::unique_ptr<MockWrite[]> mock_writes_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52671 quic::MockClock clock_;
Keishi Hattori0e45c022021-11-27 09:25:52672 raw_ptr<TestQuicConnection> connection_;
danakjad1777e2016-04-16 00:56:42673 std::unique_ptr<QuicChromiumConnectionHelper> helper_;
rch16c74d1d2016-04-22 06:14:07674 std::unique_ptr<QuicChromiumAlarmFactory> alarm_factory_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52675 testing::StrictMock<quic::test::MockQuicConnectionVisitor> visitor_;
rch97827ee2017-05-24 23:49:12676 std::unique_ptr<UploadDataStream> upload_data_stream_;
danakjad1777e2016-04-16 00:56:42677 std::unique_ptr<QuicHttpStream> stream_;
[email protected]5db452202014-08-19 05:22:15678 TransportSecurityState transport_security_state_;
danakjad1777e2016-04-16 00:56:42679 std::unique_ptr<QuicChromiumClientSession> session_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52680 quic::QuicCryptoClientConfig crypto_config_;
[email protected]f702d572012-12-04 15:56:20681 TestCompletionCallback callback_;
682 HttpRequestInfo request_;
683 HttpRequestHeaders headers_;
684 HttpResponseInfo response_;
685 scoped_refptr<IOBufferWithSize> read_buffer_;
Bence Béky4c325e52020-10-22 20:48:01686 spdy::Http2HeaderBlock request_headers_;
687 spdy::Http2HeaderBlock response_headers_;
bnc614a92d32016-04-04 13:56:07688 string request_data_;
689 string response_data_;
[email protected]f702d572012-12-04 15:56:20690
ckrasic3865ee0f2016-02-29 22:04:56691 // For server push testing
danakjad1777e2016-04-16 00:56:42692 std::unique_ptr<QuicHttpStream> promised_stream_;
Bence Béky4c325e52020-10-22 20:48:01693 spdy::Http2HeaderBlock push_promise_;
694 spdy::Http2HeaderBlock promised_response_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52695 const quic::QuicStreamId promise_id_;
ckrasic3865ee0f2016-02-29 22:04:56696 string promise_url_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52697 const quic::QuicStreamId stream_id_;
ckrasic3865ee0f2016-02-29 22:04:56698
Ryan Hamilton8d9ee76e2018-05-29 23:52:52699 const quic::QuicConnectionId connection_id_;
alyssar2adf3ac2016-05-03 17:12:58700 QuicTestPacketMaker client_maker_;
701 QuicTestPacketMaker server_maker_;
[email protected]f702d572012-12-04 15:56:20702 IPEndPoint self_addr_;
703 IPEndPoint peer_addr_;
Tsuyoshi Horo432981d52022-06-09 09:50:13704 quic::test::MockRandom random_generator_{0};
rch03b7a202016-02-05 00:54:20705 ProofVerifyDetailsChromium verify_details_;
[email protected]e8ff26842013-03-22 21:02:05706 MockCryptoClientStreamFactory crypto_client_stream_factory_;
danakjad1777e2016-04-16 00:56:42707 std::unique_ptr<StaticSocketDataProvider> socket_data_;
Ryan Hamilton0d65a8c2019-06-07 00:46:02708 QuicPacketPrinter printer_;
[email protected]f702d572012-12-04 15:56:20709 std::vector<PacketToWrite> writes_;
Bence Béky6e243aa2019-12-13 19:01:07710 quic::test::NoopQpackStreamSenderDelegate noop_qpack_stream_sender_delegate_;
[email protected]f702d572012-12-04 15:56:20711};
712
David Schinazi09e9a6012019-10-03 17:37:57713INSTANTIATE_TEST_SUITE_P(VersionIncludeStreamDependencySequence,
714 QuicHttpStreamTest,
715 ::testing::ValuesIn(GetTestParams()),
716 ::testing::PrintToStringParamName());
[email protected]1e960032013-12-20 19:00:20717
718TEST_P(QuicHttpStreamTest, RenewStreamForAuth) {
[email protected]ed3fc15d2013-03-08 18:37:44719 Initialize();
rtennetibe635732014-10-02 22:51:42720 EXPECT_EQ(nullptr, stream_->RenewStreamForAuth());
[email protected]f702d572012-12-04 15:56:20721}
722
mmenkebd84c392015-09-02 14:12:34723TEST_P(QuicHttpStreamTest, CanReuseConnection) {
[email protected]ed3fc15d2013-03-08 18:37:44724 Initialize();
mmenkebd84c392015-09-02 14:12:34725 EXPECT_FALSE(stream_->CanReuseConnection());
[email protected]f702d572012-12-04 15:56:20726}
727
jri231c2972016-03-08 19:50:11728TEST_P(QuicHttpStreamTest, DisableConnectionMigrationForStream) {
Zhongyi Shibb28b1f2018-07-18 02:41:26729 request_.load_flags |= LOAD_DISABLE_CONNECTION_MIGRATION_TO_CELLULAR;
jri231c2972016-03-08 19:50:11730 Initialize();
Ali Beyada0b1a1c2022-04-08 20:08:14731 stream_->RegisterRequest(&request_);
732 EXPECT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:26733 net_log_with_source_,
734 callback_.callback()));
rch08e198572017-05-09 16:56:55735 QuicChromiumClientStream::Handle* client_stream =
jri231c2972016-03-08 19:50:11736 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
Zhongyi Shibb28b1f2018-07-18 02:41:26737 EXPECT_FALSE(client_stream->can_migrate_to_cellular_network());
jri231c2972016-03-08 19:50:11738}
739
[email protected]1e960032013-12-20 19:00:20740TEST_P(QuicHttpStreamTest, GetRequest) {
741 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:45742 size_t spdy_request_header_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:23743 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:25744 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:23745 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:37746 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23747 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
748 kIncludeVersion, kFin, DEFAULT_PRIORITY,
749 &spdy_request_header_frame_length));
fayang3bcb8b502016-12-07 21:44:37750
[email protected]f702d572012-12-04 15:56:20751 Initialize();
752
753 request_.method = "GET";
rchcd379012017-04-12 21:53:32754 request_.url = GURL("https://www.example.org/");
[email protected]f702d572012-12-04 15:56:20755
xunjieli100937eb52016-09-15 20:09:37756 // Make sure getting load timing from the stream early does not crash.
757 LoadTimingInfo load_timing_info;
758 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
Ali Beyada0b1a1c2022-04-08 20:08:14759 stream_->RegisterRequest(&request_);
760 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:26761 net_log_with_source_,
762 callback_.callback()));
rjshaded5ced072015-12-18 19:26:02763 EXPECT_EQ(OK,
764 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20765
766 // Ack the request.
Renjie90e808e2019-01-24 07:24:04767 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]f702d572012-12-04 15:56:20768
robpercival214763f2016-07-01 23:27:01769 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
770 IsError(ERR_IO_PENDING));
[email protected]f702d572012-12-04 15:56:20771
Kenichi Ishibashif8634ab2021-03-16 23:41:28772 SetResponse("404", string());
sclittlec4dc1a32015-09-24 00:15:45773 size_t spdy_response_header_frame_length;
774 ProcessPacket(ConstructResponseHeadersPacket(
775 2, kFin, &spdy_response_header_frame_length));
[email protected]f702d572012-12-04 15:56:20776
777 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:01778 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]cadac622013-06-11 16:46:36779 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:20780 EXPECT_EQ(404, response_.headers->response_code());
781 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
[email protected]6ed67432014-06-24 01:53:53782 EXPECT_FALSE(response_.response_time.is_null());
783 EXPECT_FALSE(response_.request_time.is_null());
[email protected]f702d572012-12-04 15:56:20784
785 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:02786 EXPECT_EQ(0,
787 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
788 callback_.callback()));
[email protected]f702d572012-12-04 15:56:20789 EXPECT_TRUE(stream_->IsResponseBodyComplete());
790 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:10791
xunjieli100937eb52016-09-15 20:09:37792 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
xunjieli84adaab2016-09-20 01:12:28793 ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
xunjieli100937eb52016-09-15 20:09:37794
sclittle1edeeb22015-09-02 20:46:10795 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:45796 // headers and payload.
797 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
798 stream_->GetTotalSentBytes());
799 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length),
800 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:20801}
802
xunjieli100937eb52016-09-15 20:09:37803TEST_P(QuicHttpStreamTest, LoadTimingTwoRequests) {
804 SetRequest("GET", "/", DEFAULT_PRIORITY);
805 size_t spdy_request_header_frame_length;
806
Renjie Tangaadb84b2019-08-31 01:00:23807 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:25808 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:23809 AddWrite(ConstructInitialSettingsPacket(packet_number++));
xunjieli100937eb52016-09-15 20:09:37810 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23811 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
812 kIncludeVersion, kFin, DEFAULT_PRIORITY,
813 &spdy_request_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37814
815 // SetRequest() again for second request as |request_headers_| was moved.
816 SetRequest("GET", "/", DEFAULT_PRIORITY);
817 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23818 packet_number++, GetNthClientInitiatedBidirectionalStreamId(1),
819 kIncludeVersion, kFin, DEFAULT_PRIORITY,
820 GetNthClientInitiatedBidirectionalStreamId(0),
Ryan Hamilton0d65a8c2019-06-07 00:46:02821 &spdy_request_header_frame_length));
Renjie Tangcd594f32020-07-11 20:18:34822 AddWrite(
823 ConstructClientAckPacket(packet_number++, 3, 1)); // Ack the responses.
xunjieli100937eb52016-09-15 20:09:37824
825 Initialize();
826
827 request_.method = "GET";
rchcd379012017-04-12 21:53:32828 request_.url = GURL("https://www.example.org/");
xunjieli100937eb52016-09-15 20:09:37829 // Start first request.
Ali Beyada0b1a1c2022-04-08 20:08:14830 stream_->RegisterRequest(&request_);
831 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:26832 net_log_with_source_,
833 callback_.callback()));
xunjieli100937eb52016-09-15 20:09:37834 EXPECT_EQ(OK,
835 stream_->SendRequest(headers_, &response_, callback_.callback()));
836
837 // Start a second request.
Dan McArdle68a5f622021-07-09 20:56:53838 QuicHttpStream stream2(session_->CreateHandle(url::SchemeHostPort(
839 url::kHttpsScheme, "www.example.org", 443)),
840 {} /* dns_aliases */);
xunjieli100937eb52016-09-15 20:09:37841 TestCompletionCallback callback2;
Ali Beyada0b1a1c2022-04-08 20:08:14842 stream2.RegisterRequest(&request_);
Matt Reichhoff0049a0b72021-10-20 20:44:26843 EXPECT_EQ(
Ali Beyada0b1a1c2022-04-08 20:08:14844 OK, stream2.InitializeStream(true, DEFAULT_PRIORITY, net_log_with_source_,
845 callback2.callback()));
xunjieli100937eb52016-09-15 20:09:37846 EXPECT_EQ(OK,
847 stream2.SendRequest(headers_, &response_, callback2.callback()));
848
849 // Ack both requests.
Renjie90e808e2019-01-24 07:24:04850 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
xunjieli100937eb52016-09-15 20:09:37851
852 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
853 IsError(ERR_IO_PENDING));
854 size_t spdy_response_header_frame_length;
Kenichi Ishibashif8634ab2021-03-16 23:41:28855 SetResponse("200", string());
xunjieli100937eb52016-09-15 20:09:37856 ProcessPacket(InnerConstructResponseHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33857 2, GetNthClientInitiatedBidirectionalStreamId(0), kFin,
ckrasicbf2f59c2017-05-04 23:54:36858 &spdy_response_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37859
860 // Now that the headers have been processed, the callback will return.
861 EXPECT_THAT(callback_.WaitForResult(), IsOk());
862 EXPECT_EQ(200, response_.headers->response_code());
863
864 // There is no body, so this should return immediately.
865 EXPECT_EQ(0,
866 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
867 callback_.callback()));
868 EXPECT_TRUE(stream_->IsResponseBodyComplete());
869
870 LoadTimingInfo load_timing_info;
871 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
xunjieli84adaab2016-09-20 01:12:28872 ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
xunjieli100937eb52016-09-15 20:09:37873
874 // SetResponse() again for second request as |response_headers_| was moved.
Kenichi Ishibashif8634ab2021-03-16 23:41:28875 SetResponse("200", string());
xunjieli100937eb52016-09-15 20:09:37876 EXPECT_THAT(stream2.ReadResponseHeaders(callback2.callback()),
877 IsError(ERR_IO_PENDING));
878
879 ProcessPacket(InnerConstructResponseHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33880 3, GetNthClientInitiatedBidirectionalStreamId(1), kFin,
ckrasicbf2f59c2017-05-04 23:54:36881 &spdy_response_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37882
883 EXPECT_THAT(callback2.WaitForResult(), IsOk());
884
885 // There is no body, so this should return immediately.
886 EXPECT_EQ(0,
887 stream2.ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
888 callback2.callback()));
889 EXPECT_TRUE(stream2.IsResponseBodyComplete());
890
891 LoadTimingInfo load_timing_info2;
892 EXPECT_TRUE(stream2.GetLoadTimingInfo(&load_timing_info2));
xunjieli84adaab2016-09-20 01:12:28893 ExpectLoadTimingValid(load_timing_info2, /*session_reused=*/true);
xunjieli100937eb52016-09-15 20:09:37894}
895
xunjieli34291fe12016-03-02 13:58:38896// QuicHttpStream does not currently support trailers. It should ignore
897// trailers upon receiving them.
898TEST_P(QuicHttpStreamTest, GetRequestWithTrailers) {
899 SetRequest("GET", "/", DEFAULT_PRIORITY);
900 size_t spdy_request_header_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:23901 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:25902 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:23903 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:37904 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23905 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
906 kIncludeVersion, kFin, DEFAULT_PRIORITY,
907 &spdy_request_header_frame_length));
Renjie Tangcd594f32020-07-11 20:18:34908 AddWrite(
909 ConstructClientAckPacket(packet_number++, 3, 1)); // Ack the data packet.
xunjieli34291fe12016-03-02 13:58:38910
911 Initialize();
912
913 request_.method = "GET";
rchcd379012017-04-12 21:53:32914 request_.url = GURL("https://www.example.org/");
Ali Beyada0b1a1c2022-04-08 20:08:14915 stream_->RegisterRequest(&request_);
916 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:26917 net_log_with_source_,
918 callback_.callback()));
xunjieli5fafe142016-03-23 23:32:54919
xunjieli34291fe12016-03-02 13:58:38920 EXPECT_EQ(OK,
921 stream_->SendRequest(headers_, &response_, callback_.callback()));
xunjieli34291fe12016-03-02 13:58:38922 // Ack the request.
Renjie90e808e2019-01-24 07:24:04923 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
xunjieli34291fe12016-03-02 13:58:38924
robpercival214763f2016-07-01 23:27:01925 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
926 IsError(ERR_IO_PENDING));
xunjieli34291fe12016-03-02 13:58:38927
Kenichi Ishibashif8634ab2021-03-16 23:41:28928 SetResponse("200", string());
xunjieli34291fe12016-03-02 13:58:38929
930 // Send the response headers.
931 size_t spdy_response_header_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:02932 ProcessPacket(ConstructResponseHeadersPacket(
933 2, !kFin, &spdy_response_header_frame_length));
xunjieli34291fe12016-03-02 13:58:38934 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:01935 EXPECT_THAT(callback_.WaitForResult(), IsOk());
xunjieli34291fe12016-03-02 13:58:38936 ASSERT_TRUE(response_.headers.get());
937 EXPECT_EQ(200, response_.headers->response_code());
938 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
939 EXPECT_FALSE(response_.response_time.is_null());
940 EXPECT_FALSE(response_.request_time.is_null());
941
942 // Send the response body.
943 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:43944 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:17945 ProcessPacket(
946 ConstructServerDataPacket(3, false, !kFin, header + kResponseBody));
Bence Béky4c325e52020-10-22 20:48:01947 spdy::Http2HeaderBlock trailers;
xunjieli34291fe12016-03-02 13:58:38948 size_t spdy_trailers_frame_length;
949 trailers["foo"] = "bar";
Victor Vasiliev7da08172019-10-14 06:04:25950 if (!quic::VersionUsesHttp3(version_.transport_version)) {
Ryan Hamiltona1d1f4a2019-06-26 14:43:04951 trailers[quic::kFinalOffsetHeaderKey] =
952 base::NumberToString(strlen(kResponseBody) + header.length());
953 }
Ryan Hamilton0d65a8c2019-06-07 00:46:02954 ProcessPacket(ConstructResponseTrailersPacket(4, kFin, std::move(trailers),
955 &spdy_trailers_frame_length));
xunjieli34291fe12016-03-02 13:58:38956
957 // Make sure trailers are processed.
fdoray92e35a72016-06-10 15:54:55958 base::RunLoop().RunUntilIdle();
xunjieli34291fe12016-03-02 13:58:38959
960 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
961 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
962 callback_.callback()));
963 EXPECT_TRUE(stream_->IsResponseBodyComplete());
964
965 EXPECT_EQ(OK,
966 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
967 callback_.callback()));
968
969 EXPECT_TRUE(stream_->IsResponseBodyComplete());
970 EXPECT_TRUE(AtEof());
971
972 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
973 // headers and payload.
974 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
975 stream_->GetTotalSentBytes());
Renjief49758b2019-01-11 23:32:41976 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length +
977 strlen(kResponseBody) + header.length() +
978 +spdy_trailers_frame_length),
979 stream_->GetTotalReceivedBytes());
xunjieli5fafe142016-03-23 23:32:54980 // Check that NetLog was filled as expected.
Matt Reichhoff0049a0b72021-10-20 20:44:26981 auto entries = net_log_observer_.GetEntries();
xunjieli5fafe142016-03-23 23:32:54982 size_t pos = ExpectLogContainsSomewhere(
983 entries, /*min_offset=*/0,
mikecirone8b85c432016-09-08 19:11:00984 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
985 NetLogEventPhase::NONE);
xunjieli5fafe142016-03-23 23:32:54986 pos = ExpectLogContainsSomewhere(
987 entries, /*min_offset=*/pos,
mikecirone8b85c432016-09-08 19:11:00988 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
989 NetLogEventPhase::NONE);
xunjieli5fafe142016-03-23 23:32:54990 ExpectLogContainsSomewhere(
991 entries, /*min_offset=*/pos,
mikecirone8b85c432016-09-08 19:11:00992 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
993 NetLogEventPhase::NONE);
xunjieli34291fe12016-03-02 13:58:38994}
995
Bence Béky6c2c78f2020-08-28 16:49:06996TEST_P(QuicHttpStreamTest, ElideHeadersInNetLog) {
997 Initialize();
998
999 // QuicHttp3Logger is only used with HTTP/3.
1000 if (!VersionUsesHttp3(version_.transport_version)) {
1001 return;
1002 }
1003
Matt Reichhoff0049a0b72021-10-20 20:44:261004 net_log_observer_.SetObserverCaptureMode(NetLogCaptureMode::kDefault);
Bence Béky6c2c78f2020-08-28 16:49:061005
Bence Békye0d3747d2020-08-28 23:16:401006 // Send first request.
Bence Béky6c2c78f2020-08-28 16:49:061007 SetRequest("GET", "/", DEFAULT_PRIORITY);
1008 request_.method = "GET";
1009 request_.url = GURL("https://www.example.org/");
1010 headers_.SetHeader(HttpRequestHeaders::kCookie, "secret");
1011
1012 size_t spdy_request_header_frame_length;
Bence Békye0d3747d2020-08-28 23:16:401013 int outgoing_packet_number = 1;
1014 AddWrite(ConstructInitialSettingsPacket(outgoing_packet_number++));
Bence Béky6c2c78f2020-08-28 16:49:061015 AddWrite(InnerConstructRequestHeadersPacket(
Bence Békye0d3747d2020-08-28 23:16:401016 outgoing_packet_number++, stream_id_, kIncludeVersion, kFin,
1017 DEFAULT_PRIORITY, &spdy_request_header_frame_length));
Bence Béky6c2c78f2020-08-28 16:49:061018
Ali Beyada0b1a1c2022-04-08 20:08:141019 stream_->RegisterRequest(&request_);
Matt Reichhoff0049a0b72021-10-20 20:44:261020 EXPECT_THAT(
Ali Beyada0b1a1c2022-04-08 20:08:141021 stream_->InitializeStream(true, DEFAULT_PRIORITY, net_log_with_source_,
1022 callback_.callback()),
Matt Reichhoff0049a0b72021-10-20 20:44:261023 IsOk());
Bence Béky6c2c78f2020-08-28 16:49:061024 EXPECT_THAT(stream_->SendRequest(headers_, &response_, callback_.callback()),
1025 IsOk());
Bence Békye0d3747d2020-08-28 23:16:401026 int incoming_packet_number = 1;
1027 ProcessPacket(ConstructServerAckPacket(incoming_packet_number++, 1, 1,
1028 1)); // Ack the request.
Bence Béky6c2c78f2020-08-28 16:49:061029
Bence Békye0d3747d2020-08-28 23:16:401030 // Process first response.
Kenichi Ishibashif8634ab2021-03-16 23:41:281031 SetResponse("200", string());
Bence Béky6c2c78f2020-08-28 16:49:061032 response_headers_["set-cookie"] = "secret";
1033 size_t spdy_response_header_frame_length;
1034 ProcessPacket(ConstructResponseHeadersPacket(
Bence Békye0d3747d2020-08-28 23:16:401035 incoming_packet_number++, kFin, &spdy_response_header_frame_length));
Bence Béky6c2c78f2020-08-28 16:49:061036 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
Bence Béky6c2c78f2020-08-28 16:49:061037
1038 ASSERT_TRUE(response_.headers.get());
1039 EXPECT_EQ(200, response_.headers->response_code());
1040 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1041 EXPECT_TRUE(response_.headers->HasHeaderValue("set-cookie", "secret"));
1042
Matt Reichhoff0049a0b72021-10-20 20:44:261043 net_log_observer_.SetObserverCaptureMode(
1044 NetLogCaptureMode::kIncludeSensitive);
Bence Béky6c2c78f2020-08-28 16:49:061045
Bence Békye0d3747d2020-08-28 23:16:401046 // Send second request.
1047 quic::QuicStreamId stream_id = GetNthClientInitiatedBidirectionalStreamId(1);
1048 request_.url = GURL("https://www.example.org/foo");
Bence Béky6c2c78f2020-08-28 16:49:061049
Bence Békye0d3747d2020-08-28 23:16:401050 AddWrite(InnerConstructRequestHeadersPacket(
1051 outgoing_packet_number++, stream_id, kIncludeVersion, kFin,
1052 DEFAULT_PRIORITY, &spdy_request_header_frame_length));
Bence Béky6c2c78f2020-08-28 16:49:061053
Bence Békye0d3747d2020-08-28 23:16:401054 auto stream = std::make_unique<QuicHttpStream>(
Dan McArdle68a5f622021-07-09 20:56:531055 session_->CreateHandle(
1056 url::SchemeHostPort(url::kHttpsScheme, "www.example.org/foo", 443)),
Eric Orthac661912022-01-10 21:44:171057 /*dns_aliases=*/std::set<std::string>());
Ali Beyada0b1a1c2022-04-08 20:08:141058 stream->RegisterRequest(&request_);
Matt Reichhoff0049a0b72021-10-20 20:44:261059 EXPECT_THAT(
Ali Beyada0b1a1c2022-04-08 20:08:141060 stream->InitializeStream(true, DEFAULT_PRIORITY, net_log_with_source_,
1061 callback_.callback()),
Matt Reichhoff0049a0b72021-10-20 20:44:261062 IsOk());
Bence Békye0d3747d2020-08-28 23:16:401063 EXPECT_THAT(stream->SendRequest(headers_, &response_, callback_.callback()),
1064 IsOk());
1065 ProcessPacket(ConstructServerAckPacket(incoming_packet_number++, 1, 1,
1066 1)); // Ack the request.
Bence Béky6c2c78f2020-08-28 16:49:061067
Bence Békye0d3747d2020-08-28 23:16:401068 // Process second response.
Kenichi Ishibashif8634ab2021-03-16 23:41:281069 SetResponse("200", string());
Bence Békye0d3747d2020-08-28 23:16:401070 response_headers_["set-cookie"] = "secret";
1071 ProcessPacket(InnerConstructResponseHeadersPacket(
1072 incoming_packet_number++, stream_id, kFin,
1073 &spdy_response_header_frame_length));
1074 EXPECT_THAT(stream->ReadResponseHeaders(callback_.callback()), IsOk());
Bence Béky6c2c78f2020-08-28 16:49:061075
Bence Békye0d3747d2020-08-28 23:16:401076 ASSERT_TRUE(response_.headers.get());
1077 EXPECT_EQ(200, response_.headers->response_code());
1078 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1079 EXPECT_TRUE(response_.headers->HasHeaderValue("set-cookie", "secret"));
1080
1081 EXPECT_TRUE(AtEof());
1082
1083 // Check that sensitive header value were stripped
1084 // for the first transaction (logged with NetLogCaptureMode::kDefault)
1085 // but not for the second (logged with NetLogCaptureMode::kIncludeSensitive).
1086 auto entries =
Matt Reichhoff0049a0b72021-10-20 20:44:261087 net_log_observer_.GetEntriesWithType(NetLogEventType::HTTP3_HEADERS_SENT);
Bence Békye0d3747d2020-08-28 23:16:401088 ASSERT_EQ(2u, entries.size());
1089 EXPECT_TRUE(
1090 CheckHeader(entries[0].params, "cookie", "[6 bytes were stripped]"));
1091 EXPECT_TRUE(CheckHeader(entries[1].params, "cookie", "secret"));
1092
Matt Reichhoff0049a0b72021-10-20 20:44:261093 entries = net_log_observer_.GetEntriesWithType(
1094 NetLogEventType::HTTP3_HEADERS_DECODED);
Bence Békye0d3747d2020-08-28 23:16:401095 ASSERT_EQ(2u, entries.size());
1096 EXPECT_TRUE(
1097 CheckHeader(entries[0].params, "set-cookie", "[6 bytes were stripped]"));
1098 EXPECT_TRUE(CheckHeader(entries[1].params, "set-cookie", "secret"));
Bence Béky6c2c78f2020-08-28 16:49:061099}
1100
[email protected]3e7dca62013-09-10 16:14:231101// Regression test for http://crbug.com/288128
[email protected]1e960032013-12-20 19:00:201102TEST_P(QuicHttpStreamTest, GetRequestLargeResponse) {
1103 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451104 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231105 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251106 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231107 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371108 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231109 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1110 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1111 &spdy_request_headers_frame_length));
[email protected]3e7dca62013-09-10 16:14:231112 Initialize();
1113
1114 request_.method = "GET";
rchcd379012017-04-12 21:53:321115 request_.url = GURL("https://www.example.org/");
[email protected]3e7dca62013-09-10 16:14:231116
Ali Beyada0b1a1c2022-04-08 20:08:141117 stream_->RegisterRequest(&request_);
1118 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261119 net_log_with_source_,
1120 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021121 EXPECT_EQ(OK,
1122 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:231123
1124 // Ack the request.
Renjie90e808e2019-01-24 07:24:041125 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]3e7dca62013-09-10 16:14:231126
robpercival214763f2016-07-01 23:27:011127 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1128 IsError(ERR_IO_PENDING));
[email protected]3e7dca62013-09-10 16:14:231129
Kenichi Ishibashif8634ab2021-03-16 23:41:281130 response_headers_[":status"] = "200";
bnc086b39e12016-06-24 13:05:261131 response_headers_[":version"] = "HTTP/1.1";
1132 response_headers_["content-type"] = "text/plain";
1133 response_headers_["big6"] = string(1000, 'x'); // Lots of x's.
[email protected]3e7dca62013-09-10 16:14:231134
sclittlec4dc1a32015-09-24 00:15:451135 size_t spdy_response_headers_frame_length;
1136 ProcessPacket(ConstructResponseHeadersPacket(
1137 2, kFin, &spdy_response_headers_frame_length));
[email protected]3e7dca62013-09-10 16:14:231138
1139 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:011140 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]3e7dca62013-09-10 16:14:231141 ASSERT_TRUE(response_.headers.get());
1142 EXPECT_EQ(200, response_.headers->response_code());
1143 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1144
1145 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:021146 EXPECT_EQ(0,
1147 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1148 callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:231149 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1150 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101151
1152 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451153 // headers and payload.
1154 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1155 stream_->GetTotalSentBytes());
1156 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length),
1157 stream_->GetTotalReceivedBytes());
[email protected]3e7dca62013-09-10 16:14:231158}
1159
rchf9f103cbc2014-08-30 05:28:041160// Regression test for http://crbug.com/409101
1161TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendRequest) {
1162 SetRequest("GET", "/", DEFAULT_PRIORITY);
1163 Initialize();
1164
1165 request_.method = "GET";
rchcd379012017-04-12 21:53:321166 request_.url = GURL("https://www.example.org/");
rchf9f103cbc2014-08-30 05:28:041167
Ali Beyada0b1a1c2022-04-08 20:08:141168 stream_->RegisterRequest(&request_);
1169 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261170 net_log_with_source_,
1171 callback_.callback()));
rchf9f103cbc2014-08-30 05:28:041172
jri78ec06a2016-03-31 18:19:401173 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521174 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rchf9f103cbc2014-08-30 05:28:041175
1176 EXPECT_EQ(ERR_CONNECTION_CLOSED,
rjshaded5ced072015-12-18 19:26:021177 stream_->SendRequest(headers_, &response_, callback_.callback()));
sclittle1edeeb22015-09-02 20:46:101178
1179 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1180 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rchf9f103cbc2014-08-30 05:28:041181}
1182
rch03b7a202016-02-05 00:54:201183// Regression test for http://crbug.com/584441
1184TEST_P(QuicHttpStreamTest, GetSSLInfoAfterSessionClosed) {
1185 SetRequest("GET", "/", DEFAULT_PRIORITY);
1186 Initialize();
1187
1188 request_.method = "GET";
rchcd379012017-04-12 21:53:321189 request_.url = GURL("https://www.example.org/");
rch03b7a202016-02-05 00:54:201190
Ali Beyada0b1a1c2022-04-08 20:08:141191 stream_->RegisterRequest(&request_);
1192 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261193 net_log_with_source_,
1194 callback_.callback()));
rch03b7a202016-02-05 00:54:201195
1196 SSLInfo ssl_info;
rch11565e02016-02-09 20:13:471197 EXPECT_FALSE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:201198 stream_->GetSSLInfo(&ssl_info);
rch11565e02016-02-09 20:13:471199 EXPECT_TRUE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:201200
jri78ec06a2016-03-31 18:19:401201 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521202 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rch03b7a202016-02-05 00:54:201203
rch11565e02016-02-09 20:13:471204 SSLInfo ssl_info2;
1205 stream_->GetSSLInfo(&ssl_info2);
1206 EXPECT_TRUE(ssl_info2.is_valid());
rch03b7a202016-02-05 00:54:201207}
1208
rchcd379012017-04-12 21:53:321209TEST_P(QuicHttpStreamTest, GetAlternativeService) {
1210 SetRequest("GET", "/", DEFAULT_PRIORITY);
1211 Initialize();
1212
1213 request_.method = "GET";
1214 request_.url = GURL("https://www.example.org/");
1215
Ali Beyada0b1a1c2022-04-08 20:08:141216 stream_->RegisterRequest(&request_);
1217 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261218 net_log_with_source_,
1219 callback_.callback()));
rchcd379012017-04-12 21:53:321220
1221 AlternativeService alternative_service;
1222 EXPECT_TRUE(stream_->GetAlternativeService(&alternative_service));
1223 EXPECT_EQ(AlternativeService(kProtoQUIC, "www.example.org", 443),
1224 alternative_service);
1225
1226 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521227 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rchcd379012017-04-12 21:53:321228
1229 AlternativeService alternative_service2;
1230 EXPECT_TRUE(stream_->GetAlternativeService(&alternative_service2));
1231 EXPECT_EQ(AlternativeService(kProtoQUIC, "www.example.org", 443),
1232 alternative_service2);
1233}
1234
zhongyica364fbb2015-12-12 03:39:121235TEST_P(QuicHttpStreamTest, LogGranularQuicConnectionError) {
1236 SetRequest("GET", "/", DEFAULT_PRIORITY);
1237 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231238 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251239 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231240 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371241 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231242 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1243 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1244 &spdy_request_headers_frame_length));
fayang3bcb8b502016-12-07 21:44:371245 AddWrite(ConstructAckAndRstStreamPacket(3));
zhongyica364fbb2015-12-12 03:39:121246 Initialize();
1247
1248 request_.method = "GET";
rchcd379012017-04-12 21:53:321249 request_.url = GURL("https://www.example.org/");
zhongyica364fbb2015-12-12 03:39:121250
Ali Beyada0b1a1c2022-04-08 20:08:141251 stream_->RegisterRequest(&request_);
1252 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261253 net_log_with_source_,
1254 callback_.callback()));
zhongyica364fbb2015-12-12 03:39:121255 EXPECT_EQ(OK,
1256 stream_->SendRequest(headers_, &response_, callback_.callback()));
1257
1258 // Ack the request.
Renjie90e808e2019-01-24 07:24:041259 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011260 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1261 IsError(ERR_IO_PENDING));
zhongyica364fbb2015-12-12 03:39:121262
Ryan Hamilton8d9ee76e2018-05-29 23:52:521263 quic::QuicConnectionCloseFrame frame;
Zhongyi Shica576df2019-04-12 17:43:401264 frame.quic_error_code = quic::QUIC_PEER_GOING_AWAY;
rch1c5b74a2016-06-23 22:10:551265 session_->connection()->OnConnectionCloseFrame(frame);
zhongyica364fbb2015-12-12 03:39:121266
1267 NetErrorDetails details;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521268 EXPECT_EQ(quic::QUIC_NO_ERROR, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121269 stream_->PopulateNetErrorDetails(&details);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521270 EXPECT_EQ(quic::QUIC_PEER_GOING_AWAY, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121271}
1272
Ryan Hamiltone316e482017-08-17 02:48:531273TEST_P(QuicHttpStreamTest, LogGranularQuicErrorIfHandshakeNotConfirmed) {
rch617e0652017-04-26 17:57:511274 // By default the test setup defaults handshake to be confirmed. Manually set
1275 // it to be not confirmed.
rch617e0652017-04-26 17:57:511276 crypto_client_stream_factory_.set_handshake_mode(
Ryan Hamilton9835e662018-08-02 05:36:271277 MockCryptoClientStream::ZERO_RTT);
rch617e0652017-04-26 17:57:511278
zhongyica364fbb2015-12-12 03:39:121279 SetRequest("GET", "/", DEFAULT_PRIORITY);
1280 size_t spdy_request_headers_frame_length;
Michael Warres167db3e2019-03-01 21:38:031281 client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
Nick Harper057264a82019-09-12 23:33:491282 client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
1283 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251284 if (VersionUsesHttp3(version_.transport_version))
Nick Harper057264a82019-09-12 23:33:491285 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371286 AddWrite(InnerConstructRequestHeadersPacket(
Nick Harper057264a82019-09-12 23:33:491287 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1288 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1289 &spdy_request_headers_frame_length));
zhongyica364fbb2015-12-12 03:39:121290 Initialize();
1291
1292 request_.method = "GET";
rchcd379012017-04-12 21:53:321293 request_.url = GURL("https://www.example.org/");
zhongyica364fbb2015-12-12 03:39:121294
Ali Beyada0b1a1c2022-04-08 20:08:141295 stream_->RegisterRequest(&request_);
1296 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261297 net_log_with_source_,
1298 callback_.callback()));
zhongyica364fbb2015-12-12 03:39:121299 EXPECT_EQ(OK,
1300 stream_->SendRequest(headers_, &response_, callback_.callback()));
1301
1302 // Ack the request.
Renjie90e808e2019-01-24 07:24:041303 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011304 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1305 IsError(ERR_IO_PENDING));
zhongyica364fbb2015-12-12 03:39:121306
Ryan Hamilton8d9ee76e2018-05-29 23:52:521307 quic::QuicConnectionCloseFrame frame;
Zhongyi Shica576df2019-04-12 17:43:401308 frame.quic_error_code = quic::QUIC_PEER_GOING_AWAY;
rch1c5b74a2016-06-23 22:10:551309 session_->connection()->OnConnectionCloseFrame(frame);
zhongyica364fbb2015-12-12 03:39:121310
1311 NetErrorDetails details;
zhongyica364fbb2015-12-12 03:39:121312 stream_->PopulateNetErrorDetails(&details);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521313 EXPECT_EQ(quic::QUIC_PEER_GOING_AWAY, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121314}
1315
rch11a114a2014-09-04 23:41:591316// Regression test for http://crbug.com/409871
1317TEST_P(QuicHttpStreamTest, SessionClosedBeforeReadResponseHeaders) {
1318 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451319 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231320 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251321 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231322 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371323 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231324 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1325 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1326 &spdy_request_headers_frame_length));
rch11a114a2014-09-04 23:41:591327 Initialize();
1328
1329 request_.method = "GET";
rchcd379012017-04-12 21:53:321330 request_.url = GURL("https://www.example.org/");
rch11a114a2014-09-04 23:41:591331
Ali Beyada0b1a1c2022-04-08 20:08:141332 stream_->RegisterRequest(&request_);
1333 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261334 net_log_with_source_,
1335 callback_.callback()));
rch11a114a2014-09-04 23:41:591336
rjshaded5ced072015-12-18 19:26:021337 EXPECT_EQ(OK,
1338 stream_->SendRequest(headers_, &response_, callback_.callback()));
rch11a114a2014-09-04 23:41:591339
jri78ec06a2016-03-31 18:19:401340 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521341 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rch11a114a2014-09-04 23:41:591342
1343 EXPECT_NE(OK, stream_->ReadResponseHeaders(callback_.callback()));
sclittle1edeeb22015-09-02 20:46:101344
1345 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451346 // headers and payload.
1347 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1348 stream_->GetTotalSentBytes());
sclittle1edeeb22015-09-02 20:46:101349 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rch11a114a2014-09-04 23:41:591350}
1351
[email protected]1e960032013-12-20 19:00:201352TEST_P(QuicHttpStreamTest, SendPostRequest) {
1353 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451354 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231355 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251356 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231357 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Yixin Wange7ecc472018-03-06 19:00:251358
Victor Vasiliev076657c2019-03-12 02:46:431359 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:321360 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411361 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231362 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1363 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1364 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411365 } else {
1366 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231367 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1368 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1369 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411370 }
Yixin Wange7ecc472018-03-06 19:00:251371
Renjie Tangcd594f32020-07-11 20:18:341372 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]f702d572012-12-04 15:56:201373
1374 Initialize();
1375
danakjad1777e2016-04-16 00:56:421376 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:191377 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
ricea2deef682016-09-09 08:04:071378 kUploadData, strlen(kUploadData)));
rch97827ee2017-05-24 23:49:121379 upload_data_stream_ =
Jeremy Roman0579ed62017-08-29 15:56:191380 std::make_unique<ElementsUploadDataStream>(std::move(element_readers), 0);
[email protected]f702d572012-12-04 15:56:201381 request_.method = "POST";
rchcd379012017-04-12 21:53:321382 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121383 request_.upload_data_stream = upload_data_stream_.get();
Bence Békyd8a21fc32018-06-27 18:29:581384 ASSERT_THAT(request_.upload_data_stream->Init(CompletionOnceCallback(),
tfarina42834112016-09-22 13:38:201385 NetLogWithSource()),
1386 IsOk());
[email protected]f702d572012-12-04 15:56:201387
Ali Beyada0b1a1c2022-04-08 20:08:141388 stream_->RegisterRequest(&request_);
1389 EXPECT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261390 net_log_with_source_,
1391 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021392 EXPECT_EQ(OK,
1393 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:201394
1395 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041396 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]f702d572012-12-04 15:56:201397
1398 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281399 SetResponse("200", string());
sclittlec4dc1a32015-09-24 00:15:451400 size_t spdy_response_headers_frame_length;
1401 ProcessPacket(ConstructResponseHeadersPacket(
1402 2, !kFin, &spdy_response_headers_frame_length));
[email protected]f702d572012-12-04 15:56:201403
rchfb47f712017-05-21 03:24:001404 // The headers have already arrived.
1405 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]cadac622013-06-11 16:46:361406 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:201407 EXPECT_EQ(200, response_.headers->response_code());
1408 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1409
1410 // Send the response body.
1411 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431412 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:411413 ProcessPacket(
Ryan Hamilton7505eb92019-06-08 00:22:171414 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
[email protected]f702d572012-12-04 15:56:201415 // Since the body has already arrived, this should return immediately.
1416 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
1417 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1418 callback_.callback()));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291419 EXPECT_EQ(0,
1420 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1421 callback_.callback()));
1422
1423 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1424 EXPECT_TRUE(AtEof());
1425
1426 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
1427 // headers and payload.
1428 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411429 strlen(kUploadData) + header.length()),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291430 stream_->GetTotalSentBytes());
1431 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411432 strlen(kResponseBody) + header2.length()),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291433 stream_->GetTotalReceivedBytes());
1434}
1435
1436TEST_P(QuicHttpStreamTest, SendPostRequestAndReceiveSoloFin) {
1437 SetRequest("POST", "/", DEFAULT_PRIORITY);
1438 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231439 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251440 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231441 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431442 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:321443 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411444 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231445 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1446 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1447 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411448 } else {
1449 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231450 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1451 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1452 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411453 }
1454
Renjie Tangcd594f32020-07-11 20:18:341455 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291456
1457 Initialize();
1458
1459 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:191460 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
Ryan Hamilton2ef0a9c2017-07-25 03:18:291461 kUploadData, strlen(kUploadData)));
1462 upload_data_stream_ =
Jeremy Roman0579ed62017-08-29 15:56:191463 std::make_unique<ElementsUploadDataStream>(std::move(element_readers), 0);
Ryan Hamilton2ef0a9c2017-07-25 03:18:291464 request_.method = "POST";
1465 request_.url = GURL("https://www.example.org/");
1466 request_.upload_data_stream = upload_data_stream_.get();
Bence Békyd8a21fc32018-06-27 18:29:581467 ASSERT_THAT(request_.upload_data_stream->Init(CompletionOnceCallback(),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291468 NetLogWithSource()),
1469 IsOk());
1470
Ali Beyada0b1a1c2022-04-08 20:08:141471 stream_->RegisterRequest(&request_);
1472 EXPECT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261473 net_log_with_source_,
1474 callback_.callback()));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291475 EXPECT_EQ(OK,
1476 stream_->SendRequest(headers_, &response_, callback_.callback()));
1477
1478 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041479 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291480
1481 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281482 SetResponse("200", string());
Ryan Hamilton2ef0a9c2017-07-25 03:18:291483 size_t spdy_response_headers_frame_length;
1484 ProcessPacket(ConstructResponseHeadersPacket(
1485 2, !kFin, &spdy_response_headers_frame_length));
1486
1487 // The headers have already arrived.
1488 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
1489 ASSERT_TRUE(response_.headers.get());
1490 EXPECT_EQ(200, response_.headers->response_code());
1491 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1492
1493 // Send the response body.
1494 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431495 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:411496 ProcessPacket(
Ryan Hamilton7505eb92019-06-08 00:22:171497 ConstructServerDataPacket(3, false, !kFin, header2 + kResponseBody));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291498 // Since the body has already arrived, this should return immediately.
1499 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
1500 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1501 callback_.callback()));
Ryan Hamilton7505eb92019-06-08 00:22:171502 ProcessPacket(ConstructServerDataPacket(4, false, kFin, ""));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291503 EXPECT_EQ(0,
1504 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1505 callback_.callback()));
[email protected]f702d572012-12-04 15:56:201506
1507 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1508 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101509
1510 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451511 // headers and payload.
1512 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411513 strlen(kUploadData) + header.length()),
sclittle1edeeb22015-09-02 20:46:101514 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451515 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411516 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101517 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:201518}
1519
[email protected]1e960032013-12-20 19:00:201520TEST_P(QuicHttpStreamTest, SendChunkedPostRequest) {
1521 SetRequest("POST", "/", DEFAULT_PRIORITY);
[email protected]c9e49a02013-02-26 05:56:471522 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:451523 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231524 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251525 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231526 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431527 std::string header = ConstructDataHeader(chunk_size);
Nick Harperc6cb7a612020-02-24 20:03:321528 if (version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411529 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231530 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1531 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1532 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjie Tangd5133972019-12-06 00:20:281533 AddWrite(ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin,
1534 {header + kUploadData}));
Renjief49758b2019-01-11 23:32:411535 } else {
1536 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231537 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1538 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1539 &spdy_request_headers_frame_length, {kUploadData}));
1540 AddWrite(ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin,
1541 kUploadData));
Renjief49758b2019-01-11 23:32:411542 }
1543
Renjie Tangcd594f32020-07-11 20:18:341544 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]c9e49a02013-02-26 05:56:471545 Initialize();
1546
Jeremy Roman0579ed62017-08-29 15:56:191547 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121548 auto* chunked_upload_stream =
1549 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1550 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
[email protected]c9e49a02013-02-26 05:56:471551
1552 request_.method = "POST";
rchcd379012017-04-12 21:53:321553 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121554 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071555 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201556 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]c9e49a02013-02-26 05:56:471557
Ali Beyada0b1a1c2022-04-08 20:08:141558 stream_->RegisterRequest(&request_);
1559 ASSERT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261560 net_log_with_source_,
1561 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021562 ASSERT_EQ(ERR_IO_PENDING,
1563 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]c9e49a02013-02-26 05:56:471564
rch97827ee2017-05-24 23:49:121565 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
robpercival214763f2016-07-01 23:27:011566 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]c9e49a02013-02-26 05:56:471567
1568 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041569 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]c9e49a02013-02-26 05:56:471570
1571 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281572 SetResponse("200", string());
sclittlec4dc1a32015-09-24 00:15:451573 size_t spdy_response_headers_frame_length;
1574 ProcessPacket(ConstructResponseHeadersPacket(
1575 2, !kFin, &spdy_response_headers_frame_length));
[email protected]c9e49a02013-02-26 05:56:471576
rchfb47f712017-05-21 03:24:001577 // The headers have already arrived.
1578 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]cadac622013-06-11 16:46:361579 ASSERT_TRUE(response_.headers.get());
[email protected]c9e49a02013-02-26 05:56:471580 EXPECT_EQ(200, response_.headers->response_code());
1581 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1582
1583 // Send the response body.
1584 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431585 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171586 ProcessPacket(
1587 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
[email protected]c9e49a02013-02-26 05:56:471588
1589 // Since the body has already arrived, this should return immediately.
1590 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1591 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1592 callback_.callback()));
1593
1594 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1595 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101596
1597 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451598 // headers and payload.
1599 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411600 strlen(kUploadData) * 2 + header.length() * 2),
sclittle1edeeb22015-09-02 20:46:101601 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451602 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411603 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101604 stream_->GetTotalReceivedBytes());
[email protected]c9e49a02013-02-26 05:56:471605}
1606
[email protected]16ba7742014-08-22 00:57:251607TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithFinalEmptyDataPacket) {
1608 SetRequest("POST", "/", DEFAULT_PRIORITY);
1609 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:451610 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231611 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251612 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231613 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431614 std::string header = ConstructDataHeader(chunk_size);
Renjief49758b2019-01-11 23:32:411615
Nick Harperc6cb7a612020-02-24 20:03:321616 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411617 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231618 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1619 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1620 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411621 } else {
1622 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231623 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1624 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1625 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411626 }
Renjie Tangaadb84b2019-08-31 01:00:231627 AddWrite(
1628 ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin, ""));
Renjie Tangcd594f32020-07-11 20:18:341629 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]16ba7742014-08-22 00:57:251630 Initialize();
1631
Jeremy Roman0579ed62017-08-29 15:56:191632 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121633 auto* chunked_upload_stream =
1634 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1635 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
[email protected]16ba7742014-08-22 00:57:251636
1637 request_.method = "POST";
rchcd379012017-04-12 21:53:321638 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121639 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071640 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201641 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]16ba7742014-08-22 00:57:251642
Ali Beyada0b1a1c2022-04-08 20:08:141643 stream_->RegisterRequest(&request_);
1644 ASSERT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261645 net_log_with_source_,
1646 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021647 ASSERT_EQ(ERR_IO_PENDING,
1648 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251649
rch97827ee2017-05-24 23:49:121650 chunked_upload_stream->AppendData(nullptr, 0, true);
robpercival214763f2016-07-01 23:27:011651 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]16ba7742014-08-22 00:57:251652
Renjie90e808e2019-01-24 07:24:041653 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]16ba7742014-08-22 00:57:251654
1655 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281656 SetResponse("200", string());
sclittlec4dc1a32015-09-24 00:15:451657 size_t spdy_response_headers_frame_length;
1658 ProcessPacket(ConstructResponseHeadersPacket(
1659 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251660
rchfb47f712017-05-21 03:24:001661 // The headers have already arrived.
1662 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]16ba7742014-08-22 00:57:251663 ASSERT_TRUE(response_.headers.get());
1664 EXPECT_EQ(200, response_.headers->response_code());
1665 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1666
1667 // Send the response body.
1668 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431669 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171670 ProcessPacket(
1671 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
[email protected]16ba7742014-08-22 00:57:251672
rchb27683c2015-07-29 23:53:501673 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251674 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1675 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1676 callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251677 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1678 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101679
1680 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451681 // headers and payload.
1682 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411683 strlen(kUploadData) + header.length()),
sclittle1edeeb22015-09-02 20:46:101684 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451685 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411686 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101687 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251688}
1689
1690TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithOneEmptyDataPacket) {
1691 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451692 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231693 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251694 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231695 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371696 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231697 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1698 kIncludeVersion, !kFin, DEFAULT_PRIORITY,
1699 &spdy_request_headers_frame_length));
1700 AddWrite(
1701 ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin, ""));
Renjie Tangcd594f32020-07-11 20:18:341702 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]16ba7742014-08-22 00:57:251703 Initialize();
1704
Jeremy Roman0579ed62017-08-29 15:56:191705 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121706 auto* chunked_upload_stream =
1707 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
[email protected]16ba7742014-08-22 00:57:251708
1709 request_.method = "POST";
rchcd379012017-04-12 21:53:321710 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121711 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071712 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201713 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]16ba7742014-08-22 00:57:251714
Ali Beyada0b1a1c2022-04-08 20:08:141715 stream_->RegisterRequest(&request_);
1716 ASSERT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261717 net_log_with_source_,
1718 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021719 ASSERT_EQ(ERR_IO_PENDING,
1720 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251721
rch97827ee2017-05-24 23:49:121722 chunked_upload_stream->AppendData(nullptr, 0, true);
robpercival214763f2016-07-01 23:27:011723 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]16ba7742014-08-22 00:57:251724
Renjie90e808e2019-01-24 07:24:041725 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]16ba7742014-08-22 00:57:251726
1727 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281728 SetResponse("200", string());
sclittlec4dc1a32015-09-24 00:15:451729 size_t spdy_response_headers_frame_length;
1730 ProcessPacket(ConstructResponseHeadersPacket(
1731 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251732
rchfb47f712017-05-21 03:24:001733 // The headers have already arrived.
1734 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]16ba7742014-08-22 00:57:251735 ASSERT_TRUE(response_.headers.get());
1736 EXPECT_EQ(200, response_.headers->response_code());
1737 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1738
1739 // Send the response body.
1740 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431741 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171742 ProcessPacket(
1743 ConstructServerDataPacket(3, false, kFin, header + kResponseBody));
[email protected]16ba7742014-08-22 00:57:251744
rchb27683c2015-07-29 23:53:501745 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251746 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1747 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1748 callback_.callback()));
1749
1750 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1751 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101752
1753 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451754 // headers and payload.
1755 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1756 stream_->GetTotalSentBytes());
1757 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411758 strlen(kResponseBody) + header.length()),
sclittle1edeeb22015-09-02 20:46:101759 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251760}
1761
Bence Békye3c6f122020-05-08 01:09:471762TEST_P(QuicHttpStreamTest, SendChunkedPostRequestAbortedByResetStream) {
1763 SetRequest("POST", "/", DEFAULT_PRIORITY);
1764 size_t chunk_size = strlen(kUploadData);
1765 size_t spdy_request_headers_frame_length;
1766 int packet_number = 1;
1767
1768 if (version_.UsesHttp3()) {
1769 AddWrite(ConstructInitialSettingsPacket(packet_number++));
1770 }
1771
1772 std::string header = ConstructDataHeader(chunk_size);
1773 if (version_.HasIetfQuicFrames()) {
1774 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1775 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1776 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1777 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjie Tangcd594f32020-07-11 20:18:341778 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
Fan Yang8d4177792021-07-16 17:48:531779 AddWrite(client_maker_.MakeAckAndRstPacket(
1780 packet_number++, true, stream_id_, quic::QUIC_STREAM_NO_ERROR, 4, 1,
Renjie Tangcd594f32020-07-11 20:18:341781 /* include_stop_sending_if_v99 = */ false));
Bence Békye3c6f122020-05-08 01:09:471782 } else {
1783 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1784 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1785 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1786 &spdy_request_headers_frame_length, {kUploadData}));
Renjie Tangcd594f32020-07-11 20:18:341787 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
Bence Békye3c6f122020-05-08 01:09:471788 AddWrite(client_maker_.MakeAckAndRstPacket(
1789 packet_number++,
1790 /* include_version = */ false, stream_id_,
Renjie Tangcd594f32020-07-11 20:18:341791 quic::QUIC_RST_ACKNOWLEDGEMENT, 4, 1,
Bence Békye3c6f122020-05-08 01:09:471792 /* include_stop_sending_if_v99 = */ false));
1793 }
1794
1795 Initialize();
1796
1797 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
1798 auto* chunked_upload_stream =
1799 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1800 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
1801
1802 request_.method = "POST";
1803 request_.url = GURL("https://www.example.org/");
1804 request_.upload_data_stream = upload_data_stream_.get();
1805 ASSERT_THAT(request_.upload_data_stream->Init(
1806 TestCompletionCallback().callback(), NetLogWithSource()),
1807 IsOk());
Ali Beyada0b1a1c2022-04-08 20:08:141808 stream_->RegisterRequest(&request_);
Matt Reichhoff0049a0b72021-10-20 20:44:261809 ASSERT_THAT(
Ali Beyada0b1a1c2022-04-08 20:08:141810 stream_->InitializeStream(false, DEFAULT_PRIORITY, net_log_with_source_,
1811 callback_.callback()),
Matt Reichhoff0049a0b72021-10-20 20:44:261812 IsOk());
Bence Békye3c6f122020-05-08 01:09:471813 ASSERT_THAT(stream_->SendRequest(headers_, &response_, callback_.callback()),
1814 IsError(ERR_IO_PENDING));
1815
1816 // Ack both packets in the request.
1817 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
1818
1819 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281820 SetResponse("200", string());
Bence Békye3c6f122020-05-08 01:09:471821 size_t spdy_response_headers_frame_length;
1822 ProcessPacket(ConstructResponseHeadersPacket(
1823 2, !kFin, &spdy_response_headers_frame_length));
1824
1825 // Send the response body.
1826 const char kResponseBody[] = "Hello world!";
1827 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
1828 ProcessPacket(
1829 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
1830
Bence Béky050ec6d2021-02-25 22:07:051831 if (version_.HasIetfQuicFrames()) {
1832 // In IETF QUIC, the server uses a STOP_SENDING frame to notify the client
1833 // that it does not need any further data to fully process the request.
1834 ProcessPacket(server_maker_.MakeStopSendingPacket(
1835 4, /* include_version = */ false, stream_id_,
1836 quic::QUIC_STREAM_NO_ERROR));
1837 } else {
1838 // Server resets stream with H3_NO_ERROR before request body is complete.
1839 ProcessPacket(server_maker_.MakeRstPacket(4, /* include_version = */ false,
1840 stream_id_,
1841 quic::QUIC_STREAM_NO_ERROR));
1842 }
Bence Békye3c6f122020-05-08 01:09:471843
1844 // Finish feeding request body to QuicHttpStream. Data will be discarded.
1845 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1846 EXPECT_THAT(callback_.WaitForResult(), IsOk());
1847
1848 // Verify response.
1849 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
1850 ASSERT_TRUE(response_.headers.get());
1851 EXPECT_EQ(200, response_.headers->response_code());
1852 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1853 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1854 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1855 callback_.callback()));
1856 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1857 EXPECT_TRUE(AtEof());
1858
1859 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
1860 // headers and payload.
1861 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
1862 strlen(kUploadData) + header.length()),
1863 stream_->GetTotalSentBytes());
1864 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1865 strlen(kResponseBody) + header2.length()),
1866 stream_->GetTotalReceivedBytes());
1867}
1868
[email protected]1e960032013-12-20 19:00:201869TEST_P(QuicHttpStreamTest, DestroyedEarly) {
1870 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451871 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231872 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251873 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231874 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371875 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231876 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1877 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1878 &spdy_request_headers_frame_length));
1879 AddWrite(ConstructAckAndRstStreamPacket(packet_number++));
[email protected]63534512012-12-23 18:49:001880 Initialize();
1881
1882 request_.method = "GET";
rchcd379012017-04-12 21:53:321883 request_.url = GURL("https://www.example.org/");
[email protected]63534512012-12-23 18:49:001884
Ali Beyada0b1a1c2022-04-08 20:08:141885 stream_->RegisterRequest(&request_);
1886 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261887 net_log_with_source_,
1888 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021889 EXPECT_EQ(OK,
1890 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]63534512012-12-23 18:49:001891
1892 // Ack the request.
Renjie90e808e2019-01-24 07:24:041893 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
rchfb47f712017-05-21 03:24:001894 EXPECT_THAT(stream_->ReadResponseHeaders(
Yannic Bonenberger3c96beb2019-09-03 20:41:371895 base::BindOnce(&QuicHttpStreamTest::CloseStream,
1896 base::Unretained(this), stream_.get())),
robpercival214763f2016-07-01 23:27:011897 IsError(ERR_IO_PENDING));
[email protected]63534512012-12-23 18:49:001898
1899 // Send the response with a body.
Kenichi Ishibashif8634ab2021-03-16 23:41:281900 SetResponse("404", "hello world!");
[email protected]63534512012-12-23 18:49:001901 // In the course of processing this packet, the QuicHttpStream close itself.
rchfb47f712017-05-21 03:24:001902 size_t response_size = 0;
rch1bcfddf22017-06-03 00:26:291903 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin, &response_size));
[email protected]63534512012-12-23 18:49:001904
fdoray92e35a72016-06-10 15:54:551905 base::RunLoop().RunUntilIdle();
rchb27683c2015-07-29 23:53:501906
[email protected]63534512012-12-23 18:49:001907 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101908
1909 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451910 // headers and payload.
1911 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1912 stream_->GetTotalSentBytes());
rchfb47f712017-05-21 03:24:001913 // The stream was closed after receiving the headers.
1914 EXPECT_EQ(static_cast<int64_t>(response_size),
1915 stream_->GetTotalReceivedBytes());
[email protected]63534512012-12-23 18:49:001916}
1917
[email protected]1e960032013-12-20 19:00:201918TEST_P(QuicHttpStreamTest, Priority) {
1919 SetRequest("GET", "/", MEDIUM);
sclittlec4dc1a32015-09-24 00:15:451920 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231921 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251922 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231923 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371924 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231925 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1926 kIncludeVersion, kFin, MEDIUM, &spdy_request_headers_frame_length));
[email protected]24e5bc52013-09-18 15:36:581927 Initialize();
1928
1929 request_.method = "GET";
rchcd379012017-04-12 21:53:321930 request_.url = GURL("https://www.example.org/");
[email protected]24e5bc52013-09-18 15:36:581931
Ali Beyada0b1a1c2022-04-08 20:08:141932 stream_->RegisterRequest(&request_);
1933 EXPECT_EQ(OK, stream_->InitializeStream(true, MEDIUM, net_log_with_source_,
Matt Reichhoff0049a0b72021-10-20 20:44:261934 callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581935
rjshaded5ced072015-12-18 19:26:021936 EXPECT_EQ(OK,
1937 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581938
[email protected]24e5bc52013-09-18 15:36:581939 // Ack the request.
Renjie90e808e2019-01-24 07:24:041940 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011941 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1942 IsError(ERR_IO_PENDING));
[email protected]24e5bc52013-09-18 15:36:581943
1944 // Send the response with a body.
Kenichi Ishibashif8634ab2021-03-16 23:41:281945 SetResponse("404", "hello world!");
rchfb47f712017-05-21 03:24:001946 size_t response_size = 0;
1947 ProcessPacket(ConstructResponseHeadersPacket(2, kFin, &response_size));
[email protected]24e5bc52013-09-18 15:36:581948
rchfb47f712017-05-21 03:24:001949 EXPECT_EQ(OK, callback_.WaitForResult());
rchb27683c2015-07-29 23:53:501950
[email protected]24e5bc52013-09-18 15:36:581951 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101952
1953 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451954 // headers and payload.
1955 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1956 stream_->GetTotalSentBytes());
rchfb47f712017-05-21 03:24:001957 EXPECT_EQ(static_cast<int64_t>(response_size),
1958 stream_->GetTotalReceivedBytes());
[email protected]24e5bc52013-09-18 15:36:581959}
1960
xunjieli8dff50b2016-07-22 14:19:061961TEST_P(QuicHttpStreamTest, SessionClosedDuringDoLoop) {
1962 SetRequest("POST", "/", DEFAULT_PRIORITY);
1963 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231964 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251965 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231966 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431967 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:321968 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411969 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231970 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1971 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1972 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411973 } else {
1974 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231975 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1976 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1977 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411978 }
1979
xunjieli8dff50b2016-07-22 14:19:061980 // Second data write will result in a synchronous failure which will close
1981 // the session.
1982 AddWrite(SYNCHRONOUS, ERR_FAILED);
1983 Initialize();
1984
Jeremy Roman0579ed62017-08-29 15:56:191985 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121986 auto* chunked_upload_stream =
1987 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
xunjieli8dff50b2016-07-22 14:19:061988
1989 request_.method = "POST";
rchcd379012017-04-12 21:53:321990 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121991 request_.upload_data_stream = upload_data_stream_.get();
xunjieli8dff50b2016-07-22 14:19:061992 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201993 TestCompletionCallback().callback(), NetLogWithSource()));
xunjieli8dff50b2016-07-22 14:19:061994
1995 size_t chunk_size = strlen(kUploadData);
rch97827ee2017-05-24 23:49:121996 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
Ali Beyada0b1a1c2022-04-08 20:08:141997 stream_->RegisterRequest(&request_);
1998 ASSERT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261999 net_log_with_source_,
2000 callback_.callback()));
xunjieli8dff50b2016-07-22 14:19:062001 QuicHttpStream* stream = stream_.get();
2002 DeleteStreamCallback delete_stream_callback(std::move(stream_));
2003 // SendRequest() completes asynchronously after the final chunk is added.
Yixin Wange7ecc472018-03-06 19:00:252004 // Error does not surface yet since packet write is triggered by a packet
2005 // flusher that tries to bundle request body writes.
xunjieli8dff50b2016-07-22 14:19:062006 ASSERT_EQ(ERR_IO_PENDING,
2007 stream->SendRequest(headers_, &response_, callback_.callback()));
rch97827ee2017-05-24 23:49:122008 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
xunjieli8dff50b2016-07-22 14:19:062009 int rv = callback_.WaitForResult();
Yixin Wange7ecc472018-03-06 19:00:252010 EXPECT_EQ(OK, rv);
2011 // Error will be surfaced once an attempt to read the response occurs.
2012 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
2013 stream->ReadResponseHeaders(callback_.callback()));
xunjieli8dff50b2016-07-22 14:19:062014}
2015
rtenneti15656ae2016-01-23 03:05:032016TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersComplete) {
2017 SetRequest("POST", "/", DEFAULT_PRIORITY);
Victor Vasiliev7da08172019-10-14 06:04:252018 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232019 AddWrite(ConstructInitialSettingsPacket());
rtenneti15656ae2016-01-23 03:05:032020 AddWrite(SYNCHRONOUS, ERR_FAILED);
2021 Initialize();
2022
Jeremy Roman0579ed62017-08-29 15:56:192023 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
Yixin Wange7ecc472018-03-06 19:00:252024 auto* chunked_upload_stream =
2025 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
rtenneti15656ae2016-01-23 03:05:032026
2027 request_.method = "POST";
rchcd379012017-04-12 21:53:322028 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122029 request_.upload_data_stream = upload_data_stream_.get();
rtenneti15656ae2016-01-23 03:05:032030 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202031 TestCompletionCallback().callback(), NetLogWithSource()));
rtenneti15656ae2016-01-23 03:05:032032
Ali Beyada0b1a1c2022-04-08 20:08:142033 stream_->RegisterRequest(&request_);
2034 ASSERT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262035 net_log_with_source_,
2036 callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252037 ASSERT_EQ(ERR_IO_PENDING,
rtenneti15656ae2016-01-23 03:05:032038 stream_->SendRequest(headers_, &response_, callback_.callback()));
mmenkeffff3642017-06-15 17:37:242039
Yixin Wange7ecc472018-03-06 19:00:252040 // Error will be surfaced once |upload_data_stream| triggers the next write.
2041 size_t chunk_size = strlen(kUploadData);
2042 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2043 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR, callback_.WaitForResult());
2044
2045 EXPECT_LE(0, stream_->GetTotalSentBytes());
2046 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2047}
2048
2049TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersCompleteReadResponse) {
2050 SetRequest("POST", "/", DEFAULT_PRIORITY);
Victor Vasiliev7da08172019-10-14 06:04:252051 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232052 AddWrite(ConstructInitialSettingsPacket());
Yixin Wange7ecc472018-03-06 19:00:252053 AddWrite(SYNCHRONOUS, ERR_FAILED);
2054 Initialize();
2055
2056 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
2057 auto* chunked_upload_stream =
2058 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
2059
2060 request_.method = "POST";
2061 request_.url = GURL("https://www.example.org/");
2062 request_.upload_data_stream = upload_data_stream_.get();
2063
2064 size_t chunk_size = strlen(kUploadData);
2065 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2066
2067 ASSERT_EQ(OK, request_.upload_data_stream->Init(
2068 TestCompletionCallback().callback(), NetLogWithSource()));
2069
Ali Beyada0b1a1c2022-04-08 20:08:142070 stream_->RegisterRequest(&request_);
2071 ASSERT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262072 net_log_with_source_,
2073 callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252074 ASSERT_EQ(OK,
2075 stream_->SendRequest(headers_, &response_, callback_.callback()));
2076
2077 // Error will be surfaced once an attempt to read the response occurs.
2078 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
2079 stream_->ReadResponseHeaders(callback_.callback()));
2080
mmenkeffff3642017-06-15 17:37:242081 EXPECT_LE(0, stream_->GetTotalSentBytes());
2082 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rtenneti15656ae2016-01-23 03:05:032083}
2084
2085TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBodyComplete) {
2086 SetRequest("POST", "/", DEFAULT_PRIORITY);
2087 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232088 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252089 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232090 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:372091 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:232092 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2093 kIncludeVersion, !kFin, DEFAULT_PRIORITY,
2094 &spdy_request_headers_frame_length));
rtenneti15656ae2016-01-23 03:05:032095 AddWrite(SYNCHRONOUS, ERR_FAILED);
2096 Initialize();
2097
Jeremy Roman0579ed62017-08-29 15:56:192098 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:122099 auto* chunked_upload_stream =
2100 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
rtenneti15656ae2016-01-23 03:05:032101
2102 request_.method = "POST";
rchcd379012017-04-12 21:53:322103 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122104 request_.upload_data_stream = upload_data_stream_.get();
rtenneti15656ae2016-01-23 03:05:032105 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202106 TestCompletionCallback().callback(), NetLogWithSource()));
rtenneti15656ae2016-01-23 03:05:032107
Ali Beyada0b1a1c2022-04-08 20:08:142108 stream_->RegisterRequest(&request_);
2109 ASSERT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262110 net_log_with_source_,
2111 callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252112 ASSERT_EQ(ERR_IO_PENDING,
rtenneti15656ae2016-01-23 03:05:032113 stream_->SendRequest(headers_, &response_, callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252114
2115 size_t chunk_size = strlen(kUploadData);
2116 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2117 // Error does not surface yet since packet write is triggered by a packet
2118 // flusher that tries to bundle request body writes.
2119 ASSERT_EQ(OK, callback_.WaitForResult());
2120 // Error will be surfaced once an attempt to read the response occurs.
2121 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
2122 stream_->ReadResponseHeaders(callback_.callback()));
2123
2124 EXPECT_LE(0, stream_->GetTotalSentBytes());
2125 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2126}
2127
2128TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBundledBodyComplete) {
2129 SetRequest("POST", "/", DEFAULT_PRIORITY);
2130 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232131 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252132 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232133 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:432134 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:322135 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:412136 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:232137 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2138 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
2139 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:412140 } else {
2141 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:232142 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2143 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
2144 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:412145 }
2146
Yixin Wange7ecc472018-03-06 19:00:252147 AddWrite(SYNCHRONOUS, ERR_FAILED);
2148 Initialize();
2149
2150 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
2151 auto* chunked_upload_stream =
2152 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
2153
2154 request_.method = "POST";
2155 request_.url = GURL("https://www.example.org/");
2156 request_.upload_data_stream = upload_data_stream_.get();
2157
2158 size_t chunk_size = strlen(kUploadData);
2159 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
2160
2161 ASSERT_EQ(OK, request_.upload_data_stream->Init(
2162 TestCompletionCallback().callback(), NetLogWithSource()));
2163
Ali Beyada0b1a1c2022-04-08 20:08:142164 stream_->RegisterRequest(&request_);
2165 ASSERT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262166 net_log_with_source_,
2167 callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252168 ASSERT_EQ(ERR_IO_PENDING,
2169 stream_->SendRequest(headers_, &response_, callback_.callback()));
2170
2171 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2172
2173 // Error does not surface yet since packet write is triggered by a packet
2174 // flusher that tries to bundle request body writes.
2175 ASSERT_EQ(OK, callback_.WaitForResult());
2176 // Error will be surfaced once an attempt to read the response occurs.
2177 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
2178 stream_->ReadResponseHeaders(callback_.callback()));
2179
2180 EXPECT_LE(0, stream_->GetTotalSentBytes());
2181 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rtenneti15656ae2016-01-23 03:05:032182}
2183
ckrasic3865ee0f2016-02-29 22:04:562184TEST_P(QuicHttpStreamTest, ServerPushGetRequest) {
2185 SetRequest("GET", "/", DEFAULT_PRIORITY);
2186 Initialize();
2187
Bin Wue8408792021-08-24 23:25:162188 // Server push is not supported in HTTP/3.
2189 if (version_.UsesHttp3())
2190 return;
2191
ckrasic3865ee0f2016-02-29 22:04:562192 // Initialize the first stream, for receiving the promise on.
2193 request_.method = "GET";
rchcd379012017-04-12 21:53:322194 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562195
Ali Beyada0b1a1c2022-04-08 20:08:142196 stream_->RegisterRequest(&request_);
2197 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262198 net_log_with_source_,
2199 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232200 ASSERT_EQ(OK,
2201 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562202
2203 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2204 // packet, but does it matter?
2205 ReceivePromise(promise_id_);
2206 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2207
2208 request_.url = GURL(promise_url_);
2209
2210 // Make the second stream that will exercise the first step of the
2211 // server push rendezvous mechanism.
Ali Beyada0b1a1c2022-04-08 20:08:142212 promised_stream_->RegisterRequest(&request_);
2213 EXPECT_EQ(OK, promised_stream_->InitializeStream(true, DEFAULT_PRIORITY,
2214 net_log_with_source_,
2215 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562216
2217 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252218 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562219 size_t spdy_response_headers_frame_length;
2220 ProcessPacket(InnerConstructResponseHeadersPacket(
2221 1, promise_id_, false, &spdy_response_headers_frame_length));
2222
2223 // Receive the promised response body.
2224 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432225 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172226 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2227 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562228
2229 // Now sending a matching request will have successful rendezvous
2230 // with the promised stream.
Ryan Hamiltona1d1f4a2019-06-26 14:43:042231 ASSERT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
ckrasic3865ee0f2016-02-29 22:04:562232 callback_.callback()));
2233
2234 EXPECT_EQ(
2235 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2236 ->id(),
2237 promise_id_);
2238
2239 // The headers will be immediately available.
robpercival214763f2016-07-01 23:27:012240 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2241 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562242
2243 // As will be the body.
2244 EXPECT_EQ(
2245 static_cast<int>(strlen(kResponseBody)),
2246 promised_stream_->ReadResponseBody(
2247 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2248 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2249 EXPECT_TRUE(AtEof());
2250
ckrasic3865ee0f2016-02-29 22:04:562251 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2252 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412253 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562254 promised_stream_->GetTotalReceivedBytes());
2255}
2256
2257TEST_P(QuicHttpStreamTest, ServerPushGetRequestSlowResponse) {
2258 SetRequest("GET", "/", DEFAULT_PRIORITY);
2259 Initialize();
2260
Bin Wue8408792021-08-24 23:25:162261 // Server push is not supported in HTTP/3.
2262 if (version_.UsesHttp3())
2263 return;
2264
ckrasic3865ee0f2016-02-29 22:04:562265 // Initialize the first stream, for receiving the promise on.
2266 request_.method = "GET";
rchcd379012017-04-12 21:53:322267 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562268
Ali Beyada0b1a1c2022-04-08 20:08:142269 stream_->RegisterRequest(&request_);
2270 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262271 net_log_with_source_,
2272 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232273 ASSERT_EQ(OK,
2274 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562275
2276 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2277 // packet, but does it matter?
2278 ReceivePromise(promise_id_);
2279 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2280
2281 request_.url = GURL(promise_url_);
2282
2283 // Make the second stream that will exercise the first step of the
2284 // server push rendezvous mechanism.
Ali Beyada0b1a1c2022-04-08 20:08:142285 promised_stream_->RegisterRequest(&request_);
2286 EXPECT_EQ(OK, promised_stream_->InitializeStream(true, DEFAULT_PRIORITY,
2287 net_log_with_source_,
2288 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562289
2290 // Now sending a matching request will rendezvous with the promised
2291 // stream, but pending secondary validation.
2292 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2293 headers_, &response_, callback_.callback()));
2294
2295 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252296 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562297 size_t spdy_response_headers_frame_length;
2298 ProcessPacket(InnerConstructResponseHeadersPacket(
2299 1, promise_id_, false, &spdy_response_headers_frame_length));
2300
2301 // Receive the promised response body.
2302 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432303 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172304 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2305 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562306
fdoray92e35a72016-06-10 15:54:552307 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562308
2309 // Rendezvous should have succeeded now, so the promised stream
2310 // should point at our push stream, and we should be able read
2311 // headers and data from it.
robpercival214763f2016-07-01 23:27:012312 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562313
2314 EXPECT_EQ(
2315 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2316 ->id(),
2317 promise_id_);
2318
robpercival214763f2016-07-01 23:27:012319 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2320 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562321
2322 EXPECT_EQ(
2323 static_cast<int>(strlen(kResponseBody)),
2324 promised_stream_->ReadResponseBody(
2325 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2326
2327 // Callback should return
2328 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2329 EXPECT_TRUE(AtEof());
2330
ckrasic3865ee0f2016-02-29 22:04:562331 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2332 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412333 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562334 promised_stream_->GetTotalReceivedBytes());
2335}
2336
ckrasic2c63f9b2016-08-16 23:54:072337// Verify fix for crbug.com/637349
2338TEST_P(QuicHttpStreamTest, ServerPushCancelHttpStreamBeforeResponse) {
2339 SetRequest("GET", "/", DEFAULT_PRIORITY);
2340 Initialize();
2341
Bin Wue8408792021-08-24 23:25:162342 // Server push is not supported in HTTP/3.
2343 if (version_.UsesHttp3())
2344 return;
2345
ckrasic2c63f9b2016-08-16 23:54:072346 // Initialize the first stream, for receiving the promise on.
2347 request_.method = "GET";
rchcd379012017-04-12 21:53:322348 request_.url = GURL("https://www.example.org/");
ckrasic2c63f9b2016-08-16 23:54:072349
Ali Beyada0b1a1c2022-04-08 20:08:142350 stream_->RegisterRequest(&request_);
2351 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262352 net_log_with_source_,
2353 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232354 ASSERT_EQ(OK,
2355 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic2c63f9b2016-08-16 23:54:072356
2357 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2358 // packet, but does it matter?
2359 ReceivePromise(promise_id_);
2360 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2361
2362 request_.url = GURL(promise_url_);
2363
2364 // Make the second stream that will exercise the first step of the
2365 // server push rendezvous mechanism.
Ali Beyada0b1a1c2022-04-08 20:08:142366 promised_stream_->RegisterRequest(&request_);
2367 EXPECT_EQ(OK, promised_stream_->InitializeStream(true, DEFAULT_PRIORITY,
2368 net_log_with_source_,
2369 callback_.callback()));
ckrasic2c63f9b2016-08-16 23:54:072370
2371 // Now sending a matching request will rendezvous with the promised
2372 // stream, but pending secondary validation.
2373 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2374 headers_, &response_, callback_.callback()));
2375
2376 base::RunLoop().RunUntilIdle();
2377
2378 // Cause of FinalValidation() crash as per bug.
2379 promised_stream_.reset();
2380
2381 // Receive the promised response headers.
2382 response_headers_ = promised_response_.Clone();
2383 size_t spdy_response_headers_frame_length;
2384 ProcessPacket(InnerConstructResponseHeadersPacket(
2385 1, promise_id_, false, &spdy_response_headers_frame_length));
2386}
2387
ckrasic3865ee0f2016-02-29 22:04:562388TEST_P(QuicHttpStreamTest, ServerPushCrossOriginOK) {
2389 SetRequest("GET", "/", DEFAULT_PRIORITY);
2390 Initialize();
2391
Bin Wue8408792021-08-24 23:25:162392 // Server push is not supported in HTTP/3.
2393 if (version_.UsesHttp3())
2394 return;
2395
ckrasic3865ee0f2016-02-29 22:04:562396 // Initialize the first stream, for receiving the promise on.
2397 request_.method = "GET";
rchcd379012017-04-12 21:53:322398 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562399
Ali Beyada0b1a1c2022-04-08 20:08:142400 stream_->RegisterRequest(&request_);
2401 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262402 net_log_with_source_,
2403 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232404 ASSERT_EQ(OK,
2405 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562406
2407 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2408 // packet, but does it matter?
2409
2410 push_promise_[":authority"] = "mail.example.org";
David Schinazi3f7465c2019-07-12 01:57:052411 promise_url_ =
2412 quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
ckrasic3865ee0f2016-02-29 22:04:562413
2414 ReceivePromise(promise_id_);
2415 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2416
2417 request_.url = GURL(promise_url_);
2418
2419 // Make the second stream that will exercise the first step of the
2420 // server push rendezvous mechanism.
Ali Beyada0b1a1c2022-04-08 20:08:142421 promised_stream_->RegisterRequest(&request_);
2422 EXPECT_EQ(OK, promised_stream_->InitializeStream(true, DEFAULT_PRIORITY,
2423 net_log_with_source_,
2424 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562425
2426 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252427 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562428 size_t spdy_response_headers_frame_length;
2429 ProcessPacket(InnerConstructResponseHeadersPacket(
2430 1, promise_id_, false, &spdy_response_headers_frame_length));
2431
2432 // Receive the promised response body.
2433 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432434 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172435 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2436 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562437
2438 // Now sending a matching request will have successful rendezvous
2439 // with the promised stream.
2440 EXPECT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
2441 callback_.callback()));
2442
2443 EXPECT_EQ(
2444 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2445 ->id(),
2446 promise_id_);
2447
2448 // The headers will be immediately available.
robpercival214763f2016-07-01 23:27:012449 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2450 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562451
2452 // As will be the body.
2453 EXPECT_EQ(
2454 static_cast<int>(strlen(kResponseBody)),
2455 promised_stream_->ReadResponseBody(
2456 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2457 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2458 EXPECT_TRUE(AtEof());
2459
ckrasic3865ee0f2016-02-29 22:04:562460 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2461 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412462 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562463 promised_stream_->GetTotalReceivedBytes());
2464}
2465
2466TEST_P(QuicHttpStreamTest, ServerPushCrossOriginFail) {
2467 SetRequest("GET", "/", DEFAULT_PRIORITY);
2468 Initialize();
2469
Bin Wue8408792021-08-24 23:25:162470 // Server push is not supported in HTTP/3.
2471 if (version_.UsesHttp3())
2472 return;
2473
ckrasic3865ee0f2016-02-29 22:04:562474 // Initialize the first stream, for receiving the promise on.
2475 request_.method = "GET";
rchcd379012017-04-12 21:53:322476 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562477
Ali Beyada0b1a1c2022-04-08 20:08:142478 stream_->RegisterRequest(&request_);
2479 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262480 net_log_with_source_,
2481 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232482 ASSERT_EQ(OK,
2483 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562484
2485 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2486 // packet, but does it matter?
2487 push_promise_[":authority"] = "www.notexample.org";
David Schinazi3f7465c2019-07-12 01:57:052488 promise_url_ =
2489 quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
ckrasic3865ee0f2016-02-29 22:04:562490
2491 ReceivePromise(promise_id_);
2492 // The promise will have been rejected because the cert doesn't
2493 // match.
2494 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
2495}
2496
2497TEST_P(QuicHttpStreamTest, ServerPushVaryCheckOK) {
2498 SetRequest("GET", "/", DEFAULT_PRIORITY);
2499 Initialize();
2500
Bin Wue8408792021-08-24 23:25:162501 // Server push is not supported in HTTP/3.
2502 if (version_.UsesHttp3())
2503 return;
2504
ckrasic3865ee0f2016-02-29 22:04:562505 // Initialize the first stream, for receiving the promise on.
2506 request_.method = "GET";
rchcd379012017-04-12 21:53:322507 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562508
Ali Beyada0b1a1c2022-04-08 20:08:142509 stream_->RegisterRequest(&request_);
2510 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262511 net_log_with_source_,
2512 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232513 ASSERT_EQ(OK,
2514 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562515
2516 push_promise_["accept-encoding"] = "gzip";
ckrasic3865ee0f2016-02-29 22:04:562517
2518 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2519 // packet, but does it matter?
2520 ReceivePromise(promise_id_);
2521 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2522
2523 request_.url = GURL(promise_url_);
2524
2525 // Make the second stream that will exercise the first step of the
2526 // server push rendezvous mechanism.
Ali Beyada0b1a1c2022-04-08 20:08:142527 promised_stream_->RegisterRequest(&request_);
2528 EXPECT_EQ(OK, promised_stream_->InitializeStream(true, DEFAULT_PRIORITY,
2529 net_log_with_source_,
2530 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562531
2532 headers_.SetHeader("accept-encoding", "gzip");
2533
2534 // Now sending a matching request will rendezvous with the promised
2535 // stream, but pending secondary validation.
2536 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2537 headers_, &response_, callback_.callback()));
2538
2539 // Receive the promised response headers.
2540 promised_response_["vary"] = "accept-encoding";
bnc94893a72016-06-30 13:45:252541 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562542 size_t spdy_response_headers_frame_length;
2543 ProcessPacket(InnerConstructResponseHeadersPacket(
2544 1, promise_id_, false, &spdy_response_headers_frame_length));
2545
2546 // Receive the promised response body.
2547 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432548 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172549 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2550 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562551
fdoray92e35a72016-06-10 15:54:552552 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562553
2554 // Rendezvous should have succeeded now, so the promised stream
2555 // should point at our push stream, and we should be able read
2556 // headers and data from it.
robpercival214763f2016-07-01 23:27:012557 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562558
2559 EXPECT_EQ(
2560 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2561 ->id(),
2562 promise_id_);
2563
robpercival214763f2016-07-01 23:27:012564 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2565 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562566
2567 EXPECT_EQ(
2568 static_cast<int>(strlen(kResponseBody)),
2569 promised_stream_->ReadResponseBody(
2570 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2571
2572 // Callback should return
2573 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2574 EXPECT_TRUE(AtEof());
2575
ckrasic3865ee0f2016-02-29 22:04:562576 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2577 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412578 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562579 promised_stream_->GetTotalReceivedBytes());
2580}
2581
2582TEST_P(QuicHttpStreamTest, ServerPushVaryCheckFail) {
2583 SetRequest("GET", "/", DEFAULT_PRIORITY);
2584 request_headers_[":scheme"] = "https";
2585 request_headers_[":path"] = "/bar";
2586 request_headers_["accept-encoding"] = "sdch";
2587
ckrasic3865ee0f2016-02-29 22:04:562588 Initialize();
2589
Bin Wue8408792021-08-24 23:25:162590 // Server push is not supported in HTTP/3.
2591 if (version_.UsesHttp3())
2592 return;
2593
ckrasic3865ee0f2016-02-29 22:04:562594 // Initialize the first stream, for receiving the promise on.
2595 request_.method = "GET";
rchcd379012017-04-12 21:53:322596 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562597
Ali Beyada0b1a1c2022-04-08 20:08:142598 stream_->RegisterRequest(&request_);
2599 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262600 net_log_with_source_,
2601 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232602 ASSERT_EQ(OK,
2603 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562604
2605 push_promise_["accept-encoding"] = "gzip";
ckrasic3865ee0f2016-02-29 22:04:562606
2607 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2608 // packet, but does it matter?
2609 ReceivePromise(promise_id_);
2610 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2611
2612 request_.url = GURL(promise_url_);
2613
2614 // Make the second stream that will exercise the first step of the
2615 // server push rendezvous mechanism.
Ali Beyada0b1a1c2022-04-08 20:08:142616 promised_stream_->RegisterRequest(&request_);
2617 EXPECT_EQ(OK, promised_stream_->InitializeStream(true, DEFAULT_PRIORITY,
2618 net_log_with_source_,
2619 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562620
2621 headers_.SetHeader("accept-encoding", "sdch");
2622
2623 // Now sending a matching request will rendezvous with the promised
2624 // stream, but pending secondary validation.
2625 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2626 headers_, &response_, callback_.callback()));
2627
2628 // Receive the promised response headers.
2629 promised_response_["vary"] = "accept-encoding";
bnc94893a72016-06-30 13:45:252630 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562631 size_t spdy_response_headers_frame_length;
2632 ProcessPacket(InnerConstructResponseHeadersPacket(
2633 1, promise_id_, false, &spdy_response_headers_frame_length));
2634
fdoray92e35a72016-06-10 15:54:552635 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562636
2637 // Rendezvous should have failed due to vary mismatch, so the
2638 // promised stream should have been aborted, and instead we have a
2639 // new, regular client initiated stream.
robpercival214763f2016-07-01 23:27:012640 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562641
2642 // Not a server-initiated stream.
2643 EXPECT_NE(
2644 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2645 ->id(),
2646 promise_id_);
2647
2648 // Instead, a new client-initiated stream.
2649 EXPECT_EQ(
2650 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2651 ->id(),
Nick Harper23290b82019-05-02 00:02:562652 stream_id_ + quic::QuicUtils::StreamIdDelta(version_.transport_version));
ckrasic3865ee0f2016-02-29 22:04:562653
2654 // After rendezvous failure, the push stream has been cancelled.
2655 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
2656
2657 // The rest of the test verifies that the retried as
2658 // client-initiated version of |promised_stream_| works as intended.
2659
2660 // Ack the request.
Renjie90e808e2019-01-24 07:24:042661 ProcessPacket(ConstructServerAckPacket(2, 1, 1, 1));
ckrasic3865ee0f2016-02-29 22:04:562662
Kenichi Ishibashif8634ab2021-03-16 23:41:282663 SetResponse("404", string());
ckrasic3865ee0f2016-02-29 22:04:562664 size_t spdy_response_header_frame_length;
2665 ProcessPacket(InnerConstructResponseHeadersPacket(
Nick Harper23290b82019-05-02 00:02:562666 3,
2667 stream_id_ + quic::QuicUtils::StreamIdDelta(version_.transport_version),
2668 kFin, &spdy_response_header_frame_length));
ckrasic3865ee0f2016-02-29 22:04:562669
fdoray92e35a72016-06-10 15:54:552670 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562671
robpercival214763f2016-07-01 23:27:012672 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2673 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562674 ASSERT_TRUE(response_.headers.get());
2675 EXPECT_EQ(404, response_.headers->response_code());
2676 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
2677 EXPECT_FALSE(response_.response_time.is_null());
2678 EXPECT_FALSE(response_.request_time.is_null());
2679
2680 // There is no body, so this should return immediately.
2681 EXPECT_EQ(
2682 0, promised_stream_->ReadResponseBody(
2683 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2684 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2685
2686 stream_->Close(true);
2687
2688 EXPECT_TRUE(AtEof());
ckrasic3865ee0f2016-02-29 22:04:562689}
2690
maksim.sisov84e20c92016-06-23 08:49:342691TEST_P(QuicHttpStreamTest, DataReadErrorSynchronous) {
2692 SetRequest("POST", "/", DEFAULT_PRIORITY);
2693 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232694 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252695 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232696 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Yixin Wange7ecc472018-03-06 19:00:252697 AddWrite(ConstructRequestAndRstPacket(
Renjie Tangaadb84b2019-08-31 01:00:232698 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2699 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
2700 &spdy_request_headers_frame_length, quic::QUIC_ERROR_PROCESSING_STREAM));
maksim.sisov84e20c92016-06-23 08:49:342701
2702 Initialize();
2703
Jeremy Roman0579ed62017-08-29 15:56:192704 upload_data_stream_ = std::make_unique<ReadErrorUploadDataStream>(
maksim.sisov84e20c92016-06-23 08:49:342705 ReadErrorUploadDataStream::FailureMode::SYNC);
2706 request_.method = "POST";
rchcd379012017-04-12 21:53:322707 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122708 request_.upload_data_stream = upload_data_stream_.get();
maksim.sisov84e20c92016-06-23 08:49:342709 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202710 TestCompletionCallback().callback(), NetLogWithSource()));
maksim.sisov84e20c92016-06-23 08:49:342711
Ali Beyada0b1a1c2022-04-08 20:08:142712 stream_->RegisterRequest(&request_);
2713 EXPECT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262714 net_log_with_source_,
2715 callback_.callback()));
maksim.sisov84e20c92016-06-23 08:49:342716
2717 int result = stream_->SendRequest(headers_, &response_, callback_.callback());
robpercival214763f2016-07-01 23:27:012718 EXPECT_THAT(result, IsError(ERR_FAILED));
maksim.sisov84e20c92016-06-23 08:49:342719
2720 EXPECT_TRUE(AtEof());
2721
2722 // QuicHttpStream::GetTotalSent/ReceivedBytes includes only headers.
2723 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
2724 stream_->GetTotalSentBytes());
2725 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2726}
2727
2728TEST_P(QuicHttpStreamTest, DataReadErrorAsynchronous) {
2729 SetRequest("POST", "/", DEFAULT_PRIORITY);
2730 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232731 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252732 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232733 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:372734 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:232735 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2736 kIncludeVersion, !kFin, DEFAULT_PRIORITY,
2737 &spdy_request_headers_frame_length));
2738 AddWrite(
2739 ConstructClientRstStreamErrorPacket(packet_number++, !kIncludeVersion));
maksim.sisov84e20c92016-06-23 08:49:342740
2741 Initialize();
2742
Jeremy Roman0579ed62017-08-29 15:56:192743 upload_data_stream_ = std::make_unique<ReadErrorUploadDataStream>(
maksim.sisov84e20c92016-06-23 08:49:342744 ReadErrorUploadDataStream::FailureMode::ASYNC);
2745 request_.method = "POST";
rchcd379012017-04-12 21:53:322746 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122747 request_.upload_data_stream = upload_data_stream_.get();
maksim.sisov84e20c92016-06-23 08:49:342748 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202749 TestCompletionCallback().callback(), NetLogWithSource()));
maksim.sisov84e20c92016-06-23 08:49:342750
Ali Beyada0b1a1c2022-04-08 20:08:142751 stream_->RegisterRequest(&request_);
2752 EXPECT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262753 net_log_with_source_,
2754 callback_.callback()));
maksim.sisov84e20c92016-06-23 08:49:342755
2756 int result = stream_->SendRequest(headers_, &response_, callback_.callback());
2757
Renjie90e808e2019-01-24 07:24:042758 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
Kenichi Ishibashif8634ab2021-03-16 23:41:282759 SetResponse("200", string());
maksim.sisov84e20c92016-06-23 08:49:342760
robpercival214763f2016-07-01 23:27:012761 EXPECT_THAT(result, IsError(ERR_IO_PENDING));
2762 EXPECT_THAT(callback_.GetResult(result), IsError(ERR_FAILED));
maksim.sisov84e20c92016-06-23 08:49:342763
2764 EXPECT_TRUE(AtEof());
2765
2766 // QuicHttpStream::GetTotalSent/ReceivedBytes includes only headers.
2767 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
2768 stream_->GetTotalSentBytes());
2769 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2770}
2771
Bence Béky97ec688c2021-03-16 13:48:502772TEST_P(QuicHttpStreamTest, GetAcceptChViaAlps) {
2773 AddWrite(ConstructInitialSettingsPacket());
2774 Initialize();
2775
2776 if (!VersionUsesHttp3(version_.transport_version)) {
2777 // ALPS is only implemented for HTTP/3.
2778 return;
2779 }
2780
2781 base::HistogramTester histogram_tester;
2782
2783 session_->OnAcceptChFrameReceivedViaAlps(
Bence Béky41a34f02021-05-07 00:27:482784 {{{"https://www.example.org", "Sec-CH-UA-Platform"}}});
Bence Béky97ec688c2021-03-16 13:48:502785
2786 request_.method = "GET";
2787 request_.url = GURL("https://www.example.org/foo");
2788
Ali Beyada0b1a1c2022-04-08 20:08:142789 stream_->RegisterRequest(&request_);
2790 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262791 net_log_with_source_,
2792 callback_.callback()));
Bence Béky41a34f02021-05-07 00:27:482793 EXPECT_EQ("Sec-CH-UA-Platform", stream_->GetAcceptChViaAlps());
Bence Béky97ec688c2021-03-16 13:48:502794 EXPECT_TRUE(AtEof());
2795
2796 histogram_tester.ExpectBucketCount(
2797 "Net.QuicSession.AcceptChFrameReceivedViaAlps", 1, 1);
2798 histogram_tester.ExpectTotalCount(
2799 "Net.QuicSession.AcceptChFrameReceivedViaAlps", 1);
2800 histogram_tester.ExpectBucketCount("Net.QuicSession.AcceptChForOrigin", 1, 1);
2801 histogram_tester.ExpectTotalCount("Net.QuicSession.AcceptChForOrigin", 1);
2802}
2803
[email protected]f702d572012-12-04 15:56:202804} // namespace test
[email protected]f702d572012-12-04 15:56:202805} // namespace net