blob: 402271e9e7ce663bc01db030dab5ffce985ef22c [file] [log] [blame]
[email protected]f702d572012-12-04 15:56:201// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Ryan Hamiltona3ee93a72018-08-01 22:03:085#include "net/quic/quic_http_stream.h"
[email protected]f702d572012-12-04 15:56:206
sclittle1edeeb22015-09-02 20:46:107#include <stdint.h>
8
danakjad1777e2016-04-16 00:56:429#include <memory>
bnc086b39e12016-06-24 13:05:2610#include <utility>
[email protected]f702d572012-12-04 15:56:2011
Sebastien Marchand6d0558fd2019-01-25 16:49:3712#include "base/bind.h"
danakjad1777e2016-04-16 00:56:4213#include "base/memory/ptr_util.h"
Keishi Hattori0e45c022021-11-27 09:25:5214#include "base/memory/raw_ptr.h"
fdoray92e35a72016-06-10 15:54:5515#include "base/run_loop.h"
Bence Békye0d3747d2020-08-28 23:16:4016#include "base/strings/strcat.h"
xunjieli188bd402016-03-12 00:17:2517#include "base/strings/string_number_conversions.h"
Bence Béky97ec688c2021-03-16 13:48:5018#include "base/test/metrics/histogram_tester.h"
gabf767595f2016-05-11 18:50:3519#include "base/threading/thread_task_runner_handle.h"
Zhongyi Shic16b4102019-02-12 00:37:4020#include "base/time/default_tick_clock.h"
xunjieli84adaab2016-09-20 01:12:2821#include "base/time/time.h"
mmenkecbc2b712014-10-09 20:29:0722#include "net/base/chunked_upload_data_stream.h"
23#include "net/base/elements_upload_data_stream.h"
David Benjamin0288768a2019-07-22 15:00:2624#include "net/base/load_flags.h"
xunjieli84adaab2016-09-20 01:12:2825#include "net/base/load_timing_info.h"
26#include "net/base/load_timing_info_test_util.h"
[email protected]f702d572012-12-04 15:56:2027#include "net/base/net_errors.h"
28#include "net/base/test_completion_callback.h"
[email protected]b2d26cfd2012-12-11 10:36:0629#include "net/base/upload_bytes_element_reader.h"
Ben Schwartz3ff4dc1e62021-04-27 21:15:2330#include "net/dns/public/secure_dns_policy.h"
[email protected]f702d572012-12-04 15:56:2031#include "net/http/http_response_headers.h"
[email protected]5db452202014-08-19 05:22:1532#include "net/http/transport_security_state.h"
Matt Reichhoff0049a0b72021-10-20 20:44:2633#include "net/log/net_log.h"
mikecirone8b85c432016-09-08 19:11:0034#include "net/log/net_log_event_type.h"
xunjieli5fafe142016-03-23 23:32:5435#include "net/log/test_net_log.h"
36#include "net/log/test_net_log_util.h"
Victor Vasiliev4f6fb892019-05-31 16:58:3137#include "net/quic/address_utils.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0838#include "net/quic/crypto/proof_verifier_chromium.h"
39#include "net/quic/mock_crypto_client_stream_factory.h"
40#include "net/quic/quic_chromium_alarm_factory.h"
41#include "net/quic/quic_chromium_connection_helper.h"
42#include "net/quic/quic_chromium_packet_reader.h"
43#include "net/quic/quic_chromium_packet_writer.h"
Matt Menkefca05b62019-09-20 23:15:5644#include "net/quic/quic_crypto_client_config_handle.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0845#include "net/quic/quic_http_utils.h"
46#include "net/quic/quic_server_info.h"
47#include "net/quic/quic_stream_factory.h"
48#include "net/quic/quic_test_packet_maker.h"
Ryan Hamilton0d65a8c2019-06-07 00:46:0249#include "net/quic/quic_test_packet_printer.h"
Matt Menkefca05b62019-09-20 23:15:5650#include "net/quic/test_quic_crypto_client_config_handle.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0851#include "net/quic/test_task_runner.h"
tbansalca83c002016-04-28 20:56:2852#include "net/socket/socket_performance_watcher.h"
[email protected]f702d572012-12-04 15:56:2053#include "net/socket/socket_test_util.h"
Bence Béky94658bf2018-05-11 19:22:5854#include "net/spdy/spdy_http_utils.h"
rch03b7a202016-02-05 00:54:2055#include "net/test/cert_test_util.h"
robpercival214763f2016-07-01 23:27:0156#include "net/test/gtest_util.h"
rsleevia69c79a2016-06-22 03:28:4357#include "net/test/test_data_directory.h"
Gabriel Charettec7108742019-08-23 03:31:4058#include "net/test/test_with_task_environment.h"
Ryan Hamiltonea4fa192022-04-12 18:30:4959#include "net/third_party/quiche/src/quiche/quic/core/congestion_control/send_algorithm_interface.h"
60#include "net/third_party/quiche/src/quiche/quic/core/crypto/crypto_protocol.h"
61#include "net/third_party/quiche/src/quiche/quic/core/crypto/quic_decrypter.h"
62#include "net/third_party/quiche/src/quiche/quic/core/crypto/quic_encrypter.h"
63#include "net/third_party/quiche/src/quiche/quic/core/http/spdy_server_push_utils.h"
64#include "net/third_party/quiche/src/quiche/quic/core/quic_connection.h"
65#include "net/third_party/quiche/src/quiche/quic/core/quic_utils.h"
66#include "net/third_party/quiche/src/quiche/quic/core/quic_write_blocked_list.h"
67#include "net/third_party/quiche/src/quiche/quic/core/tls_client_handshaker.h"
68#include "net/third_party/quiche/src/quiche/quic/platform/api/quic_flags.h"
69#include "net/third_party/quiche/src/quiche/quic/test_tools/crypto_test_utils.h"
70#include "net/third_party/quiche/src/quiche/quic/test_tools/mock_clock.h"
71#include "net/third_party/quiche/src/quiche/quic/test_tools/mock_random.h"
72#include "net/third_party/quiche/src/quiche/quic/test_tools/qpack/qpack_test_utils.h"
73#include "net/third_party/quiche/src/quiche/quic/test_tools/quic_connection_peer.h"
74#include "net/third_party/quiche/src/quiche/quic/test_tools/quic_spdy_session_peer.h"
75#include "net/third_party/quiche/src/quiche/quic/test_tools/quic_test_utils.h"
76#include "net/third_party/quiche/src/quiche/spdy/core/spdy_frame_builder.h"
77#include "net/third_party/quiche/src/quiche/spdy/core/spdy_framer.h"
78#include "net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.h"
Ramin Halavati683bcaa92018-02-14 08:42:3979#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
[email protected]f702d572012-12-04 15:56:2080#include "testing/gmock/include/gmock/gmock.h"
81#include "testing/gtest/include/gtest/gtest.h"
Dan McArdle68a5f622021-07-09 20:56:5382#include "url/scheme_host_port.h"
83#include "url/url_constants.h"
[email protected]f702d572012-12-04 15:56:2084
bnc614a92d32016-04-04 13:56:0785using std::string;
[email protected]f702d572012-12-04 15:56:2086using testing::_;
[email protected]06ff5152013-08-29 01:03:0587using testing::AnyNumber;
88using testing::Return;
[email protected]f702d572012-12-04 15:56:2089
Tsuyoshi Horo4f516be2022-06-14 11:53:1390namespace net::test {
[email protected]f702d572012-12-04 15:56:2091namespace {
92
[email protected]16ba7742014-08-22 00:57:2593const char kUploadData[] = "Really nifty data!";
rch9ae5b3b2016-02-11 00:36:2994const char kDefaultServerHostName[] = "www.example.org";
rchcd379012017-04-12 21:53:3295const uint16_t kDefaultServerPort = 443;
[email protected]f702d572012-12-04 15:56:2096
David Schinazi09e9a6012019-10-03 17:37:5797struct TestParams {
98 quic::ParsedQuicVersion version;
99 bool client_headers_include_h2_stream_dependency;
100};
101
102// Used by ::testing::PrintToStringParamName().
103std::string PrintToString(const TestParams& p) {
Victor Vasiliev62c09dc2020-11-06 18:18:29104 return base::StrCat(
105 {ParsedQuicVersionToString(p.version), "_",
106 (p.client_headers_include_h2_stream_dependency ? "" : "No"),
107 "Dependency"});
David Schinazi09e9a6012019-10-03 17:37:57108}
109
110std::vector<TestParams> GetTestParams() {
111 std::vector<TestParams> params;
112 quic::ParsedQuicVersionVector all_supported_versions =
113 quic::AllSupportedVersions();
114 for (const auto& version : all_supported_versions) {
115 params.push_back(TestParams{version, false});
116 params.push_back(TestParams{version, true});
117 }
118 return params;
119}
120
Bence Békye0d3747d2020-08-28 23:16:40121// Returns true if |params| is a dict, has an entry with key "headers", that
122// entry is a list of strings, which when interpreted as colon-separated
123// key-value pairs has exactly one entry with |key| and that entry has value
124// |expected_value|.
125bool CheckHeader(const base::Value& params,
126 base::StringPiece key,
127 base::StringPiece expected_value) {
128 if (!params.is_dict()) {
129 return false;
130 }
Matt Menke355d7b1e2022-05-27 23:19:53131 const base::Value::List* headers = params.GetDict().FindList("headers");
Bence Békye0d3747d2020-08-28 23:16:40132 if (!headers) {
133 return false;
134 }
135
136 std::string header_prefix = base::StrCat({key, ": "});
137 std::string expected_header = base::StrCat({header_prefix, expected_value});
138
Bence Békye0d3747d2020-08-28 23:16:40139 bool header_found = false;
Matt Menke355d7b1e2022-05-27 23:19:53140 for (const auto& header_value : *headers) {
141 const std::string* header = header_value.GetIfString();
142 if (!header) {
Bence Békye0d3747d2020-08-28 23:16:40143 return false;
144 }
Matt Menke355d7b1e2022-05-27 23:19:53145 if (base::StartsWith(*header, header_prefix)) {
Bence Békye0d3747d2020-08-28 23:16:40146 if (header_found) {
147 return false;
148 }
Matt Menke355d7b1e2022-05-27 23:19:53149 if (*header != expected_header) {
Bence Békye0d3747d2020-08-28 23:16:40150 return false;
151 }
152 header_found = true;
153 }
Bence Békye0d3747d2020-08-28 23:16:40154 }
155 return header_found;
156}
157
Ryan Hamilton8d9ee76e2018-05-29 23:52:52158class TestQuicConnection : public quic::QuicConnection {
[email protected]f702d572012-12-04 15:56:20159 public:
Ryan Hamilton8d9ee76e2018-05-29 23:52:52160 TestQuicConnection(const quic::ParsedQuicVersionVector& versions,
161 quic::QuicConnectionId connection_id,
[email protected]f702d572012-12-04 15:56:20162 IPEndPoint address,
rch12fef552016-01-15 16:26:31163 QuicChromiumConnectionHelper* helper,
rch16c74d1d2016-04-22 06:14:07164 QuicChromiumAlarmFactory* alarm_factory,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52165 quic::QuicPacketWriter* writer)
Victor Vasiliev4f6fb892019-05-31 16:58:31166 : quic::QuicConnection(connection_id,
Nick Harperd049f192020-10-02 02:56:10167 quic::QuicSocketAddress(),
Victor Vasiliev4f6fb892019-05-31 16:58:31168 ToQuicSocketAddress(address),
169 helper,
170 alarm_factory,
171 writer,
172 true /* owns_writer */,
173 quic::Perspective::IS_CLIENT,
174 versions) {}
[email protected]f702d572012-12-04 15:56:20175
Ryan Hamilton8d9ee76e2018-05-29 23:52:52176 void SetSendAlgorithm(quic::SendAlgorithmInterface* send_algorithm) {
177 quic::test::QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
[email protected]f702d572012-12-04 15:56:20178 }
179};
180
maksim.sisov84e20c92016-06-23 08:49:34181// UploadDataStream that always returns errors on data read.
182class ReadErrorUploadDataStream : public UploadDataStream {
183 public:
184 enum class FailureMode { SYNC, ASYNC };
185
186 explicit ReadErrorUploadDataStream(FailureMode mode)
Jeremy Romand54000b22019-07-08 18:40:16187 : UploadDataStream(true, 0), async_(mode) {}
Peter Boström293b1342021-09-22 17:31:43188
189 ReadErrorUploadDataStream(const ReadErrorUploadDataStream&) = delete;
190 ReadErrorUploadDataStream& operator=(const ReadErrorUploadDataStream&) =
191 delete;
192
maksim.sisov84e20c92016-06-23 08:49:34193 ~ReadErrorUploadDataStream() override {}
194
195 private:
196 void CompleteRead() { UploadDataStream::OnReadCompleted(ERR_FAILED); }
197
198 // UploadDataStream implementation:
tfarina42834112016-09-22 13:38:20199 int InitInternal(const NetLogWithSource& net_log) override { return OK; }
maksim.sisov84e20c92016-06-23 08:49:34200
201 int ReadInternal(IOBuffer* buf, int buf_len) override {
202 if (async_ == FailureMode::ASYNC) {
203 base::ThreadTaskRunnerHandle::Get()->PostTask(
kylecharf4fe5172019-02-15 18:53:49204 FROM_HERE, base::BindOnce(&ReadErrorUploadDataStream::CompleteRead,
205 weak_factory_.GetWeakPtr()));
maksim.sisov84e20c92016-06-23 08:49:34206 return ERR_IO_PENDING;
207 }
208 return ERR_FAILED;
209 }
210
211 void ResetInternal() override {}
212
213 const FailureMode async_;
214
Jeremy Romand54000b22019-07-08 18:40:16215 base::WeakPtrFactory<ReadErrorUploadDataStream> weak_factory_{this};
maksim.sisov84e20c92016-06-23 08:49:34216};
217
Bence Béky8ddc2492018-06-13 01:02:04218// A helper class that will delete |stream| when the callback is invoked.
xunjieli8dff50b2016-07-22 14:19:06219class DeleteStreamCallback : public TestCompletionCallbackBase {
220 public:
Bence Béky8ddc2492018-06-13 01:02:04221 explicit DeleteStreamCallback(std::unique_ptr<QuicHttpStream> stream)
222 : stream_(std::move(stream)) {}
xunjieli8dff50b2016-07-22 14:19:06223
Bence Béky8ddc2492018-06-13 01:02:04224 CompletionOnceCallback callback() {
225 return base::BindOnce(&DeleteStreamCallback::DeleteStream,
226 base::Unretained(this));
227 }
xunjieli8dff50b2016-07-22 14:19:06228
229 private:
230 void DeleteStream(int result) {
231 stream_.reset();
232 SetResult(result);
233 }
234
235 std::unique_ptr<QuicHttpStream> stream_;
xunjieli8dff50b2016-07-22 14:19:06236};
237
[email protected]f702d572012-12-04 15:56:20238} // namespace
239
[email protected]24e5bc52013-09-18 15:36:58240class QuicHttpStreamPeer {
241 public:
rch08e198572017-05-09 16:56:55242 static QuicChromiumClientStream::Handle* GetQuicChromiumClientStream(
[email protected]24e5bc52013-09-18 15:36:58243 QuicHttpStream* stream) {
rch08e198572017-05-09 16:56:55244 return stream->stream_.get();
[email protected]24e5bc52013-09-18 15:36:58245 }
246};
247
David Schinazi09e9a6012019-10-03 17:37:57248class QuicHttpStreamTest : public ::testing::TestWithParam<TestParams>,
Gabriel Charette694c3c332019-08-19 14:53:05249 public WithTaskEnvironment {
rchfb47f712017-05-21 03:24:00250 public:
251 void CloseStream(QuicHttpStream* stream, int /*rv*/) { stream->Close(false); }
252
[email protected]f702d572012-12-04 15:56:20253 protected:
[email protected]1e960032013-12-20 19:00:20254 static const bool kFin = true;
255 static const bool kIncludeVersion = true;
[email protected]1e960032013-12-20 19:00:20256
[email protected]f702d572012-12-04 15:56:20257 // Holds a packet to be written to the wire, and the IO mode that should
258 // be used by the mock socket when performing the write.
259 struct PacketToWrite {
Ryan Hamilton8d9ee76e2018-05-29 23:52:52260 PacketToWrite(IoMode mode, quic::QuicReceivedPacket* packet)
rjshaded5ced072015-12-18 19:26:02261 : mode(mode), packet(packet) {}
rtenneti15656ae2016-01-23 03:05:03262 PacketToWrite(IoMode mode, int rv) : mode(mode), packet(nullptr), rv(rv) {}
[email protected]f702d572012-12-04 15:56:20263 IoMode mode;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52264 quic::QuicReceivedPacket* packet;
rtenneti15656ae2016-01-23 03:05:03265 int rv;
[email protected]f702d572012-12-04 15:56:20266 };
267
268 QuicHttpStreamTest()
David Schinazi09e9a6012019-10-03 17:37:57269 : version_(GetParam().version),
270 client_headers_include_h2_stream_dependency_(
271 GetParam().client_headers_include_h2_stream_dependency),
Nick Harpera598fc5f2019-06-21 08:46:50272 crypto_config_(
273 quic::test::crypto_test_utils::ProofVerifierForTesting()),
Victor Costan9c7302b2018-08-27 16:39:44274 read_buffer_(base::MakeRefCounted<IOBufferWithSize>(4096)),
Fan Yang32c5a112018-12-10 20:06:33275 promise_id_(GetNthServerInitiatedUnidirectionalStreamId(0)),
276 stream_id_(GetNthClientInitiatedBidirectionalStreamId(0)),
David Schinazic8281052019-01-24 06:14:17277 connection_id_(quic::test::TestConnectionId(2)),
Yixin Wang079ad542018-01-11 04:06:05278 client_maker_(version_,
alyssar2adf3ac2016-05-03 17:12:58279 connection_id_,
280 &clock_,
281 kDefaultServerHostName,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52282 quic::Perspective::IS_CLIENT,
Yixin Wang079ad542018-01-11 04:06:05283 client_headers_include_h2_stream_dependency_),
284 server_maker_(version_,
zhongyi5dbfdd42017-06-20 05:22:15285 connection_id_,
alyssar2adf3ac2016-05-03 17:12:58286 &clock_,
287 kDefaultServerHostName,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52288 quic::Perspective::IS_SERVER,
Yixin Wang079ad542018-01-11 04:06:05289 false),
Ryan Hamilton0d65a8c2019-06-07 00:46:02290 printer_(version_) {
Renjie Tang98b4d512020-02-08 01:24:19291 FLAGS_quic_enable_http3_grease_randomness = false;
Zhongyi Shi49f8ad2fd2019-12-13 01:20:31292 quic::QuicEnableVersion(version_);
martijn21968ea2016-02-24 18:46:20293 IPAddress ip(192, 0, 2, 33);
[email protected]f702d572012-12-04 15:56:20294 peer_addr_ = IPEndPoint(ip, 443);
295 self_addr_ = IPEndPoint(ip, 8435);
Ryan Hamilton8d9ee76e2018-05-29 23:52:52296 clock_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(20));
Ramin Halavati683bcaa92018-02-14 08:42:39297 request_.traffic_annotation =
298 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f702d572012-12-04 15:56:20299 }
300
301 ~QuicHttpStreamTest() {
Renjieba55fae2018-09-20 03:05:16302 session_->CloseSessionOnError(ERR_ABORTED, quic::QUIC_INTERNAL_ERROR,
303 quic::ConnectionCloseBehavior::SILENT_CLOSE);
[email protected]f702d572012-12-04 15:56:20304 for (size_t i = 0; i < writes_.size(); i++) {
305 delete writes_[i].packet;
306 }
307 }
308
309 // Adds a packet to the list of expected writes.
Ryan Hamilton8d9ee76e2018-05-29 23:52:52310 void AddWrite(std::unique_ptr<quic::QuicReceivedPacket> packet) {
[email protected]1e960032013-12-20 19:00:20311 writes_.push_back(PacketToWrite(SYNCHRONOUS, packet.release()));
[email protected]f702d572012-12-04 15:56:20312 }
313
rtenneti15656ae2016-01-23 03:05:03314 void AddWrite(IoMode mode, int rv) {
315 writes_.push_back(PacketToWrite(mode, rv));
316 }
317
[email protected]f702d572012-12-04 15:56:20318 // Returns the packet to be written at position |pos|.
Ryan Hamilton8d9ee76e2018-05-29 23:52:52319 quic::QuicReceivedPacket* GetWrite(size_t pos) { return writes_[pos].packet; }
[email protected]f702d572012-12-04 15:56:20320
321 bool AtEof() {
rch37de576c2015-05-17 20:28:17322 return socket_data_->AllReadDataConsumed() &&
323 socket_data_->AllWriteDataConsumed();
[email protected]f702d572012-12-04 15:56:20324 }
325
Ryan Hamilton8d9ee76e2018-05-29 23:52:52326 void ProcessPacket(std::unique_ptr<quic::QuicReceivedPacket> packet) {
Victor Vasiliev4f6fb892019-05-31 16:58:31327 connection_->ProcessUdpPacket(ToQuicSocketAddress(self_addr_),
328 ToQuicSocketAddress(peer_addr_), *packet);
[email protected]f702d572012-12-04 15:56:20329 }
330
331 // Configures the test fixture to use the list of expected writes.
332 void Initialize() {
Renjie Tang6ff9a9b2021-02-03 22:11:09333 mock_writes_ = std::make_unique<MockWrite[]>(writes_.size());
[email protected]f702d572012-12-04 15:56:20334 for (size_t i = 0; i < writes_.size(); i++) {
rtenneti15656ae2016-01-23 03:05:03335 if (writes_[i].packet == nullptr) {
336 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].rv, i);
337 } else {
338 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].packet->data(),
339 writes_[i].packet->length());
340 }
bnc614a92d32016-04-04 13:56:07341 }
[email protected]f702d572012-12-04 15:56:20342
Renjie Tang6ff9a9b2021-02-03 22:11:09343 socket_data_ = std::make_unique<StaticSocketDataProvider>(
Ryan Sleevib8d7ea02018-05-07 20:01:01344 base::span<MockRead>(),
Renjie Tang6ff9a9b2021-02-03 22:11:09345 base::make_span(mock_writes_.get(), writes_.size()));
Ryan Hamilton0d65a8c2019-06-07 00:46:02346 socket_data_->set_printer(&printer_);
[email protected]f702d572012-12-04 15:56:20347
Matt Reichhoff0049a0b72021-10-20 20:44:26348 std::unique_ptr<MockUDPClientSocket> socket(
349 new MockUDPClientSocket(socket_data_.get(), NetLog::Get()));
[email protected]e13201d82012-12-12 05:00:32350 socket->Connect(peer_addr_);
[email protected]f702d572012-12-04 15:56:20351 runner_ = new TestTaskRunner(&clock_);
Ryan Hamilton8d9ee76e2018-05-29 23:52:52352 send_algorithm_ = new quic::test::MockSendAlgorithm();
rch7dd15702015-07-01 18:57:57353 EXPECT_CALL(*send_algorithm_, InRecovery()).WillRepeatedly(Return(false));
354 EXPECT_CALL(*send_algorithm_, InSlowStart()).WillRepeatedly(Return(false));
Victor Vasiliev7da08172019-10-14 06:04:25355 if (VersionUsesHttp3(version_.transport_version)) {
Renjie Tangaadb84b2019-08-31 01:00:23356 EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
357 .Times(testing::AtLeast(1));
358 }
Ryan Hamiltona1d1f4a2019-06-26 14:43:04359 EXPECT_CALL(*send_algorithm_, OnCongestionEvent(_, _, _, _, _))
360 .Times(AnyNumber());
rtenneti44f4a2e2015-08-07 14:00:07361 EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
Zhongyi Shica576df2019-04-12 17:43:40362 .WillRepeatedly(Return(quic::kMaxOutgoingPacketSize));
jokulik0e0a00c32016-06-13 21:51:58363 EXPECT_CALL(*send_algorithm_, PacingRate(_))
Ryan Hamilton8d9ee76e2018-05-29 23:52:52364 .WillRepeatedly(Return(quic::QuicBandwidth::Zero()));
Michael Warres74ee3ce2017-10-09 15:26:37365 EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true));
rtenneti44f4a2e2015-08-07 14:00:07366 EXPECT_CALL(*send_algorithm_, BandwidthEstimate())
Ryan Hamilton8d9ee76e2018-05-29 23:52:52367 .WillRepeatedly(Return(quic::QuicBandwidth::Zero()));
rch1e543ec2015-03-29 07:04:40368 EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(AnyNumber());
rch08cae032017-03-29 00:59:15369 EXPECT_CALL(*send_algorithm_, OnApplicationLimited(_)).Times(AnyNumber());
rch0d5bcf62017-05-24 22:48:45370 EXPECT_CALL(*send_algorithm_, GetCongestionControlType())
371 .Times(AnyNumber());
Renjie Tang6ff9a9b2021-02-03 22:11:09372 helper_ = std::make_unique<QuicChromiumConnectionHelper>(
373 &clock_, &random_generator_);
374 alarm_factory_ =
375 std::make_unique<QuicChromiumAlarmFactory>(runner_.get(), &clock_);
rch16c74d1d2016-04-22 06:14:07376
Michael Warres74ee3ce2017-10-09 15:26:37377 connection_ = new TestQuicConnection(
Nick Harper23290b82019-05-02 00:02:56378 quic::test::SupportedVersions(version_), connection_id_, peer_addr_,
379 helper_.get(), alarm_factory_.get(),
Ryan Hamilton9edcf1a2017-11-22 05:55:17380 new QuicChromiumPacketWriter(
381 socket.get(), base::ThreadTaskRunnerHandle::Get().get()));
[email protected]f702d572012-12-04 15:56:20382 connection_->set_visitor(&visitor_);
[email protected]fee17f72013-02-03 07:47:41383 connection_->SetSendAlgorithm(send_algorithm_);
rch03b7a202016-02-05 00:54:20384
385 // Load a certificate that is valid for *.example.org
386 scoped_refptr<X509Certificate> test_cert(
387 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
388 EXPECT_TRUE(test_cert.get());
389
390 verify_details_.cert_verify_result.verified_cert = test_cert;
391 verify_details_.cert_verify_result.is_issued_by_known_root = true;
392 crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details_);
393
xunjieli84adaab2016-09-20 01:12:28394 base::TimeTicks dns_end = base::TimeTicks::Now();
Peter Kastinge5a38ed2021-10-02 03:06:35395 base::TimeTicks dns_start = dns_end - base::Milliseconds(1);
Renjie Tang6ff9a9b2021-02-03 22:11:09396 session_ = std::make_unique<QuicChromiumClientSession>(
xunjielib53b38c2016-03-24 15:54:36397 connection_, std::move(socket),
rtenneti1cd3b162015-09-29 02:58:28398 /*stream_factory=*/nullptr, &crypto_client_stream_factory_, &clock_,
Nick Harper89bc7212018-07-31 19:07:57399 &transport_security_state_, /*ssl_config_service=*/nullptr,
danakjad1777e2016-04-16 00:56:42400 base::WrapUnique(static_cast<QuicServerInfo*>(nullptr)),
Paul Jensen8e3c5d32018-02-19 17:06:33401 QuicSessionKey(kDefaultServerHostName, kDefaultServerPort,
dalyk51ab46b2019-10-15 15:14:34402 PRIVACY_MODE_DISABLED, SocketTag(),
Tsuyoshi Horo7acebce2022-05-12 06:13:23403 NetworkIsolationKey(), SecureDnsPolicy::kAllow,
404 /*require_dns_https_alpn=*/false),
Bence Béky1ceba552019-07-19 17:11:05405 /*require_confirmation=*/false,
Bence Béky1ceba552019-07-19 17:11:05406 /*migrate_session_early_v2=*/false,
Zhongyi Shi757fcce2018-06-27 05:41:27407 /*migrate_session_on_network_change_v2=*/false,
408 /*default_network=*/NetworkChangeNotifier::kInvalidNetworkHandle,
Zhongyi Shie01f2db2019-02-22 19:53:23409 quic::QuicTime::Delta::FromMilliseconds(
Ryan Sleevi2e8255b2019-07-17 21:02:21410 kDefaultRetransmittableOnWireTimeout.InMilliseconds()),
Zhongyi Shiaf38c4e42019-08-29 22:49:05411 /*migrate_idle_session=*/false, /*allow_port_migration=*/false,
412 kDefaultIdleSessionMigrationPeriod, kMaxTimeOnNonDefaultNetwork,
Zhongyi Shiee760762018-08-01 00:54:29413 kMaxMigrationsToNonDefaultNetworkOnWriteError,
Zhongyi Shi8b1e43f2017-12-13 20:46:30414 kMaxMigrationsToNonDefaultNetworkOnPathDegrading,
Zhongyi Shi5f587cc2017-11-21 23:24:17415 kQuicYieldAfterPacketsRead,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52416 quic::QuicTime::Delta::FromMilliseconds(
417 kQuicYieldAfterDurationMilliseconds),
Yixin Wang079ad542018-01-11 04:06:05418 client_headers_include_h2_stream_dependency_, /*cert_verify_flags=*/0,
Matt Menkefca05b62019-09-20 23:15:56419 quic::test::DefaultQuicConfig(),
420 std::make_unique<TestQuicCryptoClientConfigHandle>(&crypto_config_),
Matt Menked804aaf2020-07-21 21:25:48421 "CONNECTION_UNKNOWN", dns_start, dns_end,
422 std::make_unique<quic::QuicClientPushPromiseIndex>(), nullptr,
Zhongyi Shic16b4102019-02-12 00:37:40423 base::DefaultTickClock::GetInstance(),
xunjieli84adaab2016-09-20 01:12:28424 base::ThreadTaskRunnerHandle::Get().get(),
Matt Reichhoff0049a0b72021-10-20 20:44:26425 /*socket_performance_watcher=*/nullptr, NetLog::Get());
rtennetid39bd762015-06-12 01:05:52426 session_->Initialize();
rchf0b18c8a2017-05-05 19:31:57427
Bence Béky6e243aa2019-12-13 19:01:07428 // Blackhole QPACK decoder stream instead of constructing mock writes.
429 if (VersionUsesHttp3(version_.transport_version)) {
430 session_->qpack_decoder()->set_qpack_stream_sender_delegate(
431 &noop_qpack_stream_sender_delegate_);
432 }
433
434 TestCompletionCallback callback;
rch433bf5f2017-02-14 04:10:47435 session_->CryptoConnect(callback.callback());
Ryan Hamilton6c2a2a82017-12-15 02:06:28436 stream_ = std::make_unique<QuicHttpStream>(
Dan McArdle68a5f622021-07-09 20:56:53437 session_->CreateHandle(
438 url::SchemeHostPort(url::kHttpsScheme, "www.example.org", 443)),
Eric Orthac661912022-01-10 21:44:17439 /*dns_aliases=*/std::set<std::string>());
Ryan Hamilton6c2a2a82017-12-15 02:06:28440 promised_stream_ = std::make_unique<QuicHttpStream>(
Dan McArdle68a5f622021-07-09 20:56:53441 session_->CreateHandle(
442 url::SchemeHostPort(url::kHttpsScheme, "www.example.org", 443)),
Eric Orthac661912022-01-10 21:44:17443 /*dns_aliases=*/std::set<std::string>());
ckrasic3865ee0f2016-02-29 22:04:56444 push_promise_[":path"] = "/bar";
445 push_promise_[":authority"] = "www.example.org";
446 push_promise_[":version"] = "HTTP/1.1";
447 push_promise_[":method"] = "GET";
448 push_promise_[":scheme"] = "https";
449
Kenichi Ishibashif8634ab2021-03-16 23:41:28450 promised_response_[":status"] = "200";
ckrasic3865ee0f2016-02-29 22:04:56451 promised_response_[":version"] = "HTTP/1.1";
452 promised_response_["content-type"] = "text/plain";
453
David Schinazi3f7465c2019-07-12 01:57:05454 promise_url_ =
455 quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
[email protected]6cca996b2013-01-25 07:43:36456 }
457
bnc614a92d32016-04-04 13:56:07458 void SetRequest(const string& method,
459 const string& path,
[email protected]1e960032013-12-20 19:00:20460 RequestPriority priority) {
rchcd379012017-04-12 21:53:32461 request_headers_ = client_maker_.GetRequestHeaders(method, "https", path);
[email protected]6cca996b2013-01-25 07:43:36462 }
463
bnc614a92d32016-04-04 13:56:07464 void SetResponse(const string& status, const string& body) {
alyssar2adf3ac2016-05-03 17:12:58465 response_headers_ = server_maker_.GetResponseHeaders(status);
[email protected]92bf17c2014-03-03 21:14:03466 response_data_ = body;
[email protected]6cca996b2013-01-25 07:43:36467 }
[email protected]f702d572012-12-04 15:56:20468
Ryan Hamilton8d9ee76e2018-05-29 23:52:52469 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientDataPacket(
Fan Yangac867502019-01-28 21:10:23470 uint64_t packet_number,
[email protected]e8ff26842013-03-22 21:02:05471 bool should_include_version,
[email protected]f702d572012-12-04 15:56:20472 bool fin,
Victor Vasiliev47ecb6a2020-10-14 17:22:10473 absl::string_view data) {
Ryan Hamilton7505eb92019-06-08 00:22:17474 return client_maker_.MakeDataPacket(packet_number, stream_id_,
475 should_include_version, fin, data);
alyssar2adf3ac2016-05-03 17:12:58476 }
477
Ryan Hamilton8d9ee76e2018-05-29 23:52:52478 std::unique_ptr<quic::QuicReceivedPacket> ConstructServerDataPacket(
Fan Yangac867502019-01-28 21:10:23479 uint64_t packet_number,
alyssar2adf3ac2016-05-03 17:12:58480 bool should_include_version,
481 bool fin,
Victor Vasiliev47ecb6a2020-10-14 17:22:10482 absl::string_view data) {
Ryan Hamilton7505eb92019-06-08 00:22:17483 return server_maker_.MakeDataPacket(packet_number, stream_id_,
484 should_include_version, fin, data);
ckrasic3865ee0f2016-02-29 22:04:56485 }
486
Ryan Hamilton8d9ee76e2018-05-29 23:52:52487 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23488 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52489 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56490 bool should_include_version,
491 bool fin,
492 RequestPriority request_priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02493 size_t* spdy_headers_frame_length) {
Yixin Wang7a3f1b8d2018-01-17 21:40:48494 return InnerConstructRequestHeadersPacket(
495 packet_number, stream_id, should_include_version, fin, request_priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02496 0, spdy_headers_frame_length);
Yixin Wang7a3f1b8d2018-01-17 21:40:48497 }
498
Ryan Hamilton8d9ee76e2018-05-29 23:52:52499 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23500 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52501 quic::QuicStreamId stream_id,
Yixin Wang7a3f1b8d2018-01-17 21:40:48502 bool should_include_version,
503 bool fin,
504 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52505 quic::QuicStreamId parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02506 size_t* spdy_headers_frame_length) {
Ryan Hamilton0239aac2018-05-19 00:03:13507 spdy::SpdyPriority priority =
ckrasic3865ee0f2016-02-29 22:04:56508 ConvertRequestPriorityToQuicPriority(request_priority);
alyssar2adf3ac2016-05-03 17:12:58509 return client_maker_.MakeRequestHeadersPacket(
ckrasic3865ee0f2016-02-29 22:04:56510 packet_number, stream_id, should_include_version, fin, priority,
Yixin Wang7a3f1b8d2018-01-17 21:40:48511 std::move(request_headers_), parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02512 spdy_headers_frame_length);
[email protected]f702d572012-12-04 15:56:20513 }
514
Ryan Hamilton8d9ee76e2018-05-29 23:52:52515 std::unique_ptr<quic::QuicReceivedPacket>
Yixin Wange7ecc472018-03-06 19:00:25516 ConstructRequestHeadersAndDataFramesPacket(
Fan Yangac867502019-01-28 21:10:23517 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52518 quic::QuicStreamId stream_id,
Yixin Wange7ecc472018-03-06 19:00:25519 bool should_include_version,
520 bool fin,
521 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52522 quic::QuicStreamId parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25523 size_t* spdy_headers_frame_length,
524 const std::vector<std::string>& data_writes) {
Ryan Hamilton0239aac2018-05-19 00:03:13525 spdy::SpdyPriority priority =
Yixin Wange7ecc472018-03-06 19:00:25526 ConvertRequestPriorityToQuicPriority(request_priority);
527 return client_maker_.MakeRequestHeadersAndMultipleDataFramesPacket(
528 packet_number, stream_id, should_include_version, fin, priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02529 std::move(request_headers_), parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25530 spdy_headers_frame_length, data_writes);
531 }
532
Ryan Hamilton8d9ee76e2018-05-29 23:52:52533 std::unique_ptr<quic::QuicReceivedPacket> ConstructRequestAndRstPacket(
Fan Yangac867502019-01-28 21:10:23534 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52535 quic::QuicStreamId stream_id,
Yixin Wange7ecc472018-03-06 19:00:25536 bool should_include_version,
537 bool fin,
538 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52539 quic::QuicStreamId parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25540 size_t* spdy_headers_frame_length,
Ryan Hamiltonb5d4c5a2019-06-21 22:08:41541 quic::QuicRstStreamErrorCode error_code) {
Ryan Hamilton0239aac2018-05-19 00:03:13542 spdy::SpdyPriority priority =
Yixin Wange7ecc472018-03-06 19:00:25543 ConvertRequestPriorityToQuicPriority(request_priority);
544 return client_maker_.MakeRequestHeadersAndRstPacket(
545 packet_number, stream_id, should_include_version, fin, priority,
546 std::move(request_headers_), parent_stream_id,
Ryan Hamiltonb5d4c5a2019-06-21 22:08:41547 spdy_headers_frame_length, error_code);
Yixin Wange7ecc472018-03-06 19:00:25548 }
549
Ryan Hamilton8d9ee76e2018-05-29 23:52:52550 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructResponseHeadersPacket(
Fan Yangac867502019-01-28 21:10:23551 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52552 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56553 bool fin,
554 size_t* spdy_headers_frame_length) {
alyssar2adf3ac2016-05-03 17:12:58555 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26556 packet_number, stream_id, !kIncludeVersion, fin,
Ryan Hamilton0d65a8c2019-06-07 00:46:02557 std::move(response_headers_), spdy_headers_frame_length);
[email protected]1e960032013-12-20 19:00:20558 }
559
Ryan Hamilton8d9ee76e2018-05-29 23:52:52560 std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseHeadersPacket(
Fan Yangac867502019-01-28 21:10:23561 uint64_t packet_number,
sclittlec4dc1a32015-09-24 00:15:45562 bool fin,
563 size_t* spdy_headers_frame_length) {
ckrasic3865ee0f2016-02-29 22:04:56564 return InnerConstructResponseHeadersPacket(packet_number, stream_id_, fin,
565 spdy_headers_frame_length);
[email protected]1e960032013-12-20 19:00:20566 }
567
Ryan Hamilton8d9ee76e2018-05-29 23:52:52568 std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseTrailersPacket(
Fan Yangac867502019-01-28 21:10:23569 uint64_t packet_number,
xunjieli34291fe12016-03-02 13:58:38570 bool fin,
Bence Béky4c325e52020-10-22 20:48:01571 spdy::Http2HeaderBlock trailers,
Ryan Hamilton0d65a8c2019-06-07 00:46:02572 size_t* spdy_headers_frame_length) {
alyssar2adf3ac2016-05-03 17:12:58573 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26574 packet_number, stream_id_, !kIncludeVersion, fin, std::move(trailers),
Ryan Hamilton0d65a8c2019-06-07 00:46:02575 spdy_headers_frame_length);
xunjieli34291fe12016-03-02 13:58:38576 }
577
Ryan Hamilton8d9ee76e2018-05-29 23:52:52578 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientRstStreamErrorPacket(
Fan Yangac867502019-01-28 21:10:23579 uint64_t packet_number,
maksim.sisov84e20c92016-06-23 08:49:34580 bool include_version) {
581 return client_maker_.MakeRstPacket(packet_number, include_version,
582 stream_id_,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52583 quic::QUIC_ERROR_PROCESSING_STREAM);
maksim.sisov84e20c92016-06-23 08:49:34584 }
585
Ryan Hamilton8d9ee76e2018-05-29 23:52:52586 std::unique_ptr<quic::QuicReceivedPacket> ConstructAckAndRstStreamPacket(
Fan Yangac867502019-01-28 21:10:23587 uint64_t packet_number) {
Renjie Tangcd594f32020-07-11 20:18:34588 return client_maker_.MakeAckAndRstPacket(packet_number, !kIncludeVersion,
589 stream_id_,
590 quic::QUIC_STREAM_CANCELLED, 2, 1);
[email protected]c5e1aca2014-01-30 04:03:04591 }
592
Ryan Hamilton8d9ee76e2018-05-29 23:52:52593 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientAckPacket(
Fan Yangac867502019-01-28 21:10:23594 uint64_t packet_number,
595 uint64_t largest_received,
Renjie Tangcd594f32020-07-11 20:18:34596 uint64_t smallest_received) {
alyssar2adf3ac2016-05-03 17:12:58597 return client_maker_.MakeAckPacket(packet_number, largest_received,
Renjie Tangcd594f32020-07-11 20:18:34598 smallest_received);
alyssar2adf3ac2016-05-03 17:12:58599 }
600
Ryan Hamilton8d9ee76e2018-05-29 23:52:52601 std::unique_ptr<quic::QuicReceivedPacket> ConstructServerAckPacket(
Fan Yangac867502019-01-28 21:10:23602 uint64_t packet_number,
603 uint64_t largest_received,
604 uint64_t smallest_received,
605 uint64_t least_unacked) {
alyssar2adf3ac2016-05-03 17:12:58606 return server_maker_.MakeAckPacket(packet_number, largest_received,
Bence Béky7a45d4d2020-05-08 01:59:23607 smallest_received, least_unacked);
[email protected]63534512012-12-23 18:49:00608 }
609
Ryan Hamilton0d65a8c2019-06-07 00:46:02610 std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket() {
611 return client_maker_.MakeInitialSettingsPacket(1);
fayang3bcb8b502016-12-07 21:44:37612 }
613
Renjie Tangaadb84b2019-08-31 01:00:23614 std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket(
615 int packet_number) {
616 return client_maker_.MakeInitialSettingsPacket(packet_number);
617 }
618
Victor Vasiliev076657c2019-03-12 02:46:43619 std::string ConstructDataHeader(size_t body_len) {
Nick Harperc6cb7a612020-02-24 20:03:32620 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:41621 return "";
622 }
Victor Vasilievc617d452022-03-07 15:54:25623 quiche::QuicheBuffer buffer = quic::HttpEncoder::SerializeDataFrameHeader(
624 body_len, quiche::SimpleBufferAllocator::Get());
Ian Swett17d4d1c02021-06-08 19:52:41625 return std::string(buffer.data(), buffer.size());
Renjief49758b2019-01-11 23:32:41626 }
627
Ryan Hamilton8d9ee76e2018-05-29 23:52:52628 void ReceivePromise(quic::QuicStreamId id) {
629 auto headers = quic::test::AsHeaderList(push_promise_);
rch08e198572017-05-09 16:56:55630 QuicChromiumClientStream::Handle* stream =
ckrasic3865ee0f2016-02-29 22:04:56631 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
ckrasic32b17dcd2016-10-31 06:15:35632 stream->OnPromiseHeaderList(id, headers.uncompressed_header_bytes(),
633 headers);
ckrasic3865ee0f2016-02-29 22:04:56634 }
635
xunjieli84adaab2016-09-20 01:12:28636 void ExpectLoadTimingValid(const LoadTimingInfo& load_timing_info,
xunjieli100937eb52016-09-15 20:09:37637 bool session_reused) {
638 EXPECT_EQ(session_reused, load_timing_info.socket_reused);
xunjieli84adaab2016-09-20 01:12:28639 if (session_reused) {
640 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
641 } else {
642 ExpectConnectTimingHasTimes(
643 load_timing_info.connect_timing,
644 CONNECT_TIMING_HAS_SSL_TIMES | CONNECT_TIMING_HAS_DNS_TIMES);
645 }
646 ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info);
xunjieli100937eb52016-09-15 20:09:37647 }
648
Fan Yang32c5a112018-12-10 20:06:33649 quic::QuicStreamId GetNthClientInitiatedBidirectionalStreamId(int n) {
Nick Harper23290b82019-05-02 00:02:56650 return quic::test::GetNthClientInitiatedBidirectionalStreamId(
651 version_.transport_version, n);
ckrasicbf2f59c2017-05-04 23:54:36652 }
653
Fan Yang32c5a112018-12-10 20:06:33654 quic::QuicStreamId GetNthServerInitiatedUnidirectionalStreamId(int n) {
Nick Harper23290b82019-05-02 00:02:56655 return quic::test::GetNthServerInitiatedUnidirectionalStreamId(
656 version_.transport_version, n);
ckrasicbf2f59c2017-05-04 23:54:36657 }
658
Patrick Meenan0041f332022-05-19 23:48:35659 quic::test::QuicFlagSaver saver_;
Ryan Hamiltona1d1f4a2019-06-26 14:43:04660
Nick Harper23290b82019-05-02 00:02:56661 const quic::ParsedQuicVersion version_;
Yixin Wang079ad542018-01-11 04:06:05662 const bool client_headers_include_h2_stream_dependency_;
663
Matt Reichhoff0049a0b72021-10-20 20:44:26664 NetLogWithSource net_log_with_source_{
665 NetLogWithSource::Make(NetLog::Get(), NetLogSourceType::NONE)};
666 RecordingNetLogObserver net_log_observer_;
Keishi Hattori0e45c022021-11-27 09:25:52667 raw_ptr<quic::test::MockSendAlgorithm> send_algorithm_;
[email protected]f702d572012-12-04 15:56:20668 scoped_refptr<TestTaskRunner> runner_;
danakjad1777e2016-04-16 00:56:42669 std::unique_ptr<MockWrite[]> mock_writes_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52670 quic::MockClock clock_;
Keishi Hattori0e45c022021-11-27 09:25:52671 raw_ptr<TestQuicConnection> connection_;
danakjad1777e2016-04-16 00:56:42672 std::unique_ptr<QuicChromiumConnectionHelper> helper_;
rch16c74d1d2016-04-22 06:14:07673 std::unique_ptr<QuicChromiumAlarmFactory> alarm_factory_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52674 testing::StrictMock<quic::test::MockQuicConnectionVisitor> visitor_;
rch97827ee2017-05-24 23:49:12675 std::unique_ptr<UploadDataStream> upload_data_stream_;
danakjad1777e2016-04-16 00:56:42676 std::unique_ptr<QuicHttpStream> stream_;
[email protected]5db452202014-08-19 05:22:15677 TransportSecurityState transport_security_state_;
danakjad1777e2016-04-16 00:56:42678 std::unique_ptr<QuicChromiumClientSession> session_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52679 quic::QuicCryptoClientConfig crypto_config_;
[email protected]f702d572012-12-04 15:56:20680 TestCompletionCallback callback_;
681 HttpRequestInfo request_;
682 HttpRequestHeaders headers_;
683 HttpResponseInfo response_;
684 scoped_refptr<IOBufferWithSize> read_buffer_;
Bence Béky4c325e52020-10-22 20:48:01685 spdy::Http2HeaderBlock request_headers_;
686 spdy::Http2HeaderBlock response_headers_;
bnc614a92d32016-04-04 13:56:07687 string request_data_;
688 string response_data_;
[email protected]f702d572012-12-04 15:56:20689
ckrasic3865ee0f2016-02-29 22:04:56690 // For server push testing
danakjad1777e2016-04-16 00:56:42691 std::unique_ptr<QuicHttpStream> promised_stream_;
Bence Béky4c325e52020-10-22 20:48:01692 spdy::Http2HeaderBlock push_promise_;
693 spdy::Http2HeaderBlock promised_response_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52694 const quic::QuicStreamId promise_id_;
ckrasic3865ee0f2016-02-29 22:04:56695 string promise_url_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52696 const quic::QuicStreamId stream_id_;
ckrasic3865ee0f2016-02-29 22:04:56697
Ryan Hamilton8d9ee76e2018-05-29 23:52:52698 const quic::QuicConnectionId connection_id_;
alyssar2adf3ac2016-05-03 17:12:58699 QuicTestPacketMaker client_maker_;
700 QuicTestPacketMaker server_maker_;
[email protected]f702d572012-12-04 15:56:20701 IPEndPoint self_addr_;
702 IPEndPoint peer_addr_;
Tsuyoshi Horo432981d52022-06-09 09:50:13703 quic::test::MockRandom random_generator_{0};
rch03b7a202016-02-05 00:54:20704 ProofVerifyDetailsChromium verify_details_;
[email protected]e8ff26842013-03-22 21:02:05705 MockCryptoClientStreamFactory crypto_client_stream_factory_;
danakjad1777e2016-04-16 00:56:42706 std::unique_ptr<StaticSocketDataProvider> socket_data_;
Ryan Hamilton0d65a8c2019-06-07 00:46:02707 QuicPacketPrinter printer_;
[email protected]f702d572012-12-04 15:56:20708 std::vector<PacketToWrite> writes_;
Bence Béky6e243aa2019-12-13 19:01:07709 quic::test::NoopQpackStreamSenderDelegate noop_qpack_stream_sender_delegate_;
[email protected]f702d572012-12-04 15:56:20710};
711
David Schinazi09e9a6012019-10-03 17:37:57712INSTANTIATE_TEST_SUITE_P(VersionIncludeStreamDependencySequence,
713 QuicHttpStreamTest,
714 ::testing::ValuesIn(GetTestParams()),
715 ::testing::PrintToStringParamName());
[email protected]1e960032013-12-20 19:00:20716
717TEST_P(QuicHttpStreamTest, RenewStreamForAuth) {
[email protected]ed3fc15d2013-03-08 18:37:44718 Initialize();
rtennetibe635732014-10-02 22:51:42719 EXPECT_EQ(nullptr, stream_->RenewStreamForAuth());
[email protected]f702d572012-12-04 15:56:20720}
721
mmenkebd84c392015-09-02 14:12:34722TEST_P(QuicHttpStreamTest, CanReuseConnection) {
[email protected]ed3fc15d2013-03-08 18:37:44723 Initialize();
mmenkebd84c392015-09-02 14:12:34724 EXPECT_FALSE(stream_->CanReuseConnection());
[email protected]f702d572012-12-04 15:56:20725}
726
jri231c2972016-03-08 19:50:11727TEST_P(QuicHttpStreamTest, DisableConnectionMigrationForStream) {
Zhongyi Shibb28b1f2018-07-18 02:41:26728 request_.load_flags |= LOAD_DISABLE_CONNECTION_MIGRATION_TO_CELLULAR;
jri231c2972016-03-08 19:50:11729 Initialize();
Ali Beyada0b1a1c2022-04-08 20:08:14730 stream_->RegisterRequest(&request_);
731 EXPECT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:26732 net_log_with_source_,
733 callback_.callback()));
rch08e198572017-05-09 16:56:55734 QuicChromiumClientStream::Handle* client_stream =
jri231c2972016-03-08 19:50:11735 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
Zhongyi Shibb28b1f2018-07-18 02:41:26736 EXPECT_FALSE(client_stream->can_migrate_to_cellular_network());
jri231c2972016-03-08 19:50:11737}
738
[email protected]1e960032013-12-20 19:00:20739TEST_P(QuicHttpStreamTest, GetRequest) {
740 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:45741 size_t spdy_request_header_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:23742 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:25743 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:23744 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:37745 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23746 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
747 kIncludeVersion, kFin, DEFAULT_PRIORITY,
748 &spdy_request_header_frame_length));
fayang3bcb8b502016-12-07 21:44:37749
[email protected]f702d572012-12-04 15:56:20750 Initialize();
751
752 request_.method = "GET";
rchcd379012017-04-12 21:53:32753 request_.url = GURL("https://www.example.org/");
[email protected]f702d572012-12-04 15:56:20754
xunjieli100937eb52016-09-15 20:09:37755 // Make sure getting load timing from the stream early does not crash.
756 LoadTimingInfo load_timing_info;
757 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
Ali Beyada0b1a1c2022-04-08 20:08:14758 stream_->RegisterRequest(&request_);
759 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:26760 net_log_with_source_,
761 callback_.callback()));
rjshaded5ced072015-12-18 19:26:02762 EXPECT_EQ(OK,
763 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20764
765 // Ack the request.
Renjie90e808e2019-01-24 07:24:04766 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]f702d572012-12-04 15:56:20767
robpercival214763f2016-07-01 23:27:01768 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
769 IsError(ERR_IO_PENDING));
[email protected]f702d572012-12-04 15:56:20770
Kenichi Ishibashif8634ab2021-03-16 23:41:28771 SetResponse("404", string());
sclittlec4dc1a32015-09-24 00:15:45772 size_t spdy_response_header_frame_length;
773 ProcessPacket(ConstructResponseHeadersPacket(
774 2, kFin, &spdy_response_header_frame_length));
[email protected]f702d572012-12-04 15:56:20775
776 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:01777 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]cadac622013-06-11 16:46:36778 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:20779 EXPECT_EQ(404, response_.headers->response_code());
780 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
[email protected]6ed67432014-06-24 01:53:53781 EXPECT_FALSE(response_.response_time.is_null());
782 EXPECT_FALSE(response_.request_time.is_null());
[email protected]f702d572012-12-04 15:56:20783
784 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:02785 EXPECT_EQ(0,
786 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
787 callback_.callback()));
[email protected]f702d572012-12-04 15:56:20788 EXPECT_TRUE(stream_->IsResponseBodyComplete());
789 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:10790
xunjieli100937eb52016-09-15 20:09:37791 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
xunjieli84adaab2016-09-20 01:12:28792 ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
xunjieli100937eb52016-09-15 20:09:37793
sclittle1edeeb22015-09-02 20:46:10794 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:45795 // headers and payload.
796 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
797 stream_->GetTotalSentBytes());
798 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length),
799 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:20800}
801
xunjieli100937eb52016-09-15 20:09:37802TEST_P(QuicHttpStreamTest, LoadTimingTwoRequests) {
803 SetRequest("GET", "/", DEFAULT_PRIORITY);
804 size_t spdy_request_header_frame_length;
805
Renjie Tangaadb84b2019-08-31 01:00:23806 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:25807 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:23808 AddWrite(ConstructInitialSettingsPacket(packet_number++));
xunjieli100937eb52016-09-15 20:09:37809 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23810 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
811 kIncludeVersion, kFin, DEFAULT_PRIORITY,
812 &spdy_request_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37813
814 // SetRequest() again for second request as |request_headers_| was moved.
815 SetRequest("GET", "/", DEFAULT_PRIORITY);
816 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23817 packet_number++, GetNthClientInitiatedBidirectionalStreamId(1),
818 kIncludeVersion, kFin, DEFAULT_PRIORITY,
819 GetNthClientInitiatedBidirectionalStreamId(0),
Ryan Hamilton0d65a8c2019-06-07 00:46:02820 &spdy_request_header_frame_length));
Renjie Tangcd594f32020-07-11 20:18:34821 AddWrite(
822 ConstructClientAckPacket(packet_number++, 3, 1)); // Ack the responses.
xunjieli100937eb52016-09-15 20:09:37823
824 Initialize();
825
826 request_.method = "GET";
rchcd379012017-04-12 21:53:32827 request_.url = GURL("https://www.example.org/");
xunjieli100937eb52016-09-15 20:09:37828 // Start first request.
Ali Beyada0b1a1c2022-04-08 20:08:14829 stream_->RegisterRequest(&request_);
830 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:26831 net_log_with_source_,
832 callback_.callback()));
xunjieli100937eb52016-09-15 20:09:37833 EXPECT_EQ(OK,
834 stream_->SendRequest(headers_, &response_, callback_.callback()));
835
836 // Start a second request.
Dan McArdle68a5f622021-07-09 20:56:53837 QuicHttpStream stream2(session_->CreateHandle(url::SchemeHostPort(
838 url::kHttpsScheme, "www.example.org", 443)),
839 {} /* dns_aliases */);
xunjieli100937eb52016-09-15 20:09:37840 TestCompletionCallback callback2;
Ali Beyada0b1a1c2022-04-08 20:08:14841 stream2.RegisterRequest(&request_);
Matt Reichhoff0049a0b72021-10-20 20:44:26842 EXPECT_EQ(
Ali Beyada0b1a1c2022-04-08 20:08:14843 OK, stream2.InitializeStream(true, DEFAULT_PRIORITY, net_log_with_source_,
844 callback2.callback()));
xunjieli100937eb52016-09-15 20:09:37845 EXPECT_EQ(OK,
846 stream2.SendRequest(headers_, &response_, callback2.callback()));
847
848 // Ack both requests.
Renjie90e808e2019-01-24 07:24:04849 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
xunjieli100937eb52016-09-15 20:09:37850
851 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
852 IsError(ERR_IO_PENDING));
853 size_t spdy_response_header_frame_length;
Kenichi Ishibashif8634ab2021-03-16 23:41:28854 SetResponse("200", string());
xunjieli100937eb52016-09-15 20:09:37855 ProcessPacket(InnerConstructResponseHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33856 2, GetNthClientInitiatedBidirectionalStreamId(0), kFin,
ckrasicbf2f59c2017-05-04 23:54:36857 &spdy_response_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37858
859 // Now that the headers have been processed, the callback will return.
860 EXPECT_THAT(callback_.WaitForResult(), IsOk());
861 EXPECT_EQ(200, response_.headers->response_code());
862
863 // There is no body, so this should return immediately.
864 EXPECT_EQ(0,
865 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
866 callback_.callback()));
867 EXPECT_TRUE(stream_->IsResponseBodyComplete());
868
869 LoadTimingInfo load_timing_info;
870 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
xunjieli84adaab2016-09-20 01:12:28871 ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
xunjieli100937eb52016-09-15 20:09:37872
873 // SetResponse() again for second request as |response_headers_| was moved.
Kenichi Ishibashif8634ab2021-03-16 23:41:28874 SetResponse("200", string());
xunjieli100937eb52016-09-15 20:09:37875 EXPECT_THAT(stream2.ReadResponseHeaders(callback2.callback()),
876 IsError(ERR_IO_PENDING));
877
878 ProcessPacket(InnerConstructResponseHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33879 3, GetNthClientInitiatedBidirectionalStreamId(1), kFin,
ckrasicbf2f59c2017-05-04 23:54:36880 &spdy_response_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37881
882 EXPECT_THAT(callback2.WaitForResult(), IsOk());
883
884 // There is no body, so this should return immediately.
885 EXPECT_EQ(0,
886 stream2.ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
887 callback2.callback()));
888 EXPECT_TRUE(stream2.IsResponseBodyComplete());
889
890 LoadTimingInfo load_timing_info2;
891 EXPECT_TRUE(stream2.GetLoadTimingInfo(&load_timing_info2));
xunjieli84adaab2016-09-20 01:12:28892 ExpectLoadTimingValid(load_timing_info2, /*session_reused=*/true);
xunjieli100937eb52016-09-15 20:09:37893}
894
xunjieli34291fe12016-03-02 13:58:38895// QuicHttpStream does not currently support trailers. It should ignore
896// trailers upon receiving them.
897TEST_P(QuicHttpStreamTest, GetRequestWithTrailers) {
898 SetRequest("GET", "/", DEFAULT_PRIORITY);
899 size_t spdy_request_header_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:23900 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:25901 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:23902 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:37903 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23904 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
905 kIncludeVersion, kFin, DEFAULT_PRIORITY,
906 &spdy_request_header_frame_length));
Renjie Tangcd594f32020-07-11 20:18:34907 AddWrite(
908 ConstructClientAckPacket(packet_number++, 3, 1)); // Ack the data packet.
xunjieli34291fe12016-03-02 13:58:38909
910 Initialize();
911
912 request_.method = "GET";
rchcd379012017-04-12 21:53:32913 request_.url = GURL("https://www.example.org/");
Ali Beyada0b1a1c2022-04-08 20:08:14914 stream_->RegisterRequest(&request_);
915 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:26916 net_log_with_source_,
917 callback_.callback()));
xunjieli5fafe142016-03-23 23:32:54918
xunjieli34291fe12016-03-02 13:58:38919 EXPECT_EQ(OK,
920 stream_->SendRequest(headers_, &response_, callback_.callback()));
xunjieli34291fe12016-03-02 13:58:38921 // Ack the request.
Renjie90e808e2019-01-24 07:24:04922 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
xunjieli34291fe12016-03-02 13:58:38923
robpercival214763f2016-07-01 23:27:01924 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
925 IsError(ERR_IO_PENDING));
xunjieli34291fe12016-03-02 13:58:38926
Kenichi Ishibashif8634ab2021-03-16 23:41:28927 SetResponse("200", string());
xunjieli34291fe12016-03-02 13:58:38928
929 // Send the response headers.
930 size_t spdy_response_header_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:02931 ProcessPacket(ConstructResponseHeadersPacket(
932 2, !kFin, &spdy_response_header_frame_length));
xunjieli34291fe12016-03-02 13:58:38933 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:01934 EXPECT_THAT(callback_.WaitForResult(), IsOk());
xunjieli34291fe12016-03-02 13:58:38935 ASSERT_TRUE(response_.headers.get());
936 EXPECT_EQ(200, response_.headers->response_code());
937 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
938 EXPECT_FALSE(response_.response_time.is_null());
939 EXPECT_FALSE(response_.request_time.is_null());
940
941 // Send the response body.
942 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:43943 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:17944 ProcessPacket(
945 ConstructServerDataPacket(3, false, !kFin, header + kResponseBody));
Bence Béky4c325e52020-10-22 20:48:01946 spdy::Http2HeaderBlock trailers;
xunjieli34291fe12016-03-02 13:58:38947 size_t spdy_trailers_frame_length;
948 trailers["foo"] = "bar";
Victor Vasiliev7da08172019-10-14 06:04:25949 if (!quic::VersionUsesHttp3(version_.transport_version)) {
Ryan Hamiltona1d1f4a2019-06-26 14:43:04950 trailers[quic::kFinalOffsetHeaderKey] =
951 base::NumberToString(strlen(kResponseBody) + header.length());
952 }
Ryan Hamilton0d65a8c2019-06-07 00:46:02953 ProcessPacket(ConstructResponseTrailersPacket(4, kFin, std::move(trailers),
954 &spdy_trailers_frame_length));
xunjieli34291fe12016-03-02 13:58:38955
956 // Make sure trailers are processed.
fdoray92e35a72016-06-10 15:54:55957 base::RunLoop().RunUntilIdle();
xunjieli34291fe12016-03-02 13:58:38958
959 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
960 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
961 callback_.callback()));
962 EXPECT_TRUE(stream_->IsResponseBodyComplete());
963
964 EXPECT_EQ(OK,
965 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
966 callback_.callback()));
967
968 EXPECT_TRUE(stream_->IsResponseBodyComplete());
969 EXPECT_TRUE(AtEof());
970
971 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
972 // headers and payload.
973 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
974 stream_->GetTotalSentBytes());
Renjief49758b2019-01-11 23:32:41975 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length +
976 strlen(kResponseBody) + header.length() +
977 +spdy_trailers_frame_length),
978 stream_->GetTotalReceivedBytes());
xunjieli5fafe142016-03-23 23:32:54979 // Check that NetLog was filled as expected.
Matt Reichhoff0049a0b72021-10-20 20:44:26980 auto entries = net_log_observer_.GetEntries();
xunjieli5fafe142016-03-23 23:32:54981 size_t pos = ExpectLogContainsSomewhere(
982 entries, /*min_offset=*/0,
mikecirone8b85c432016-09-08 19:11:00983 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
984 NetLogEventPhase::NONE);
xunjieli5fafe142016-03-23 23:32:54985 pos = ExpectLogContainsSomewhere(
986 entries, /*min_offset=*/pos,
mikecirone8b85c432016-09-08 19:11:00987 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
988 NetLogEventPhase::NONE);
xunjieli5fafe142016-03-23 23:32:54989 ExpectLogContainsSomewhere(
990 entries, /*min_offset=*/pos,
mikecirone8b85c432016-09-08 19:11:00991 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
992 NetLogEventPhase::NONE);
xunjieli34291fe12016-03-02 13:58:38993}
994
Bence Béky6c2c78f2020-08-28 16:49:06995TEST_P(QuicHttpStreamTest, ElideHeadersInNetLog) {
996 Initialize();
997
998 // QuicHttp3Logger is only used with HTTP/3.
999 if (!VersionUsesHttp3(version_.transport_version)) {
1000 return;
1001 }
1002
Matt Reichhoff0049a0b72021-10-20 20:44:261003 net_log_observer_.SetObserverCaptureMode(NetLogCaptureMode::kDefault);
Bence Béky6c2c78f2020-08-28 16:49:061004
Bence Békye0d3747d2020-08-28 23:16:401005 // Send first request.
Bence Béky6c2c78f2020-08-28 16:49:061006 SetRequest("GET", "/", DEFAULT_PRIORITY);
1007 request_.method = "GET";
1008 request_.url = GURL("https://www.example.org/");
1009 headers_.SetHeader(HttpRequestHeaders::kCookie, "secret");
1010
1011 size_t spdy_request_header_frame_length;
Bence Békye0d3747d2020-08-28 23:16:401012 int outgoing_packet_number = 1;
1013 AddWrite(ConstructInitialSettingsPacket(outgoing_packet_number++));
Bence Béky6c2c78f2020-08-28 16:49:061014 AddWrite(InnerConstructRequestHeadersPacket(
Bence Békye0d3747d2020-08-28 23:16:401015 outgoing_packet_number++, stream_id_, kIncludeVersion, kFin,
1016 DEFAULT_PRIORITY, &spdy_request_header_frame_length));
Bence Béky6c2c78f2020-08-28 16:49:061017
Ali Beyada0b1a1c2022-04-08 20:08:141018 stream_->RegisterRequest(&request_);
Matt Reichhoff0049a0b72021-10-20 20:44:261019 EXPECT_THAT(
Ali Beyada0b1a1c2022-04-08 20:08:141020 stream_->InitializeStream(true, DEFAULT_PRIORITY, net_log_with_source_,
1021 callback_.callback()),
Matt Reichhoff0049a0b72021-10-20 20:44:261022 IsOk());
Bence Béky6c2c78f2020-08-28 16:49:061023 EXPECT_THAT(stream_->SendRequest(headers_, &response_, callback_.callback()),
1024 IsOk());
Bence Békye0d3747d2020-08-28 23:16:401025 int incoming_packet_number = 1;
1026 ProcessPacket(ConstructServerAckPacket(incoming_packet_number++, 1, 1,
1027 1)); // Ack the request.
Bence Béky6c2c78f2020-08-28 16:49:061028
Bence Békye0d3747d2020-08-28 23:16:401029 // Process first response.
Kenichi Ishibashif8634ab2021-03-16 23:41:281030 SetResponse("200", string());
Bence Béky6c2c78f2020-08-28 16:49:061031 response_headers_["set-cookie"] = "secret";
1032 size_t spdy_response_header_frame_length;
1033 ProcessPacket(ConstructResponseHeadersPacket(
Bence Békye0d3747d2020-08-28 23:16:401034 incoming_packet_number++, kFin, &spdy_response_header_frame_length));
Bence Béky6c2c78f2020-08-28 16:49:061035 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
Bence Béky6c2c78f2020-08-28 16:49:061036
1037 ASSERT_TRUE(response_.headers.get());
1038 EXPECT_EQ(200, response_.headers->response_code());
1039 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1040 EXPECT_TRUE(response_.headers->HasHeaderValue("set-cookie", "secret"));
1041
Matt Reichhoff0049a0b72021-10-20 20:44:261042 net_log_observer_.SetObserverCaptureMode(
1043 NetLogCaptureMode::kIncludeSensitive);
Bence Béky6c2c78f2020-08-28 16:49:061044
Bence Békye0d3747d2020-08-28 23:16:401045 // Send second request.
1046 quic::QuicStreamId stream_id = GetNthClientInitiatedBidirectionalStreamId(1);
1047 request_.url = GURL("https://www.example.org/foo");
Bence Béky6c2c78f2020-08-28 16:49:061048
Bence Békye0d3747d2020-08-28 23:16:401049 AddWrite(InnerConstructRequestHeadersPacket(
1050 outgoing_packet_number++, stream_id, kIncludeVersion, kFin,
1051 DEFAULT_PRIORITY, &spdy_request_header_frame_length));
Bence Béky6c2c78f2020-08-28 16:49:061052
Bence Békye0d3747d2020-08-28 23:16:401053 auto stream = std::make_unique<QuicHttpStream>(
Dan McArdle68a5f622021-07-09 20:56:531054 session_->CreateHandle(
1055 url::SchemeHostPort(url::kHttpsScheme, "www.example.org/foo", 443)),
Eric Orthac661912022-01-10 21:44:171056 /*dns_aliases=*/std::set<std::string>());
Ali Beyada0b1a1c2022-04-08 20:08:141057 stream->RegisterRequest(&request_);
Matt Reichhoff0049a0b72021-10-20 20:44:261058 EXPECT_THAT(
Ali Beyada0b1a1c2022-04-08 20:08:141059 stream->InitializeStream(true, DEFAULT_PRIORITY, net_log_with_source_,
1060 callback_.callback()),
Matt Reichhoff0049a0b72021-10-20 20:44:261061 IsOk());
Bence Békye0d3747d2020-08-28 23:16:401062 EXPECT_THAT(stream->SendRequest(headers_, &response_, callback_.callback()),
1063 IsOk());
1064 ProcessPacket(ConstructServerAckPacket(incoming_packet_number++, 1, 1,
1065 1)); // Ack the request.
Bence Béky6c2c78f2020-08-28 16:49:061066
Bence Békye0d3747d2020-08-28 23:16:401067 // Process second response.
Kenichi Ishibashif8634ab2021-03-16 23:41:281068 SetResponse("200", string());
Bence Békye0d3747d2020-08-28 23:16:401069 response_headers_["set-cookie"] = "secret";
1070 ProcessPacket(InnerConstructResponseHeadersPacket(
1071 incoming_packet_number++, stream_id, kFin,
1072 &spdy_response_header_frame_length));
1073 EXPECT_THAT(stream->ReadResponseHeaders(callback_.callback()), IsOk());
Bence Béky6c2c78f2020-08-28 16:49:061074
Bence Békye0d3747d2020-08-28 23:16:401075 ASSERT_TRUE(response_.headers.get());
1076 EXPECT_EQ(200, response_.headers->response_code());
1077 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1078 EXPECT_TRUE(response_.headers->HasHeaderValue("set-cookie", "secret"));
1079
1080 EXPECT_TRUE(AtEof());
1081
1082 // Check that sensitive header value were stripped
1083 // for the first transaction (logged with NetLogCaptureMode::kDefault)
1084 // but not for the second (logged with NetLogCaptureMode::kIncludeSensitive).
1085 auto entries =
Matt Reichhoff0049a0b72021-10-20 20:44:261086 net_log_observer_.GetEntriesWithType(NetLogEventType::HTTP3_HEADERS_SENT);
Bence Békye0d3747d2020-08-28 23:16:401087 ASSERT_EQ(2u, entries.size());
1088 EXPECT_TRUE(
1089 CheckHeader(entries[0].params, "cookie", "[6 bytes were stripped]"));
1090 EXPECT_TRUE(CheckHeader(entries[1].params, "cookie", "secret"));
1091
Matt Reichhoff0049a0b72021-10-20 20:44:261092 entries = net_log_observer_.GetEntriesWithType(
1093 NetLogEventType::HTTP3_HEADERS_DECODED);
Bence Békye0d3747d2020-08-28 23:16:401094 ASSERT_EQ(2u, entries.size());
1095 EXPECT_TRUE(
1096 CheckHeader(entries[0].params, "set-cookie", "[6 bytes were stripped]"));
1097 EXPECT_TRUE(CheckHeader(entries[1].params, "set-cookie", "secret"));
Bence Béky6c2c78f2020-08-28 16:49:061098}
1099
[email protected]3e7dca62013-09-10 16:14:231100// Regression test for http://crbug.com/288128
[email protected]1e960032013-12-20 19:00:201101TEST_P(QuicHttpStreamTest, GetRequestLargeResponse) {
1102 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451103 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231104 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251105 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231106 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371107 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231108 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1109 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1110 &spdy_request_headers_frame_length));
[email protected]3e7dca62013-09-10 16:14:231111 Initialize();
1112
1113 request_.method = "GET";
rchcd379012017-04-12 21:53:321114 request_.url = GURL("https://www.example.org/");
[email protected]3e7dca62013-09-10 16:14:231115
Ali Beyada0b1a1c2022-04-08 20:08:141116 stream_->RegisterRequest(&request_);
1117 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261118 net_log_with_source_,
1119 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021120 EXPECT_EQ(OK,
1121 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:231122
1123 // Ack the request.
Renjie90e808e2019-01-24 07:24:041124 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]3e7dca62013-09-10 16:14:231125
robpercival214763f2016-07-01 23:27:011126 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1127 IsError(ERR_IO_PENDING));
[email protected]3e7dca62013-09-10 16:14:231128
Kenichi Ishibashif8634ab2021-03-16 23:41:281129 response_headers_[":status"] = "200";
bnc086b39e12016-06-24 13:05:261130 response_headers_[":version"] = "HTTP/1.1";
1131 response_headers_["content-type"] = "text/plain";
1132 response_headers_["big6"] = string(1000, 'x'); // Lots of x's.
[email protected]3e7dca62013-09-10 16:14:231133
sclittlec4dc1a32015-09-24 00:15:451134 size_t spdy_response_headers_frame_length;
1135 ProcessPacket(ConstructResponseHeadersPacket(
1136 2, kFin, &spdy_response_headers_frame_length));
[email protected]3e7dca62013-09-10 16:14:231137
1138 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:011139 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]3e7dca62013-09-10 16:14:231140 ASSERT_TRUE(response_.headers.get());
1141 EXPECT_EQ(200, response_.headers->response_code());
1142 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1143
1144 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:021145 EXPECT_EQ(0,
1146 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1147 callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:231148 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1149 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101150
1151 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451152 // headers and payload.
1153 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1154 stream_->GetTotalSentBytes());
1155 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length),
1156 stream_->GetTotalReceivedBytes());
[email protected]3e7dca62013-09-10 16:14:231157}
1158
rchf9f103cbc2014-08-30 05:28:041159// Regression test for http://crbug.com/409101
1160TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendRequest) {
1161 SetRequest("GET", "/", DEFAULT_PRIORITY);
1162 Initialize();
1163
1164 request_.method = "GET";
rchcd379012017-04-12 21:53:321165 request_.url = GURL("https://www.example.org/");
rchf9f103cbc2014-08-30 05:28:041166
Ali Beyada0b1a1c2022-04-08 20:08:141167 stream_->RegisterRequest(&request_);
1168 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261169 net_log_with_source_,
1170 callback_.callback()));
rchf9f103cbc2014-08-30 05:28:041171
jri78ec06a2016-03-31 18:19:401172 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521173 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rchf9f103cbc2014-08-30 05:28:041174
1175 EXPECT_EQ(ERR_CONNECTION_CLOSED,
rjshaded5ced072015-12-18 19:26:021176 stream_->SendRequest(headers_, &response_, callback_.callback()));
sclittle1edeeb22015-09-02 20:46:101177
1178 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1179 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rchf9f103cbc2014-08-30 05:28:041180}
1181
rch03b7a202016-02-05 00:54:201182// Regression test for http://crbug.com/584441
1183TEST_P(QuicHttpStreamTest, GetSSLInfoAfterSessionClosed) {
1184 SetRequest("GET", "/", DEFAULT_PRIORITY);
1185 Initialize();
1186
1187 request_.method = "GET";
rchcd379012017-04-12 21:53:321188 request_.url = GURL("https://www.example.org/");
rch03b7a202016-02-05 00:54:201189
Ali Beyada0b1a1c2022-04-08 20:08:141190 stream_->RegisterRequest(&request_);
1191 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261192 net_log_with_source_,
1193 callback_.callback()));
rch03b7a202016-02-05 00:54:201194
1195 SSLInfo ssl_info;
rch11565e02016-02-09 20:13:471196 EXPECT_FALSE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:201197 stream_->GetSSLInfo(&ssl_info);
rch11565e02016-02-09 20:13:471198 EXPECT_TRUE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:201199
jri78ec06a2016-03-31 18:19:401200 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521201 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rch03b7a202016-02-05 00:54:201202
rch11565e02016-02-09 20:13:471203 SSLInfo ssl_info2;
1204 stream_->GetSSLInfo(&ssl_info2);
1205 EXPECT_TRUE(ssl_info2.is_valid());
rch03b7a202016-02-05 00:54:201206}
1207
rchcd379012017-04-12 21:53:321208TEST_P(QuicHttpStreamTest, GetAlternativeService) {
1209 SetRequest("GET", "/", DEFAULT_PRIORITY);
1210 Initialize();
1211
1212 request_.method = "GET";
1213 request_.url = GURL("https://www.example.org/");
1214
Ali Beyada0b1a1c2022-04-08 20:08:141215 stream_->RegisterRequest(&request_);
1216 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261217 net_log_with_source_,
1218 callback_.callback()));
rchcd379012017-04-12 21:53:321219
1220 AlternativeService alternative_service;
1221 EXPECT_TRUE(stream_->GetAlternativeService(&alternative_service));
1222 EXPECT_EQ(AlternativeService(kProtoQUIC, "www.example.org", 443),
1223 alternative_service);
1224
1225 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521226 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rchcd379012017-04-12 21:53:321227
1228 AlternativeService alternative_service2;
1229 EXPECT_TRUE(stream_->GetAlternativeService(&alternative_service2));
1230 EXPECT_EQ(AlternativeService(kProtoQUIC, "www.example.org", 443),
1231 alternative_service2);
1232}
1233
zhongyica364fbb2015-12-12 03:39:121234TEST_P(QuicHttpStreamTest, LogGranularQuicConnectionError) {
1235 SetRequest("GET", "/", DEFAULT_PRIORITY);
1236 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231237 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251238 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231239 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371240 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231241 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1242 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1243 &spdy_request_headers_frame_length));
fayang3bcb8b502016-12-07 21:44:371244 AddWrite(ConstructAckAndRstStreamPacket(3));
zhongyica364fbb2015-12-12 03:39:121245 Initialize();
1246
1247 request_.method = "GET";
rchcd379012017-04-12 21:53:321248 request_.url = GURL("https://www.example.org/");
zhongyica364fbb2015-12-12 03:39:121249
Ali Beyada0b1a1c2022-04-08 20:08:141250 stream_->RegisterRequest(&request_);
1251 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261252 net_log_with_source_,
1253 callback_.callback()));
zhongyica364fbb2015-12-12 03:39:121254 EXPECT_EQ(OK,
1255 stream_->SendRequest(headers_, &response_, callback_.callback()));
1256
1257 // Ack the request.
Renjie90e808e2019-01-24 07:24:041258 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011259 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1260 IsError(ERR_IO_PENDING));
zhongyica364fbb2015-12-12 03:39:121261
Ryan Hamilton8d9ee76e2018-05-29 23:52:521262 quic::QuicConnectionCloseFrame frame;
Zhongyi Shica576df2019-04-12 17:43:401263 frame.quic_error_code = quic::QUIC_PEER_GOING_AWAY;
rch1c5b74a2016-06-23 22:10:551264 session_->connection()->OnConnectionCloseFrame(frame);
zhongyica364fbb2015-12-12 03:39:121265
1266 NetErrorDetails details;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521267 EXPECT_EQ(quic::QUIC_NO_ERROR, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121268 stream_->PopulateNetErrorDetails(&details);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521269 EXPECT_EQ(quic::QUIC_PEER_GOING_AWAY, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121270}
1271
Ryan Hamiltone316e482017-08-17 02:48:531272TEST_P(QuicHttpStreamTest, LogGranularQuicErrorIfHandshakeNotConfirmed) {
rch617e0652017-04-26 17:57:511273 // By default the test setup defaults handshake to be confirmed. Manually set
1274 // it to be not confirmed.
rch617e0652017-04-26 17:57:511275 crypto_client_stream_factory_.set_handshake_mode(
Ryan Hamilton9835e662018-08-02 05:36:271276 MockCryptoClientStream::ZERO_RTT);
rch617e0652017-04-26 17:57:511277
zhongyica364fbb2015-12-12 03:39:121278 SetRequest("GET", "/", DEFAULT_PRIORITY);
1279 size_t spdy_request_headers_frame_length;
Michael Warres167db3e2019-03-01 21:38:031280 client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
Nick Harper057264a82019-09-12 23:33:491281 client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
1282 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251283 if (VersionUsesHttp3(version_.transport_version))
Nick Harper057264a82019-09-12 23:33:491284 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371285 AddWrite(InnerConstructRequestHeadersPacket(
Nick Harper057264a82019-09-12 23:33:491286 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1287 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1288 &spdy_request_headers_frame_length));
zhongyica364fbb2015-12-12 03:39:121289 Initialize();
1290
1291 request_.method = "GET";
rchcd379012017-04-12 21:53:321292 request_.url = GURL("https://www.example.org/");
zhongyica364fbb2015-12-12 03:39:121293
Ali Beyada0b1a1c2022-04-08 20:08:141294 stream_->RegisterRequest(&request_);
1295 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261296 net_log_with_source_,
1297 callback_.callback()));
zhongyica364fbb2015-12-12 03:39:121298 EXPECT_EQ(OK,
1299 stream_->SendRequest(headers_, &response_, callback_.callback()));
1300
1301 // Ack the request.
Renjie90e808e2019-01-24 07:24:041302 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011303 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1304 IsError(ERR_IO_PENDING));
zhongyica364fbb2015-12-12 03:39:121305
Ryan Hamilton8d9ee76e2018-05-29 23:52:521306 quic::QuicConnectionCloseFrame frame;
Zhongyi Shica576df2019-04-12 17:43:401307 frame.quic_error_code = quic::QUIC_PEER_GOING_AWAY;
rch1c5b74a2016-06-23 22:10:551308 session_->connection()->OnConnectionCloseFrame(frame);
zhongyica364fbb2015-12-12 03:39:121309
1310 NetErrorDetails details;
zhongyica364fbb2015-12-12 03:39:121311 stream_->PopulateNetErrorDetails(&details);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521312 EXPECT_EQ(quic::QUIC_PEER_GOING_AWAY, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121313}
1314
rch11a114a2014-09-04 23:41:591315// Regression test for http://crbug.com/409871
1316TEST_P(QuicHttpStreamTest, SessionClosedBeforeReadResponseHeaders) {
1317 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451318 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231319 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251320 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231321 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371322 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231323 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1324 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1325 &spdy_request_headers_frame_length));
rch11a114a2014-09-04 23:41:591326 Initialize();
1327
1328 request_.method = "GET";
rchcd379012017-04-12 21:53:321329 request_.url = GURL("https://www.example.org/");
rch11a114a2014-09-04 23:41:591330
Ali Beyada0b1a1c2022-04-08 20:08:141331 stream_->RegisterRequest(&request_);
1332 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261333 net_log_with_source_,
1334 callback_.callback()));
rch11a114a2014-09-04 23:41:591335
rjshaded5ced072015-12-18 19:26:021336 EXPECT_EQ(OK,
1337 stream_->SendRequest(headers_, &response_, callback_.callback()));
rch11a114a2014-09-04 23:41:591338
jri78ec06a2016-03-31 18:19:401339 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521340 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rch11a114a2014-09-04 23:41:591341
1342 EXPECT_NE(OK, stream_->ReadResponseHeaders(callback_.callback()));
sclittle1edeeb22015-09-02 20:46:101343
1344 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451345 // headers and payload.
1346 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1347 stream_->GetTotalSentBytes());
sclittle1edeeb22015-09-02 20:46:101348 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rch11a114a2014-09-04 23:41:591349}
1350
[email protected]1e960032013-12-20 19:00:201351TEST_P(QuicHttpStreamTest, SendPostRequest) {
1352 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451353 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231354 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251355 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231356 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Yixin Wange7ecc472018-03-06 19:00:251357
Victor Vasiliev076657c2019-03-12 02:46:431358 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:321359 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411360 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231361 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1362 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1363 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411364 } else {
1365 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231366 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1367 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1368 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411369 }
Yixin Wange7ecc472018-03-06 19:00:251370
Renjie Tangcd594f32020-07-11 20:18:341371 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]f702d572012-12-04 15:56:201372
1373 Initialize();
1374
danakjad1777e2016-04-16 00:56:421375 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:191376 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
ricea2deef682016-09-09 08:04:071377 kUploadData, strlen(kUploadData)));
rch97827ee2017-05-24 23:49:121378 upload_data_stream_ =
Jeremy Roman0579ed62017-08-29 15:56:191379 std::make_unique<ElementsUploadDataStream>(std::move(element_readers), 0);
[email protected]f702d572012-12-04 15:56:201380 request_.method = "POST";
rchcd379012017-04-12 21:53:321381 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121382 request_.upload_data_stream = upload_data_stream_.get();
Bence Békyd8a21fc32018-06-27 18:29:581383 ASSERT_THAT(request_.upload_data_stream->Init(CompletionOnceCallback(),
tfarina42834112016-09-22 13:38:201384 NetLogWithSource()),
1385 IsOk());
[email protected]f702d572012-12-04 15:56:201386
Ali Beyada0b1a1c2022-04-08 20:08:141387 stream_->RegisterRequest(&request_);
1388 EXPECT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261389 net_log_with_source_,
1390 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021391 EXPECT_EQ(OK,
1392 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:201393
1394 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041395 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]f702d572012-12-04 15:56:201396
1397 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281398 SetResponse("200", string());
sclittlec4dc1a32015-09-24 00:15:451399 size_t spdy_response_headers_frame_length;
1400 ProcessPacket(ConstructResponseHeadersPacket(
1401 2, !kFin, &spdy_response_headers_frame_length));
[email protected]f702d572012-12-04 15:56:201402
rchfb47f712017-05-21 03:24:001403 // The headers have already arrived.
1404 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]cadac622013-06-11 16:46:361405 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:201406 EXPECT_EQ(200, response_.headers->response_code());
1407 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1408
1409 // Send the response body.
1410 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431411 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:411412 ProcessPacket(
Ryan Hamilton7505eb92019-06-08 00:22:171413 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
[email protected]f702d572012-12-04 15:56:201414 // Since the body has already arrived, this should return immediately.
1415 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
1416 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1417 callback_.callback()));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291418 EXPECT_EQ(0,
1419 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1420 callback_.callback()));
1421
1422 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1423 EXPECT_TRUE(AtEof());
1424
1425 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
1426 // headers and payload.
1427 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411428 strlen(kUploadData) + header.length()),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291429 stream_->GetTotalSentBytes());
1430 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411431 strlen(kResponseBody) + header2.length()),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291432 stream_->GetTotalReceivedBytes());
1433}
1434
1435TEST_P(QuicHttpStreamTest, SendPostRequestAndReceiveSoloFin) {
1436 SetRequest("POST", "/", DEFAULT_PRIORITY);
1437 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231438 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251439 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231440 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431441 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:321442 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411443 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231444 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1445 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1446 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411447 } else {
1448 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231449 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1450 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1451 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411452 }
1453
Renjie Tangcd594f32020-07-11 20:18:341454 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291455
1456 Initialize();
1457
1458 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:191459 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
Ryan Hamilton2ef0a9c2017-07-25 03:18:291460 kUploadData, strlen(kUploadData)));
1461 upload_data_stream_ =
Jeremy Roman0579ed62017-08-29 15:56:191462 std::make_unique<ElementsUploadDataStream>(std::move(element_readers), 0);
Ryan Hamilton2ef0a9c2017-07-25 03:18:291463 request_.method = "POST";
1464 request_.url = GURL("https://www.example.org/");
1465 request_.upload_data_stream = upload_data_stream_.get();
Bence Békyd8a21fc32018-06-27 18:29:581466 ASSERT_THAT(request_.upload_data_stream->Init(CompletionOnceCallback(),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291467 NetLogWithSource()),
1468 IsOk());
1469
Ali Beyada0b1a1c2022-04-08 20:08:141470 stream_->RegisterRequest(&request_);
1471 EXPECT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261472 net_log_with_source_,
1473 callback_.callback()));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291474 EXPECT_EQ(OK,
1475 stream_->SendRequest(headers_, &response_, callback_.callback()));
1476
1477 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041478 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291479
1480 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281481 SetResponse("200", string());
Ryan Hamilton2ef0a9c2017-07-25 03:18:291482 size_t spdy_response_headers_frame_length;
1483 ProcessPacket(ConstructResponseHeadersPacket(
1484 2, !kFin, &spdy_response_headers_frame_length));
1485
1486 // The headers have already arrived.
1487 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
1488 ASSERT_TRUE(response_.headers.get());
1489 EXPECT_EQ(200, response_.headers->response_code());
1490 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1491
1492 // Send the response body.
1493 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431494 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:411495 ProcessPacket(
Ryan Hamilton7505eb92019-06-08 00:22:171496 ConstructServerDataPacket(3, false, !kFin, header2 + kResponseBody));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291497 // Since the body has already arrived, this should return immediately.
1498 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
1499 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1500 callback_.callback()));
Ryan Hamilton7505eb92019-06-08 00:22:171501 ProcessPacket(ConstructServerDataPacket(4, false, kFin, ""));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291502 EXPECT_EQ(0,
1503 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1504 callback_.callback()));
[email protected]f702d572012-12-04 15:56:201505
1506 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1507 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101508
1509 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451510 // headers and payload.
1511 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411512 strlen(kUploadData) + header.length()),
sclittle1edeeb22015-09-02 20:46:101513 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451514 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411515 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101516 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:201517}
1518
[email protected]1e960032013-12-20 19:00:201519TEST_P(QuicHttpStreamTest, SendChunkedPostRequest) {
1520 SetRequest("POST", "/", DEFAULT_PRIORITY);
[email protected]c9e49a02013-02-26 05:56:471521 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:451522 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231523 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251524 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231525 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431526 std::string header = ConstructDataHeader(chunk_size);
Nick Harperc6cb7a612020-02-24 20:03:321527 if (version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411528 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231529 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1530 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1531 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjie Tangd5133972019-12-06 00:20:281532 AddWrite(ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin,
1533 {header + kUploadData}));
Renjief49758b2019-01-11 23:32:411534 } else {
1535 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231536 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1537 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1538 &spdy_request_headers_frame_length, {kUploadData}));
1539 AddWrite(ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin,
1540 kUploadData));
Renjief49758b2019-01-11 23:32:411541 }
1542
Renjie Tangcd594f32020-07-11 20:18:341543 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]c9e49a02013-02-26 05:56:471544 Initialize();
1545
Jeremy Roman0579ed62017-08-29 15:56:191546 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121547 auto* chunked_upload_stream =
1548 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1549 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
[email protected]c9e49a02013-02-26 05:56:471550
1551 request_.method = "POST";
rchcd379012017-04-12 21:53:321552 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121553 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071554 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201555 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]c9e49a02013-02-26 05:56:471556
Ali Beyada0b1a1c2022-04-08 20:08:141557 stream_->RegisterRequest(&request_);
1558 ASSERT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261559 net_log_with_source_,
1560 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021561 ASSERT_EQ(ERR_IO_PENDING,
1562 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]c9e49a02013-02-26 05:56:471563
rch97827ee2017-05-24 23:49:121564 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
robpercival214763f2016-07-01 23:27:011565 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]c9e49a02013-02-26 05:56:471566
1567 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041568 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]c9e49a02013-02-26 05:56:471569
1570 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281571 SetResponse("200", string());
sclittlec4dc1a32015-09-24 00:15:451572 size_t spdy_response_headers_frame_length;
1573 ProcessPacket(ConstructResponseHeadersPacket(
1574 2, !kFin, &spdy_response_headers_frame_length));
[email protected]c9e49a02013-02-26 05:56:471575
rchfb47f712017-05-21 03:24:001576 // The headers have already arrived.
1577 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]cadac622013-06-11 16:46:361578 ASSERT_TRUE(response_.headers.get());
[email protected]c9e49a02013-02-26 05:56:471579 EXPECT_EQ(200, response_.headers->response_code());
1580 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1581
1582 // Send the response body.
1583 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431584 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171585 ProcessPacket(
1586 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
[email protected]c9e49a02013-02-26 05:56:471587
1588 // Since the body has already arrived, this should return immediately.
1589 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1590 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1591 callback_.callback()));
1592
1593 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1594 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101595
1596 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451597 // headers and payload.
1598 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411599 strlen(kUploadData) * 2 + header.length() * 2),
sclittle1edeeb22015-09-02 20:46:101600 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451601 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411602 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101603 stream_->GetTotalReceivedBytes());
[email protected]c9e49a02013-02-26 05:56:471604}
1605
[email protected]16ba7742014-08-22 00:57:251606TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithFinalEmptyDataPacket) {
1607 SetRequest("POST", "/", DEFAULT_PRIORITY);
1608 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:451609 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231610 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251611 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231612 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431613 std::string header = ConstructDataHeader(chunk_size);
Renjief49758b2019-01-11 23:32:411614
Nick Harperc6cb7a612020-02-24 20:03:321615 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411616 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231617 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1618 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1619 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411620 } else {
1621 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231622 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1623 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1624 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411625 }
Renjie Tangaadb84b2019-08-31 01:00:231626 AddWrite(
1627 ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin, ""));
Renjie Tangcd594f32020-07-11 20:18:341628 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]16ba7742014-08-22 00:57:251629 Initialize();
1630
Jeremy Roman0579ed62017-08-29 15:56:191631 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121632 auto* chunked_upload_stream =
1633 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1634 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
[email protected]16ba7742014-08-22 00:57:251635
1636 request_.method = "POST";
rchcd379012017-04-12 21:53:321637 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121638 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071639 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201640 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]16ba7742014-08-22 00:57:251641
Ali Beyada0b1a1c2022-04-08 20:08:141642 stream_->RegisterRequest(&request_);
1643 ASSERT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261644 net_log_with_source_,
1645 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021646 ASSERT_EQ(ERR_IO_PENDING,
1647 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251648
rch97827ee2017-05-24 23:49:121649 chunked_upload_stream->AppendData(nullptr, 0, true);
robpercival214763f2016-07-01 23:27:011650 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]16ba7742014-08-22 00:57:251651
Renjie90e808e2019-01-24 07:24:041652 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]16ba7742014-08-22 00:57:251653
1654 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281655 SetResponse("200", string());
sclittlec4dc1a32015-09-24 00:15:451656 size_t spdy_response_headers_frame_length;
1657 ProcessPacket(ConstructResponseHeadersPacket(
1658 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251659
rchfb47f712017-05-21 03:24:001660 // The headers have already arrived.
1661 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]16ba7742014-08-22 00:57:251662 ASSERT_TRUE(response_.headers.get());
1663 EXPECT_EQ(200, response_.headers->response_code());
1664 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1665
1666 // Send the response body.
1667 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431668 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171669 ProcessPacket(
1670 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
[email protected]16ba7742014-08-22 00:57:251671
rchb27683c2015-07-29 23:53:501672 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251673 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1674 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1675 callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251676 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1677 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101678
1679 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451680 // headers and payload.
1681 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411682 strlen(kUploadData) + header.length()),
sclittle1edeeb22015-09-02 20:46:101683 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451684 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411685 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101686 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251687}
1688
1689TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithOneEmptyDataPacket) {
1690 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451691 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231692 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251693 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231694 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371695 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231696 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1697 kIncludeVersion, !kFin, DEFAULT_PRIORITY,
1698 &spdy_request_headers_frame_length));
1699 AddWrite(
1700 ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin, ""));
Renjie Tangcd594f32020-07-11 20:18:341701 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]16ba7742014-08-22 00:57:251702 Initialize();
1703
Jeremy Roman0579ed62017-08-29 15:56:191704 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121705 auto* chunked_upload_stream =
1706 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
[email protected]16ba7742014-08-22 00:57:251707
1708 request_.method = "POST";
rchcd379012017-04-12 21:53:321709 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121710 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071711 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201712 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]16ba7742014-08-22 00:57:251713
Ali Beyada0b1a1c2022-04-08 20:08:141714 stream_->RegisterRequest(&request_);
1715 ASSERT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261716 net_log_with_source_,
1717 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021718 ASSERT_EQ(ERR_IO_PENDING,
1719 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251720
rch97827ee2017-05-24 23:49:121721 chunked_upload_stream->AppendData(nullptr, 0, true);
robpercival214763f2016-07-01 23:27:011722 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]16ba7742014-08-22 00:57:251723
Renjie90e808e2019-01-24 07:24:041724 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]16ba7742014-08-22 00:57:251725
1726 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281727 SetResponse("200", string());
sclittlec4dc1a32015-09-24 00:15:451728 size_t spdy_response_headers_frame_length;
1729 ProcessPacket(ConstructResponseHeadersPacket(
1730 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251731
rchfb47f712017-05-21 03:24:001732 // The headers have already arrived.
1733 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]16ba7742014-08-22 00:57:251734 ASSERT_TRUE(response_.headers.get());
1735 EXPECT_EQ(200, response_.headers->response_code());
1736 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1737
1738 // Send the response body.
1739 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431740 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171741 ProcessPacket(
1742 ConstructServerDataPacket(3, false, kFin, header + kResponseBody));
[email protected]16ba7742014-08-22 00:57:251743
rchb27683c2015-07-29 23:53:501744 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251745 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1746 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1747 callback_.callback()));
1748
1749 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1750 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101751
1752 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451753 // headers and payload.
1754 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1755 stream_->GetTotalSentBytes());
1756 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411757 strlen(kResponseBody) + header.length()),
sclittle1edeeb22015-09-02 20:46:101758 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251759}
1760
Bence Békye3c6f122020-05-08 01:09:471761TEST_P(QuicHttpStreamTest, SendChunkedPostRequestAbortedByResetStream) {
1762 SetRequest("POST", "/", DEFAULT_PRIORITY);
1763 size_t chunk_size = strlen(kUploadData);
1764 size_t spdy_request_headers_frame_length;
1765 int packet_number = 1;
1766
1767 if (version_.UsesHttp3()) {
1768 AddWrite(ConstructInitialSettingsPacket(packet_number++));
1769 }
1770
1771 std::string header = ConstructDataHeader(chunk_size);
1772 if (version_.HasIetfQuicFrames()) {
1773 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1774 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1775 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1776 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjie Tangcd594f32020-07-11 20:18:341777 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
Fan Yang8d4177792021-07-16 17:48:531778 AddWrite(client_maker_.MakeAckAndRstPacket(
1779 packet_number++, true, stream_id_, quic::QUIC_STREAM_NO_ERROR, 4, 1,
Renjie Tangcd594f32020-07-11 20:18:341780 /* include_stop_sending_if_v99 = */ false));
Bence Békye3c6f122020-05-08 01:09:471781 } else {
1782 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1783 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1784 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1785 &spdy_request_headers_frame_length, {kUploadData}));
Renjie Tangcd594f32020-07-11 20:18:341786 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
Bence Békye3c6f122020-05-08 01:09:471787 AddWrite(client_maker_.MakeAckAndRstPacket(
1788 packet_number++,
1789 /* include_version = */ false, stream_id_,
Renjie Tangcd594f32020-07-11 20:18:341790 quic::QUIC_RST_ACKNOWLEDGEMENT, 4, 1,
Bence Békye3c6f122020-05-08 01:09:471791 /* include_stop_sending_if_v99 = */ false));
1792 }
1793
1794 Initialize();
1795
1796 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
1797 auto* chunked_upload_stream =
1798 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1799 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
1800
1801 request_.method = "POST";
1802 request_.url = GURL("https://www.example.org/");
1803 request_.upload_data_stream = upload_data_stream_.get();
1804 ASSERT_THAT(request_.upload_data_stream->Init(
1805 TestCompletionCallback().callback(), NetLogWithSource()),
1806 IsOk());
Ali Beyada0b1a1c2022-04-08 20:08:141807 stream_->RegisterRequest(&request_);
Matt Reichhoff0049a0b72021-10-20 20:44:261808 ASSERT_THAT(
Ali Beyada0b1a1c2022-04-08 20:08:141809 stream_->InitializeStream(false, DEFAULT_PRIORITY, net_log_with_source_,
1810 callback_.callback()),
Matt Reichhoff0049a0b72021-10-20 20:44:261811 IsOk());
Bence Békye3c6f122020-05-08 01:09:471812 ASSERT_THAT(stream_->SendRequest(headers_, &response_, callback_.callback()),
1813 IsError(ERR_IO_PENDING));
1814
1815 // Ack both packets in the request.
1816 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
1817
1818 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281819 SetResponse("200", string());
Bence Békye3c6f122020-05-08 01:09:471820 size_t spdy_response_headers_frame_length;
1821 ProcessPacket(ConstructResponseHeadersPacket(
1822 2, !kFin, &spdy_response_headers_frame_length));
1823
1824 // Send the response body.
1825 const char kResponseBody[] = "Hello world!";
1826 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
1827 ProcessPacket(
1828 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
1829
Bence Béky050ec6d2021-02-25 22:07:051830 if (version_.HasIetfQuicFrames()) {
1831 // In IETF QUIC, the server uses a STOP_SENDING frame to notify the client
1832 // that it does not need any further data to fully process the request.
1833 ProcessPacket(server_maker_.MakeStopSendingPacket(
1834 4, /* include_version = */ false, stream_id_,
1835 quic::QUIC_STREAM_NO_ERROR));
1836 } else {
1837 // Server resets stream with H3_NO_ERROR before request body is complete.
1838 ProcessPacket(server_maker_.MakeRstPacket(4, /* include_version = */ false,
1839 stream_id_,
1840 quic::QUIC_STREAM_NO_ERROR));
1841 }
Bence Békye3c6f122020-05-08 01:09:471842
1843 // Finish feeding request body to QuicHttpStream. Data will be discarded.
1844 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1845 EXPECT_THAT(callback_.WaitForResult(), IsOk());
1846
1847 // Verify response.
1848 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
1849 ASSERT_TRUE(response_.headers.get());
1850 EXPECT_EQ(200, response_.headers->response_code());
1851 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1852 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1853 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1854 callback_.callback()));
1855 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1856 EXPECT_TRUE(AtEof());
1857
1858 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
1859 // headers and payload.
1860 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
1861 strlen(kUploadData) + header.length()),
1862 stream_->GetTotalSentBytes());
1863 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1864 strlen(kResponseBody) + header2.length()),
1865 stream_->GetTotalReceivedBytes());
1866}
1867
[email protected]1e960032013-12-20 19:00:201868TEST_P(QuicHttpStreamTest, DestroyedEarly) {
1869 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451870 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231871 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251872 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231873 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371874 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231875 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1876 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1877 &spdy_request_headers_frame_length));
1878 AddWrite(ConstructAckAndRstStreamPacket(packet_number++));
[email protected]63534512012-12-23 18:49:001879 Initialize();
1880
1881 request_.method = "GET";
rchcd379012017-04-12 21:53:321882 request_.url = GURL("https://www.example.org/");
[email protected]63534512012-12-23 18:49:001883
Ali Beyada0b1a1c2022-04-08 20:08:141884 stream_->RegisterRequest(&request_);
1885 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261886 net_log_with_source_,
1887 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021888 EXPECT_EQ(OK,
1889 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]63534512012-12-23 18:49:001890
1891 // Ack the request.
Renjie90e808e2019-01-24 07:24:041892 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
rchfb47f712017-05-21 03:24:001893 EXPECT_THAT(stream_->ReadResponseHeaders(
Yannic Bonenberger3c96beb2019-09-03 20:41:371894 base::BindOnce(&QuicHttpStreamTest::CloseStream,
1895 base::Unretained(this), stream_.get())),
robpercival214763f2016-07-01 23:27:011896 IsError(ERR_IO_PENDING));
[email protected]63534512012-12-23 18:49:001897
1898 // Send the response with a body.
Kenichi Ishibashif8634ab2021-03-16 23:41:281899 SetResponse("404", "hello world!");
[email protected]63534512012-12-23 18:49:001900 // In the course of processing this packet, the QuicHttpStream close itself.
rchfb47f712017-05-21 03:24:001901 size_t response_size = 0;
rch1bcfddf22017-06-03 00:26:291902 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin, &response_size));
[email protected]63534512012-12-23 18:49:001903
fdoray92e35a72016-06-10 15:54:551904 base::RunLoop().RunUntilIdle();
rchb27683c2015-07-29 23:53:501905
[email protected]63534512012-12-23 18:49:001906 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101907
1908 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451909 // headers and payload.
1910 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1911 stream_->GetTotalSentBytes());
rchfb47f712017-05-21 03:24:001912 // The stream was closed after receiving the headers.
1913 EXPECT_EQ(static_cast<int64_t>(response_size),
1914 stream_->GetTotalReceivedBytes());
[email protected]63534512012-12-23 18:49:001915}
1916
[email protected]1e960032013-12-20 19:00:201917TEST_P(QuicHttpStreamTest, Priority) {
1918 SetRequest("GET", "/", MEDIUM);
sclittlec4dc1a32015-09-24 00:15:451919 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231920 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251921 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231922 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371923 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231924 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1925 kIncludeVersion, kFin, MEDIUM, &spdy_request_headers_frame_length));
[email protected]24e5bc52013-09-18 15:36:581926 Initialize();
1927
1928 request_.method = "GET";
rchcd379012017-04-12 21:53:321929 request_.url = GURL("https://www.example.org/");
[email protected]24e5bc52013-09-18 15:36:581930
Ali Beyada0b1a1c2022-04-08 20:08:141931 stream_->RegisterRequest(&request_);
1932 EXPECT_EQ(OK, stream_->InitializeStream(true, MEDIUM, net_log_with_source_,
Matt Reichhoff0049a0b72021-10-20 20:44:261933 callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581934
rjshaded5ced072015-12-18 19:26:021935 EXPECT_EQ(OK,
1936 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581937
[email protected]24e5bc52013-09-18 15:36:581938 // Ack the request.
Renjie90e808e2019-01-24 07:24:041939 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011940 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1941 IsError(ERR_IO_PENDING));
[email protected]24e5bc52013-09-18 15:36:581942
1943 // Send the response with a body.
Kenichi Ishibashif8634ab2021-03-16 23:41:281944 SetResponse("404", "hello world!");
rchfb47f712017-05-21 03:24:001945 size_t response_size = 0;
1946 ProcessPacket(ConstructResponseHeadersPacket(2, kFin, &response_size));
[email protected]24e5bc52013-09-18 15:36:581947
rchfb47f712017-05-21 03:24:001948 EXPECT_EQ(OK, callback_.WaitForResult());
rchb27683c2015-07-29 23:53:501949
[email protected]24e5bc52013-09-18 15:36:581950 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101951
1952 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451953 // headers and payload.
1954 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1955 stream_->GetTotalSentBytes());
rchfb47f712017-05-21 03:24:001956 EXPECT_EQ(static_cast<int64_t>(response_size),
1957 stream_->GetTotalReceivedBytes());
[email protected]24e5bc52013-09-18 15:36:581958}
1959
xunjieli8dff50b2016-07-22 14:19:061960TEST_P(QuicHttpStreamTest, SessionClosedDuringDoLoop) {
1961 SetRequest("POST", "/", DEFAULT_PRIORITY);
1962 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231963 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251964 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231965 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431966 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:321967 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411968 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231969 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1970 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1971 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411972 } else {
1973 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231974 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1975 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1976 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411977 }
1978
xunjieli8dff50b2016-07-22 14:19:061979 // Second data write will result in a synchronous failure which will close
1980 // the session.
1981 AddWrite(SYNCHRONOUS, ERR_FAILED);
1982 Initialize();
1983
Jeremy Roman0579ed62017-08-29 15:56:191984 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121985 auto* chunked_upload_stream =
1986 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
xunjieli8dff50b2016-07-22 14:19:061987
1988 request_.method = "POST";
rchcd379012017-04-12 21:53:321989 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121990 request_.upload_data_stream = upload_data_stream_.get();
xunjieli8dff50b2016-07-22 14:19:061991 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201992 TestCompletionCallback().callback(), NetLogWithSource()));
xunjieli8dff50b2016-07-22 14:19:061993
1994 size_t chunk_size = strlen(kUploadData);
rch97827ee2017-05-24 23:49:121995 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
Ali Beyada0b1a1c2022-04-08 20:08:141996 stream_->RegisterRequest(&request_);
1997 ASSERT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261998 net_log_with_source_,
1999 callback_.callback()));
xunjieli8dff50b2016-07-22 14:19:062000 QuicHttpStream* stream = stream_.get();
2001 DeleteStreamCallback delete_stream_callback(std::move(stream_));
2002 // SendRequest() completes asynchronously after the final chunk is added.
Yixin Wange7ecc472018-03-06 19:00:252003 // Error does not surface yet since packet write is triggered by a packet
2004 // flusher that tries to bundle request body writes.
xunjieli8dff50b2016-07-22 14:19:062005 ASSERT_EQ(ERR_IO_PENDING,
2006 stream->SendRequest(headers_, &response_, callback_.callback()));
rch97827ee2017-05-24 23:49:122007 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
xunjieli8dff50b2016-07-22 14:19:062008 int rv = callback_.WaitForResult();
Yixin Wange7ecc472018-03-06 19:00:252009 EXPECT_EQ(OK, rv);
2010 // Error will be surfaced once an attempt to read the response occurs.
2011 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
2012 stream->ReadResponseHeaders(callback_.callback()));
xunjieli8dff50b2016-07-22 14:19:062013}
2014
rtenneti15656ae2016-01-23 03:05:032015TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersComplete) {
2016 SetRequest("POST", "/", DEFAULT_PRIORITY);
Victor Vasiliev7da08172019-10-14 06:04:252017 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232018 AddWrite(ConstructInitialSettingsPacket());
rtenneti15656ae2016-01-23 03:05:032019 AddWrite(SYNCHRONOUS, ERR_FAILED);
2020 Initialize();
2021
Jeremy Roman0579ed62017-08-29 15:56:192022 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
Yixin Wange7ecc472018-03-06 19:00:252023 auto* chunked_upload_stream =
2024 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
rtenneti15656ae2016-01-23 03:05:032025
2026 request_.method = "POST";
rchcd379012017-04-12 21:53:322027 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122028 request_.upload_data_stream = upload_data_stream_.get();
rtenneti15656ae2016-01-23 03:05:032029 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202030 TestCompletionCallback().callback(), NetLogWithSource()));
rtenneti15656ae2016-01-23 03:05:032031
Ali Beyada0b1a1c2022-04-08 20:08:142032 stream_->RegisterRequest(&request_);
2033 ASSERT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262034 net_log_with_source_,
2035 callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252036 ASSERT_EQ(ERR_IO_PENDING,
rtenneti15656ae2016-01-23 03:05:032037 stream_->SendRequest(headers_, &response_, callback_.callback()));
mmenkeffff3642017-06-15 17:37:242038
Yixin Wange7ecc472018-03-06 19:00:252039 // Error will be surfaced once |upload_data_stream| triggers the next write.
2040 size_t chunk_size = strlen(kUploadData);
2041 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2042 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR, callback_.WaitForResult());
2043
2044 EXPECT_LE(0, stream_->GetTotalSentBytes());
2045 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2046}
2047
2048TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersCompleteReadResponse) {
2049 SetRequest("POST", "/", DEFAULT_PRIORITY);
Victor Vasiliev7da08172019-10-14 06:04:252050 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232051 AddWrite(ConstructInitialSettingsPacket());
Yixin Wange7ecc472018-03-06 19:00:252052 AddWrite(SYNCHRONOUS, ERR_FAILED);
2053 Initialize();
2054
2055 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
2056 auto* chunked_upload_stream =
2057 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
2058
2059 request_.method = "POST";
2060 request_.url = GURL("https://www.example.org/");
2061 request_.upload_data_stream = upload_data_stream_.get();
2062
2063 size_t chunk_size = strlen(kUploadData);
2064 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2065
2066 ASSERT_EQ(OK, request_.upload_data_stream->Init(
2067 TestCompletionCallback().callback(), NetLogWithSource()));
2068
Ali Beyada0b1a1c2022-04-08 20:08:142069 stream_->RegisterRequest(&request_);
2070 ASSERT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262071 net_log_with_source_,
2072 callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252073 ASSERT_EQ(OK,
2074 stream_->SendRequest(headers_, &response_, callback_.callback()));
2075
2076 // Error will be surfaced once an attempt to read the response occurs.
2077 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
2078 stream_->ReadResponseHeaders(callback_.callback()));
2079
mmenkeffff3642017-06-15 17:37:242080 EXPECT_LE(0, stream_->GetTotalSentBytes());
2081 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rtenneti15656ae2016-01-23 03:05:032082}
2083
2084TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBodyComplete) {
2085 SetRequest("POST", "/", DEFAULT_PRIORITY);
2086 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232087 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252088 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232089 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:372090 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:232091 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2092 kIncludeVersion, !kFin, DEFAULT_PRIORITY,
2093 &spdy_request_headers_frame_length));
rtenneti15656ae2016-01-23 03:05:032094 AddWrite(SYNCHRONOUS, ERR_FAILED);
2095 Initialize();
2096
Jeremy Roman0579ed62017-08-29 15:56:192097 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:122098 auto* chunked_upload_stream =
2099 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
rtenneti15656ae2016-01-23 03:05:032100
2101 request_.method = "POST";
rchcd379012017-04-12 21:53:322102 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122103 request_.upload_data_stream = upload_data_stream_.get();
rtenneti15656ae2016-01-23 03:05:032104 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202105 TestCompletionCallback().callback(), NetLogWithSource()));
rtenneti15656ae2016-01-23 03:05:032106
Ali Beyada0b1a1c2022-04-08 20:08:142107 stream_->RegisterRequest(&request_);
2108 ASSERT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262109 net_log_with_source_,
2110 callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252111 ASSERT_EQ(ERR_IO_PENDING,
rtenneti15656ae2016-01-23 03:05:032112 stream_->SendRequest(headers_, &response_, callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252113
2114 size_t chunk_size = strlen(kUploadData);
2115 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2116 // Error does not surface yet since packet write is triggered by a packet
2117 // flusher that tries to bundle request body writes.
2118 ASSERT_EQ(OK, callback_.WaitForResult());
2119 // Error will be surfaced once an attempt to read the response occurs.
2120 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
2121 stream_->ReadResponseHeaders(callback_.callback()));
2122
2123 EXPECT_LE(0, stream_->GetTotalSentBytes());
2124 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2125}
2126
2127TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBundledBodyComplete) {
2128 SetRequest("POST", "/", DEFAULT_PRIORITY);
2129 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232130 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252131 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232132 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:432133 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:322134 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:412135 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:232136 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2137 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
2138 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:412139 } else {
2140 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:232141 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2142 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
2143 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:412144 }
2145
Yixin Wange7ecc472018-03-06 19:00:252146 AddWrite(SYNCHRONOUS, ERR_FAILED);
2147 Initialize();
2148
2149 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
2150 auto* chunked_upload_stream =
2151 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
2152
2153 request_.method = "POST";
2154 request_.url = GURL("https://www.example.org/");
2155 request_.upload_data_stream = upload_data_stream_.get();
2156
2157 size_t chunk_size = strlen(kUploadData);
2158 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
2159
2160 ASSERT_EQ(OK, request_.upload_data_stream->Init(
2161 TestCompletionCallback().callback(), NetLogWithSource()));
2162
Ali Beyada0b1a1c2022-04-08 20:08:142163 stream_->RegisterRequest(&request_);
2164 ASSERT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262165 net_log_with_source_,
2166 callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252167 ASSERT_EQ(ERR_IO_PENDING,
2168 stream_->SendRequest(headers_, &response_, callback_.callback()));
2169
2170 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2171
2172 // Error does not surface yet since packet write is triggered by a packet
2173 // flusher that tries to bundle request body writes.
2174 ASSERT_EQ(OK, callback_.WaitForResult());
2175 // Error will be surfaced once an attempt to read the response occurs.
2176 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
2177 stream_->ReadResponseHeaders(callback_.callback()));
2178
2179 EXPECT_LE(0, stream_->GetTotalSentBytes());
2180 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rtenneti15656ae2016-01-23 03:05:032181}
2182
ckrasic3865ee0f2016-02-29 22:04:562183TEST_P(QuicHttpStreamTest, ServerPushGetRequest) {
2184 SetRequest("GET", "/", DEFAULT_PRIORITY);
2185 Initialize();
2186
Bin Wue8408792021-08-24 23:25:162187 // Server push is not supported in HTTP/3.
2188 if (version_.UsesHttp3())
2189 return;
2190
ckrasic3865ee0f2016-02-29 22:04:562191 // Initialize the first stream, for receiving the promise on.
2192 request_.method = "GET";
rchcd379012017-04-12 21:53:322193 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562194
Ali Beyada0b1a1c2022-04-08 20:08:142195 stream_->RegisterRequest(&request_);
2196 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262197 net_log_with_source_,
2198 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232199 ASSERT_EQ(OK,
2200 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562201
2202 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2203 // packet, but does it matter?
2204 ReceivePromise(promise_id_);
2205 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2206
2207 request_.url = GURL(promise_url_);
2208
2209 // Make the second stream that will exercise the first step of the
2210 // server push rendezvous mechanism.
Ali Beyada0b1a1c2022-04-08 20:08:142211 promised_stream_->RegisterRequest(&request_);
2212 EXPECT_EQ(OK, promised_stream_->InitializeStream(true, DEFAULT_PRIORITY,
2213 net_log_with_source_,
2214 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562215
2216 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252217 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562218 size_t spdy_response_headers_frame_length;
2219 ProcessPacket(InnerConstructResponseHeadersPacket(
2220 1, promise_id_, false, &spdy_response_headers_frame_length));
2221
2222 // Receive the promised response body.
2223 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432224 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172225 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2226 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562227
2228 // Now sending a matching request will have successful rendezvous
2229 // with the promised stream.
Ryan Hamiltona1d1f4a2019-06-26 14:43:042230 ASSERT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
ckrasic3865ee0f2016-02-29 22:04:562231 callback_.callback()));
2232
2233 EXPECT_EQ(
2234 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2235 ->id(),
2236 promise_id_);
2237
2238 // The headers will be immediately available.
robpercival214763f2016-07-01 23:27:012239 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2240 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562241
2242 // As will be the body.
2243 EXPECT_EQ(
2244 static_cast<int>(strlen(kResponseBody)),
2245 promised_stream_->ReadResponseBody(
2246 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2247 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2248 EXPECT_TRUE(AtEof());
2249
ckrasic3865ee0f2016-02-29 22:04:562250 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2251 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412252 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562253 promised_stream_->GetTotalReceivedBytes());
2254}
2255
2256TEST_P(QuicHttpStreamTest, ServerPushGetRequestSlowResponse) {
2257 SetRequest("GET", "/", DEFAULT_PRIORITY);
2258 Initialize();
2259
Bin Wue8408792021-08-24 23:25:162260 // Server push is not supported in HTTP/3.
2261 if (version_.UsesHttp3())
2262 return;
2263
ckrasic3865ee0f2016-02-29 22:04:562264 // Initialize the first stream, for receiving the promise on.
2265 request_.method = "GET";
rchcd379012017-04-12 21:53:322266 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562267
Ali Beyada0b1a1c2022-04-08 20:08:142268 stream_->RegisterRequest(&request_);
2269 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262270 net_log_with_source_,
2271 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232272 ASSERT_EQ(OK,
2273 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562274
2275 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2276 // packet, but does it matter?
2277 ReceivePromise(promise_id_);
2278 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2279
2280 request_.url = GURL(promise_url_);
2281
2282 // Make the second stream that will exercise the first step of the
2283 // server push rendezvous mechanism.
Ali Beyada0b1a1c2022-04-08 20:08:142284 promised_stream_->RegisterRequest(&request_);
2285 EXPECT_EQ(OK, promised_stream_->InitializeStream(true, DEFAULT_PRIORITY,
2286 net_log_with_source_,
2287 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562288
2289 // Now sending a matching request will rendezvous with the promised
2290 // stream, but pending secondary validation.
2291 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2292 headers_, &response_, callback_.callback()));
2293
2294 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252295 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562296 size_t spdy_response_headers_frame_length;
2297 ProcessPacket(InnerConstructResponseHeadersPacket(
2298 1, promise_id_, false, &spdy_response_headers_frame_length));
2299
2300 // Receive the promised response body.
2301 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432302 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172303 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2304 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562305
fdoray92e35a72016-06-10 15:54:552306 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562307
2308 // Rendezvous should have succeeded now, so the promised stream
2309 // should point at our push stream, and we should be able read
2310 // headers and data from it.
robpercival214763f2016-07-01 23:27:012311 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562312
2313 EXPECT_EQ(
2314 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2315 ->id(),
2316 promise_id_);
2317
robpercival214763f2016-07-01 23:27:012318 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2319 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562320
2321 EXPECT_EQ(
2322 static_cast<int>(strlen(kResponseBody)),
2323 promised_stream_->ReadResponseBody(
2324 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2325
2326 // Callback should return
2327 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2328 EXPECT_TRUE(AtEof());
2329
ckrasic3865ee0f2016-02-29 22:04:562330 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2331 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412332 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562333 promised_stream_->GetTotalReceivedBytes());
2334}
2335
ckrasic2c63f9b2016-08-16 23:54:072336// Verify fix for crbug.com/637349
2337TEST_P(QuicHttpStreamTest, ServerPushCancelHttpStreamBeforeResponse) {
2338 SetRequest("GET", "/", DEFAULT_PRIORITY);
2339 Initialize();
2340
Bin Wue8408792021-08-24 23:25:162341 // Server push is not supported in HTTP/3.
2342 if (version_.UsesHttp3())
2343 return;
2344
ckrasic2c63f9b2016-08-16 23:54:072345 // Initialize the first stream, for receiving the promise on.
2346 request_.method = "GET";
rchcd379012017-04-12 21:53:322347 request_.url = GURL("https://www.example.org/");
ckrasic2c63f9b2016-08-16 23:54:072348
Ali Beyada0b1a1c2022-04-08 20:08:142349 stream_->RegisterRequest(&request_);
2350 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262351 net_log_with_source_,
2352 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232353 ASSERT_EQ(OK,
2354 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic2c63f9b2016-08-16 23:54:072355
2356 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2357 // packet, but does it matter?
2358 ReceivePromise(promise_id_);
2359 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2360
2361 request_.url = GURL(promise_url_);
2362
2363 // Make the second stream that will exercise the first step of the
2364 // server push rendezvous mechanism.
Ali Beyada0b1a1c2022-04-08 20:08:142365 promised_stream_->RegisterRequest(&request_);
2366 EXPECT_EQ(OK, promised_stream_->InitializeStream(true, DEFAULT_PRIORITY,
2367 net_log_with_source_,
2368 callback_.callback()));
ckrasic2c63f9b2016-08-16 23:54:072369
2370 // Now sending a matching request will rendezvous with the promised
2371 // stream, but pending secondary validation.
2372 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2373 headers_, &response_, callback_.callback()));
2374
2375 base::RunLoop().RunUntilIdle();
2376
2377 // Cause of FinalValidation() crash as per bug.
2378 promised_stream_.reset();
2379
2380 // Receive the promised response headers.
2381 response_headers_ = promised_response_.Clone();
2382 size_t spdy_response_headers_frame_length;
2383 ProcessPacket(InnerConstructResponseHeadersPacket(
2384 1, promise_id_, false, &spdy_response_headers_frame_length));
2385}
2386
ckrasic3865ee0f2016-02-29 22:04:562387TEST_P(QuicHttpStreamTest, ServerPushCrossOriginOK) {
2388 SetRequest("GET", "/", DEFAULT_PRIORITY);
2389 Initialize();
2390
Bin Wue8408792021-08-24 23:25:162391 // Server push is not supported in HTTP/3.
2392 if (version_.UsesHttp3())
2393 return;
2394
ckrasic3865ee0f2016-02-29 22:04:562395 // Initialize the first stream, for receiving the promise on.
2396 request_.method = "GET";
rchcd379012017-04-12 21:53:322397 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562398
Ali Beyada0b1a1c2022-04-08 20:08:142399 stream_->RegisterRequest(&request_);
2400 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262401 net_log_with_source_,
2402 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232403 ASSERT_EQ(OK,
2404 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562405
2406 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2407 // packet, but does it matter?
2408
2409 push_promise_[":authority"] = "mail.example.org";
David Schinazi3f7465c2019-07-12 01:57:052410 promise_url_ =
2411 quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
ckrasic3865ee0f2016-02-29 22:04:562412
2413 ReceivePromise(promise_id_);
2414 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2415
2416 request_.url = GURL(promise_url_);
2417
2418 // Make the second stream that will exercise the first step of the
2419 // server push rendezvous mechanism.
Ali Beyada0b1a1c2022-04-08 20:08:142420 promised_stream_->RegisterRequest(&request_);
2421 EXPECT_EQ(OK, promised_stream_->InitializeStream(true, DEFAULT_PRIORITY,
2422 net_log_with_source_,
2423 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562424
2425 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252426 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562427 size_t spdy_response_headers_frame_length;
2428 ProcessPacket(InnerConstructResponseHeadersPacket(
2429 1, promise_id_, false, &spdy_response_headers_frame_length));
2430
2431 // Receive the promised response body.
2432 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432433 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172434 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2435 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562436
2437 // Now sending a matching request will have successful rendezvous
2438 // with the promised stream.
2439 EXPECT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
2440 callback_.callback()));
2441
2442 EXPECT_EQ(
2443 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2444 ->id(),
2445 promise_id_);
2446
2447 // The headers will be immediately available.
robpercival214763f2016-07-01 23:27:012448 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2449 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562450
2451 // As will be the body.
2452 EXPECT_EQ(
2453 static_cast<int>(strlen(kResponseBody)),
2454 promised_stream_->ReadResponseBody(
2455 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2456 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2457 EXPECT_TRUE(AtEof());
2458
ckrasic3865ee0f2016-02-29 22:04:562459 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2460 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412461 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562462 promised_stream_->GetTotalReceivedBytes());
2463}
2464
2465TEST_P(QuicHttpStreamTest, ServerPushCrossOriginFail) {
2466 SetRequest("GET", "/", DEFAULT_PRIORITY);
2467 Initialize();
2468
Bin Wue8408792021-08-24 23:25:162469 // Server push is not supported in HTTP/3.
2470 if (version_.UsesHttp3())
2471 return;
2472
ckrasic3865ee0f2016-02-29 22:04:562473 // Initialize the first stream, for receiving the promise on.
2474 request_.method = "GET";
rchcd379012017-04-12 21:53:322475 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562476
Ali Beyada0b1a1c2022-04-08 20:08:142477 stream_->RegisterRequest(&request_);
2478 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262479 net_log_with_source_,
2480 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232481 ASSERT_EQ(OK,
2482 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562483
2484 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2485 // packet, but does it matter?
2486 push_promise_[":authority"] = "www.notexample.org";
David Schinazi3f7465c2019-07-12 01:57:052487 promise_url_ =
2488 quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
ckrasic3865ee0f2016-02-29 22:04:562489
2490 ReceivePromise(promise_id_);
2491 // The promise will have been rejected because the cert doesn't
2492 // match.
2493 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
2494}
2495
2496TEST_P(QuicHttpStreamTest, ServerPushVaryCheckOK) {
2497 SetRequest("GET", "/", DEFAULT_PRIORITY);
2498 Initialize();
2499
Bin Wue8408792021-08-24 23:25:162500 // Server push is not supported in HTTP/3.
2501 if (version_.UsesHttp3())
2502 return;
2503
ckrasic3865ee0f2016-02-29 22:04:562504 // Initialize the first stream, for receiving the promise on.
2505 request_.method = "GET";
rchcd379012017-04-12 21:53:322506 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562507
Ali Beyada0b1a1c2022-04-08 20:08:142508 stream_->RegisterRequest(&request_);
2509 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262510 net_log_with_source_,
2511 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232512 ASSERT_EQ(OK,
2513 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562514
2515 push_promise_["accept-encoding"] = "gzip";
ckrasic3865ee0f2016-02-29 22:04:562516
2517 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2518 // packet, but does it matter?
2519 ReceivePromise(promise_id_);
2520 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2521
2522 request_.url = GURL(promise_url_);
2523
2524 // Make the second stream that will exercise the first step of the
2525 // server push rendezvous mechanism.
Ali Beyada0b1a1c2022-04-08 20:08:142526 promised_stream_->RegisterRequest(&request_);
2527 EXPECT_EQ(OK, promised_stream_->InitializeStream(true, DEFAULT_PRIORITY,
2528 net_log_with_source_,
2529 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562530
2531 headers_.SetHeader("accept-encoding", "gzip");
2532
2533 // Now sending a matching request will rendezvous with the promised
2534 // stream, but pending secondary validation.
2535 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2536 headers_, &response_, callback_.callback()));
2537
2538 // Receive the promised response headers.
2539 promised_response_["vary"] = "accept-encoding";
bnc94893a72016-06-30 13:45:252540 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562541 size_t spdy_response_headers_frame_length;
2542 ProcessPacket(InnerConstructResponseHeadersPacket(
2543 1, promise_id_, false, &spdy_response_headers_frame_length));
2544
2545 // Receive the promised response body.
2546 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432547 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172548 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2549 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562550
fdoray92e35a72016-06-10 15:54:552551 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562552
2553 // Rendezvous should have succeeded now, so the promised stream
2554 // should point at our push stream, and we should be able read
2555 // headers and data from it.
robpercival214763f2016-07-01 23:27:012556 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562557
2558 EXPECT_EQ(
2559 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2560 ->id(),
2561 promise_id_);
2562
robpercival214763f2016-07-01 23:27:012563 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2564 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562565
2566 EXPECT_EQ(
2567 static_cast<int>(strlen(kResponseBody)),
2568 promised_stream_->ReadResponseBody(
2569 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2570
2571 // Callback should return
2572 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2573 EXPECT_TRUE(AtEof());
2574
ckrasic3865ee0f2016-02-29 22:04:562575 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2576 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412577 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562578 promised_stream_->GetTotalReceivedBytes());
2579}
2580
2581TEST_P(QuicHttpStreamTest, ServerPushVaryCheckFail) {
2582 SetRequest("GET", "/", DEFAULT_PRIORITY);
2583 request_headers_[":scheme"] = "https";
2584 request_headers_[":path"] = "/bar";
2585 request_headers_["accept-encoding"] = "sdch";
2586
ckrasic3865ee0f2016-02-29 22:04:562587 Initialize();
2588
Bin Wue8408792021-08-24 23:25:162589 // Server push is not supported in HTTP/3.
2590 if (version_.UsesHttp3())
2591 return;
2592
ckrasic3865ee0f2016-02-29 22:04:562593 // Initialize the first stream, for receiving the promise on.
2594 request_.method = "GET";
rchcd379012017-04-12 21:53:322595 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562596
Ali Beyada0b1a1c2022-04-08 20:08:142597 stream_->RegisterRequest(&request_);
2598 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262599 net_log_with_source_,
2600 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232601 ASSERT_EQ(OK,
2602 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562603
2604 push_promise_["accept-encoding"] = "gzip";
ckrasic3865ee0f2016-02-29 22:04:562605
2606 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2607 // packet, but does it matter?
2608 ReceivePromise(promise_id_);
2609 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2610
2611 request_.url = GURL(promise_url_);
2612
2613 // Make the second stream that will exercise the first step of the
2614 // server push rendezvous mechanism.
Ali Beyada0b1a1c2022-04-08 20:08:142615 promised_stream_->RegisterRequest(&request_);
2616 EXPECT_EQ(OK, promised_stream_->InitializeStream(true, DEFAULT_PRIORITY,
2617 net_log_with_source_,
2618 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562619
2620 headers_.SetHeader("accept-encoding", "sdch");
2621
2622 // Now sending a matching request will rendezvous with the promised
2623 // stream, but pending secondary validation.
2624 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2625 headers_, &response_, callback_.callback()));
2626
2627 // Receive the promised response headers.
2628 promised_response_["vary"] = "accept-encoding";
bnc94893a72016-06-30 13:45:252629 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562630 size_t spdy_response_headers_frame_length;
2631 ProcessPacket(InnerConstructResponseHeadersPacket(
2632 1, promise_id_, false, &spdy_response_headers_frame_length));
2633
fdoray92e35a72016-06-10 15:54:552634 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562635
2636 // Rendezvous should have failed due to vary mismatch, so the
2637 // promised stream should have been aborted, and instead we have a
2638 // new, regular client initiated stream.
robpercival214763f2016-07-01 23:27:012639 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562640
2641 // Not a server-initiated stream.
2642 EXPECT_NE(
2643 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2644 ->id(),
2645 promise_id_);
2646
2647 // Instead, a new client-initiated stream.
2648 EXPECT_EQ(
2649 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2650 ->id(),
Nick Harper23290b82019-05-02 00:02:562651 stream_id_ + quic::QuicUtils::StreamIdDelta(version_.transport_version));
ckrasic3865ee0f2016-02-29 22:04:562652
2653 // After rendezvous failure, the push stream has been cancelled.
2654 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
2655
2656 // The rest of the test verifies that the retried as
2657 // client-initiated version of |promised_stream_| works as intended.
2658
2659 // Ack the request.
Renjie90e808e2019-01-24 07:24:042660 ProcessPacket(ConstructServerAckPacket(2, 1, 1, 1));
ckrasic3865ee0f2016-02-29 22:04:562661
Kenichi Ishibashif8634ab2021-03-16 23:41:282662 SetResponse("404", string());
ckrasic3865ee0f2016-02-29 22:04:562663 size_t spdy_response_header_frame_length;
2664 ProcessPacket(InnerConstructResponseHeadersPacket(
Nick Harper23290b82019-05-02 00:02:562665 3,
2666 stream_id_ + quic::QuicUtils::StreamIdDelta(version_.transport_version),
2667 kFin, &spdy_response_header_frame_length));
ckrasic3865ee0f2016-02-29 22:04:562668
fdoray92e35a72016-06-10 15:54:552669 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562670
robpercival214763f2016-07-01 23:27:012671 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2672 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562673 ASSERT_TRUE(response_.headers.get());
2674 EXPECT_EQ(404, response_.headers->response_code());
2675 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
2676 EXPECT_FALSE(response_.response_time.is_null());
2677 EXPECT_FALSE(response_.request_time.is_null());
2678
2679 // There is no body, so this should return immediately.
2680 EXPECT_EQ(
2681 0, promised_stream_->ReadResponseBody(
2682 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2683 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2684
2685 stream_->Close(true);
2686
2687 EXPECT_TRUE(AtEof());
ckrasic3865ee0f2016-02-29 22:04:562688}
2689
maksim.sisov84e20c92016-06-23 08:49:342690TEST_P(QuicHttpStreamTest, DataReadErrorSynchronous) {
2691 SetRequest("POST", "/", DEFAULT_PRIORITY);
2692 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232693 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252694 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232695 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Yixin Wange7ecc472018-03-06 19:00:252696 AddWrite(ConstructRequestAndRstPacket(
Renjie Tangaadb84b2019-08-31 01:00:232697 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2698 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
2699 &spdy_request_headers_frame_length, quic::QUIC_ERROR_PROCESSING_STREAM));
maksim.sisov84e20c92016-06-23 08:49:342700
2701 Initialize();
2702
Jeremy Roman0579ed62017-08-29 15:56:192703 upload_data_stream_ = std::make_unique<ReadErrorUploadDataStream>(
maksim.sisov84e20c92016-06-23 08:49:342704 ReadErrorUploadDataStream::FailureMode::SYNC);
2705 request_.method = "POST";
rchcd379012017-04-12 21:53:322706 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122707 request_.upload_data_stream = upload_data_stream_.get();
maksim.sisov84e20c92016-06-23 08:49:342708 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202709 TestCompletionCallback().callback(), NetLogWithSource()));
maksim.sisov84e20c92016-06-23 08:49:342710
Ali Beyada0b1a1c2022-04-08 20:08:142711 stream_->RegisterRequest(&request_);
2712 EXPECT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262713 net_log_with_source_,
2714 callback_.callback()));
maksim.sisov84e20c92016-06-23 08:49:342715
2716 int result = stream_->SendRequest(headers_, &response_, callback_.callback());
robpercival214763f2016-07-01 23:27:012717 EXPECT_THAT(result, IsError(ERR_FAILED));
maksim.sisov84e20c92016-06-23 08:49:342718
2719 EXPECT_TRUE(AtEof());
2720
2721 // QuicHttpStream::GetTotalSent/ReceivedBytes includes only headers.
2722 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
2723 stream_->GetTotalSentBytes());
2724 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2725}
2726
2727TEST_P(QuicHttpStreamTest, DataReadErrorAsynchronous) {
2728 SetRequest("POST", "/", DEFAULT_PRIORITY);
2729 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232730 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252731 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232732 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:372733 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:232734 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2735 kIncludeVersion, !kFin, DEFAULT_PRIORITY,
2736 &spdy_request_headers_frame_length));
2737 AddWrite(
2738 ConstructClientRstStreamErrorPacket(packet_number++, !kIncludeVersion));
maksim.sisov84e20c92016-06-23 08:49:342739
2740 Initialize();
2741
Jeremy Roman0579ed62017-08-29 15:56:192742 upload_data_stream_ = std::make_unique<ReadErrorUploadDataStream>(
maksim.sisov84e20c92016-06-23 08:49:342743 ReadErrorUploadDataStream::FailureMode::ASYNC);
2744 request_.method = "POST";
rchcd379012017-04-12 21:53:322745 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122746 request_.upload_data_stream = upload_data_stream_.get();
maksim.sisov84e20c92016-06-23 08:49:342747 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202748 TestCompletionCallback().callback(), NetLogWithSource()));
maksim.sisov84e20c92016-06-23 08:49:342749
Ali Beyada0b1a1c2022-04-08 20:08:142750 stream_->RegisterRequest(&request_);
2751 EXPECT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262752 net_log_with_source_,
2753 callback_.callback()));
maksim.sisov84e20c92016-06-23 08:49:342754
2755 int result = stream_->SendRequest(headers_, &response_, callback_.callback());
2756
Renjie90e808e2019-01-24 07:24:042757 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
Kenichi Ishibashif8634ab2021-03-16 23:41:282758 SetResponse("200", string());
maksim.sisov84e20c92016-06-23 08:49:342759
robpercival214763f2016-07-01 23:27:012760 EXPECT_THAT(result, IsError(ERR_IO_PENDING));
2761 EXPECT_THAT(callback_.GetResult(result), IsError(ERR_FAILED));
maksim.sisov84e20c92016-06-23 08:49:342762
2763 EXPECT_TRUE(AtEof());
2764
2765 // QuicHttpStream::GetTotalSent/ReceivedBytes includes only headers.
2766 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
2767 stream_->GetTotalSentBytes());
2768 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2769}
2770
Bence Béky97ec688c2021-03-16 13:48:502771TEST_P(QuicHttpStreamTest, GetAcceptChViaAlps) {
2772 AddWrite(ConstructInitialSettingsPacket());
2773 Initialize();
2774
2775 if (!VersionUsesHttp3(version_.transport_version)) {
2776 // ALPS is only implemented for HTTP/3.
2777 return;
2778 }
2779
2780 base::HistogramTester histogram_tester;
2781
2782 session_->OnAcceptChFrameReceivedViaAlps(
Bence Béky41a34f02021-05-07 00:27:482783 {{{"https://www.example.org", "Sec-CH-UA-Platform"}}});
Bence Béky97ec688c2021-03-16 13:48:502784
2785 request_.method = "GET";
2786 request_.url = GURL("https://www.example.org/foo");
2787
Ali Beyada0b1a1c2022-04-08 20:08:142788 stream_->RegisterRequest(&request_);
2789 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262790 net_log_with_source_,
2791 callback_.callback()));
Bence Béky41a34f02021-05-07 00:27:482792 EXPECT_EQ("Sec-CH-UA-Platform", stream_->GetAcceptChViaAlps());
Bence Béky97ec688c2021-03-16 13:48:502793 EXPECT_TRUE(AtEof());
2794
2795 histogram_tester.ExpectBucketCount(
2796 "Net.QuicSession.AcceptChFrameReceivedViaAlps", 1, 1);
2797 histogram_tester.ExpectTotalCount(
2798 "Net.QuicSession.AcceptChFrameReceivedViaAlps", 1);
2799 histogram_tester.ExpectBucketCount("Net.QuicSession.AcceptChForOrigin", 1, 1);
2800 histogram_tester.ExpectTotalCount("Net.QuicSession.AcceptChForOrigin", 1);
2801}
2802
Tsuyoshi Horo4f516be2022-06-14 11:53:132803} // namespace net::test