blob: ae223843cfede461c88542e2cddbc97ff63de59b [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"
Ryan Hamiltona3ee93a72018-08-01 22:03:0840#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"
Victor Vasiliev6bb59d22019-03-08 21:34:5159#include "net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.h"
60#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
61#include "net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h"
62#include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
David Schinazi3f7465c2019-07-12 01:57:0563#include "net/third_party/quiche/src/quic/core/http/spdy_server_push_utils.h"
Victor Vasiliev6bb59d22019-03-08 21:34:5164#include "net/third_party/quiche/src/quic/core/quic_connection.h"
65#include "net/third_party/quiche/src/quic/core/quic_utils.h"
66#include "net/third_party/quiche/src/quic/core/quic_write_blocked_list.h"
Ryan Hamiltona1d1f4a2019-06-26 14:43:0467#include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h"
68#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
Victor Vasiliev6bb59d22019-03-08 21:34:5169#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
70#include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
71#include "net/third_party/quiche/src/quic/test_tools/mock_random.h"
Bence Béky6e243aa2019-12-13 19:01:0772#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h"
Victor Vasiliev6bb59d22019-03-08 21:34:5173#include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
74#include "net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h"
75#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
Victor Vasiliev27cc7712019-01-24 11:50:1476#include "net/third_party/quiche/src/spdy/core/spdy_frame_builder.h"
77#include "net/third_party/quiche/src/spdy/core/spdy_framer.h"
78#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
Ramin Halavati683bcaa92018-02-14 08:42:3979#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
[email protected]f702d572012-12-04 15:56:2080#include "testing/gmock/include/gmock/gmock.h"
81#include "testing/gtest/include/gtest/gtest.h"
Dan McArdle68a5f622021-07-09 20:56:5382#include "url/scheme_host_port.h"
83#include "url/url_constants.h"
[email protected]f702d572012-12-04 15:56:2084
bnc614a92d32016-04-04 13:56:0785using std::string;
[email protected]f702d572012-12-04 15:56:2086using testing::_;
[email protected]06ff5152013-08-29 01:03:0587using testing::AnyNumber;
88using testing::Return;
[email protected]f702d572012-12-04 15:56:2089
90namespace net {
[email protected]f702d572012-12-04 15:56:2091namespace test {
[email protected]f702d572012-12-04 15:56:2092namespace {
93
[email protected]16ba7742014-08-22 00:57:2594const char kUploadData[] = "Really nifty data!";
rch9ae5b3b2016-02-11 00:36:2995const char kDefaultServerHostName[] = "www.example.org";
rchcd379012017-04-12 21:53:3296const uint16_t kDefaultServerPort = 443;
[email protected]f702d572012-12-04 15:56:2097
David Schinazi09e9a6012019-10-03 17:37:5798struct TestParams {
99 quic::ParsedQuicVersion version;
100 bool client_headers_include_h2_stream_dependency;
101};
102
103// Used by ::testing::PrintToStringParamName().
104std::string PrintToString(const TestParams& p) {
Victor Vasiliev62c09dc2020-11-06 18:18:29105 return base::StrCat(
106 {ParsedQuicVersionToString(p.version), "_",
107 (p.client_headers_include_h2_stream_dependency ? "" : "No"),
108 "Dependency"});
David Schinazi09e9a6012019-10-03 17:37:57109}
110
111std::vector<TestParams> GetTestParams() {
112 std::vector<TestParams> params;
113 quic::ParsedQuicVersionVector all_supported_versions =
114 quic::AllSupportedVersions();
115 for (const auto& version : all_supported_versions) {
116 params.push_back(TestParams{version, false});
117 params.push_back(TestParams{version, true});
118 }
119 return params;
120}
121
Bence Békye0d3747d2020-08-28 23:16:40122// Returns true if |params| is a dict, has an entry with key "headers", that
123// entry is a list of strings, which when interpreted as colon-separated
124// key-value pairs has exactly one entry with |key| and that entry has value
125// |expected_value|.
126bool CheckHeader(const base::Value& params,
127 base::StringPiece key,
128 base::StringPiece expected_value) {
129 if (!params.is_dict()) {
130 return false;
131 }
132 const base::Value* headers = params.FindListKey("headers");
133 if (!headers) {
134 return false;
135 }
136
137 std::string header_prefix = base::StrCat({key, ": "});
138 std::string expected_header = base::StrCat({header_prefix, expected_value});
139
Daniel Cheng354945d2022-02-02 23:39:17140 auto header_list = headers->GetListDeprecated();
Bence Békye0d3747d2020-08-28 23:16:40141 auto header_it = header_list.begin();
142 bool header_found = false;
143 while (header_it != header_list.end()) {
144 if (!header_it->is_string()) {
145 return false;
146 }
147 const std::string& header = header_it->GetString();
148 if (base::StartsWith(header, header_prefix)) {
149 if (header_found) {
150 return false;
151 }
152 if (header != expected_header) {
153 return false;
154 }
155 header_found = true;
156 }
157 ++header_it;
158 }
159 return header_found;
160}
161
Ryan Hamilton8d9ee76e2018-05-29 23:52:52162class TestQuicConnection : public quic::QuicConnection {
[email protected]f702d572012-12-04 15:56:20163 public:
Ryan Hamilton8d9ee76e2018-05-29 23:52:52164 TestQuicConnection(const quic::ParsedQuicVersionVector& versions,
165 quic::QuicConnectionId connection_id,
[email protected]f702d572012-12-04 15:56:20166 IPEndPoint address,
rch12fef552016-01-15 16:26:31167 QuicChromiumConnectionHelper* helper,
rch16c74d1d2016-04-22 06:14:07168 QuicChromiumAlarmFactory* alarm_factory,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52169 quic::QuicPacketWriter* writer)
Victor Vasiliev4f6fb892019-05-31 16:58:31170 : quic::QuicConnection(connection_id,
Nick Harperd049f192020-10-02 02:56:10171 quic::QuicSocketAddress(),
Victor Vasiliev4f6fb892019-05-31 16:58:31172 ToQuicSocketAddress(address),
173 helper,
174 alarm_factory,
175 writer,
176 true /* owns_writer */,
177 quic::Perspective::IS_CLIENT,
178 versions) {}
[email protected]f702d572012-12-04 15:56:20179
Ryan Hamilton8d9ee76e2018-05-29 23:52:52180 void SetSendAlgorithm(quic::SendAlgorithmInterface* send_algorithm) {
181 quic::test::QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
[email protected]f702d572012-12-04 15:56:20182 }
183};
184
maksim.sisov84e20c92016-06-23 08:49:34185// UploadDataStream that always returns errors on data read.
186class ReadErrorUploadDataStream : public UploadDataStream {
187 public:
188 enum class FailureMode { SYNC, ASYNC };
189
190 explicit ReadErrorUploadDataStream(FailureMode mode)
Jeremy Romand54000b22019-07-08 18:40:16191 : UploadDataStream(true, 0), async_(mode) {}
Peter Boström293b1342021-09-22 17:31:43192
193 ReadErrorUploadDataStream(const ReadErrorUploadDataStream&) = delete;
194 ReadErrorUploadDataStream& operator=(const ReadErrorUploadDataStream&) =
195 delete;
196
maksim.sisov84e20c92016-06-23 08:49:34197 ~ReadErrorUploadDataStream() override {}
198
199 private:
200 void CompleteRead() { UploadDataStream::OnReadCompleted(ERR_FAILED); }
201
202 // UploadDataStream implementation:
tfarina42834112016-09-22 13:38:20203 int InitInternal(const NetLogWithSource& net_log) override { return OK; }
maksim.sisov84e20c92016-06-23 08:49:34204
205 int ReadInternal(IOBuffer* buf, int buf_len) override {
206 if (async_ == FailureMode::ASYNC) {
207 base::ThreadTaskRunnerHandle::Get()->PostTask(
kylecharf4fe5172019-02-15 18:53:49208 FROM_HERE, base::BindOnce(&ReadErrorUploadDataStream::CompleteRead,
209 weak_factory_.GetWeakPtr()));
maksim.sisov84e20c92016-06-23 08:49:34210 return ERR_IO_PENDING;
211 }
212 return ERR_FAILED;
213 }
214
215 void ResetInternal() override {}
216
217 const FailureMode async_;
218
Jeremy Romand54000b22019-07-08 18:40:16219 base::WeakPtrFactory<ReadErrorUploadDataStream> weak_factory_{this};
maksim.sisov84e20c92016-06-23 08:49:34220};
221
Bence Béky8ddc2492018-06-13 01:02:04222// A helper class that will delete |stream| when the callback is invoked.
xunjieli8dff50b2016-07-22 14:19:06223class DeleteStreamCallback : public TestCompletionCallbackBase {
224 public:
Bence Béky8ddc2492018-06-13 01:02:04225 explicit DeleteStreamCallback(std::unique_ptr<QuicHttpStream> stream)
226 : stream_(std::move(stream)) {}
xunjieli8dff50b2016-07-22 14:19:06227
Bence Béky8ddc2492018-06-13 01:02:04228 CompletionOnceCallback callback() {
229 return base::BindOnce(&DeleteStreamCallback::DeleteStream,
230 base::Unretained(this));
231 }
xunjieli8dff50b2016-07-22 14:19:06232
233 private:
234 void DeleteStream(int result) {
235 stream_.reset();
236 SetResult(result);
237 }
238
239 std::unique_ptr<QuicHttpStream> stream_;
xunjieli8dff50b2016-07-22 14:19:06240};
241
[email protected]f702d572012-12-04 15:56:20242} // namespace
243
[email protected]24e5bc52013-09-18 15:36:58244class QuicHttpStreamPeer {
245 public:
rch08e198572017-05-09 16:56:55246 static QuicChromiumClientStream::Handle* GetQuicChromiumClientStream(
[email protected]24e5bc52013-09-18 15:36:58247 QuicHttpStream* stream) {
rch08e198572017-05-09 16:56:55248 return stream->stream_.get();
[email protected]24e5bc52013-09-18 15:36:58249 }
250};
251
David Schinazi09e9a6012019-10-03 17:37:57252class QuicHttpStreamTest : public ::testing::TestWithParam<TestParams>,
Gabriel Charette694c3c332019-08-19 14:53:05253 public WithTaskEnvironment {
rchfb47f712017-05-21 03:24:00254 public:
255 void CloseStream(QuicHttpStream* stream, int /*rv*/) { stream->Close(false); }
256
[email protected]f702d572012-12-04 15:56:20257 protected:
[email protected]1e960032013-12-20 19:00:20258 static const bool kFin = true;
259 static const bool kIncludeVersion = true;
[email protected]1e960032013-12-20 19:00:20260
[email protected]f702d572012-12-04 15:56:20261 // Holds a packet to be written to the wire, and the IO mode that should
262 // be used by the mock socket when performing the write.
263 struct PacketToWrite {
Ryan Hamilton8d9ee76e2018-05-29 23:52:52264 PacketToWrite(IoMode mode, quic::QuicReceivedPacket* packet)
rjshaded5ced072015-12-18 19:26:02265 : mode(mode), packet(packet) {}
rtenneti15656ae2016-01-23 03:05:03266 PacketToWrite(IoMode mode, int rv) : mode(mode), packet(nullptr), rv(rv) {}
[email protected]f702d572012-12-04 15:56:20267 IoMode mode;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52268 quic::QuicReceivedPacket* packet;
rtenneti15656ae2016-01-23 03:05:03269 int rv;
[email protected]f702d572012-12-04 15:56:20270 };
271
272 QuicHttpStreamTest()
David Schinazi09e9a6012019-10-03 17:37:57273 : version_(GetParam().version),
274 client_headers_include_h2_stream_dependency_(
275 GetParam().client_headers_include_h2_stream_dependency),
Nick Harpera598fc5f2019-06-21 08:46:50276 crypto_config_(
277 quic::test::crypto_test_utils::ProofVerifierForTesting()),
Victor Costan9c7302b2018-08-27 16:39:44278 read_buffer_(base::MakeRefCounted<IOBufferWithSize>(4096)),
Fan Yang32c5a112018-12-10 20:06:33279 promise_id_(GetNthServerInitiatedUnidirectionalStreamId(0)),
280 stream_id_(GetNthClientInitiatedBidirectionalStreamId(0)),
David Schinazic8281052019-01-24 06:14:17281 connection_id_(quic::test::TestConnectionId(2)),
Yixin Wang079ad542018-01-11 04:06:05282 client_maker_(version_,
alyssar2adf3ac2016-05-03 17:12:58283 connection_id_,
284 &clock_,
285 kDefaultServerHostName,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52286 quic::Perspective::IS_CLIENT,
Yixin Wang079ad542018-01-11 04:06:05287 client_headers_include_h2_stream_dependency_),
288 server_maker_(version_,
zhongyi5dbfdd42017-06-20 05:22:15289 connection_id_,
alyssar2adf3ac2016-05-03 17:12:58290 &clock_,
291 kDefaultServerHostName,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52292 quic::Perspective::IS_SERVER,
Yixin Wang079ad542018-01-11 04:06:05293 false),
ckrasic3865ee0f2016-02-29 22:04:56294 random_generator_(0),
Ryan Hamilton0d65a8c2019-06-07 00:46:02295 printer_(version_) {
Renjie Tang98b4d512020-02-08 01:24:19296 FLAGS_quic_enable_http3_grease_randomness = false;
Zhongyi Shi49f8ad2fd2019-12-13 01:20:31297 quic::QuicEnableVersion(version_);
martijn21968ea2016-02-24 18:46:20298 IPAddress ip(192, 0, 2, 33);
[email protected]f702d572012-12-04 15:56:20299 peer_addr_ = IPEndPoint(ip, 443);
300 self_addr_ = IPEndPoint(ip, 8435);
Ryan Hamilton8d9ee76e2018-05-29 23:52:52301 clock_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(20));
Ramin Halavati683bcaa92018-02-14 08:42:39302 request_.traffic_annotation =
303 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f702d572012-12-04 15:56:20304 }
305
306 ~QuicHttpStreamTest() {
Renjieba55fae2018-09-20 03:05:16307 session_->CloseSessionOnError(ERR_ABORTED, quic::QUIC_INTERNAL_ERROR,
308 quic::ConnectionCloseBehavior::SILENT_CLOSE);
[email protected]f702d572012-12-04 15:56:20309 for (size_t i = 0; i < writes_.size(); i++) {
310 delete writes_[i].packet;
311 }
312 }
313
314 // Adds a packet to the list of expected writes.
Ryan Hamilton8d9ee76e2018-05-29 23:52:52315 void AddWrite(std::unique_ptr<quic::QuicReceivedPacket> packet) {
[email protected]1e960032013-12-20 19:00:20316 writes_.push_back(PacketToWrite(SYNCHRONOUS, packet.release()));
[email protected]f702d572012-12-04 15:56:20317 }
318
rtenneti15656ae2016-01-23 03:05:03319 void AddWrite(IoMode mode, int rv) {
320 writes_.push_back(PacketToWrite(mode, rv));
321 }
322
[email protected]f702d572012-12-04 15:56:20323 // Returns the packet to be written at position |pos|.
Ryan Hamilton8d9ee76e2018-05-29 23:52:52324 quic::QuicReceivedPacket* GetWrite(size_t pos) { return writes_[pos].packet; }
[email protected]f702d572012-12-04 15:56:20325
326 bool AtEof() {
rch37de576c2015-05-17 20:28:17327 return socket_data_->AllReadDataConsumed() &&
328 socket_data_->AllWriteDataConsumed();
[email protected]f702d572012-12-04 15:56:20329 }
330
Ryan Hamilton8d9ee76e2018-05-29 23:52:52331 void ProcessPacket(std::unique_ptr<quic::QuicReceivedPacket> packet) {
Victor Vasiliev4f6fb892019-05-31 16:58:31332 connection_->ProcessUdpPacket(ToQuicSocketAddress(self_addr_),
333 ToQuicSocketAddress(peer_addr_), *packet);
[email protected]f702d572012-12-04 15:56:20334 }
335
336 // Configures the test fixture to use the list of expected writes.
337 void Initialize() {
Renjie Tang6ff9a9b2021-02-03 22:11:09338 mock_writes_ = std::make_unique<MockWrite[]>(writes_.size());
[email protected]f702d572012-12-04 15:56:20339 for (size_t i = 0; i < writes_.size(); i++) {
rtenneti15656ae2016-01-23 03:05:03340 if (writes_[i].packet == nullptr) {
341 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].rv, i);
342 } else {
343 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].packet->data(),
344 writes_[i].packet->length());
345 }
bnc614a92d32016-04-04 13:56:07346 }
[email protected]f702d572012-12-04 15:56:20347
Renjie Tang6ff9a9b2021-02-03 22:11:09348 socket_data_ = std::make_unique<StaticSocketDataProvider>(
Ryan Sleevib8d7ea02018-05-07 20:01:01349 base::span<MockRead>(),
Renjie Tang6ff9a9b2021-02-03 22:11:09350 base::make_span(mock_writes_.get(), writes_.size()));
Ryan Hamilton0d65a8c2019-06-07 00:46:02351 socket_data_->set_printer(&printer_);
[email protected]f702d572012-12-04 15:56:20352
Matt Reichhoff0049a0b72021-10-20 20:44:26353 std::unique_ptr<MockUDPClientSocket> socket(
354 new MockUDPClientSocket(socket_data_.get(), NetLog::Get()));
[email protected]e13201d82012-12-12 05:00:32355 socket->Connect(peer_addr_);
[email protected]f702d572012-12-04 15:56:20356 runner_ = new TestTaskRunner(&clock_);
Ryan Hamilton8d9ee76e2018-05-29 23:52:52357 send_algorithm_ = new quic::test::MockSendAlgorithm();
rch7dd15702015-07-01 18:57:57358 EXPECT_CALL(*send_algorithm_, InRecovery()).WillRepeatedly(Return(false));
359 EXPECT_CALL(*send_algorithm_, InSlowStart()).WillRepeatedly(Return(false));
Victor Vasiliev7da08172019-10-14 06:04:25360 if (VersionUsesHttp3(version_.transport_version)) {
Renjie Tangaadb84b2019-08-31 01:00:23361 EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
362 .Times(testing::AtLeast(1));
363 }
Ryan Hamiltona1d1f4a2019-06-26 14:43:04364 EXPECT_CALL(*send_algorithm_, OnCongestionEvent(_, _, _, _, _))
365 .Times(AnyNumber());
rtenneti44f4a2e2015-08-07 14:00:07366 EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
Zhongyi Shica576df2019-04-12 17:43:40367 .WillRepeatedly(Return(quic::kMaxOutgoingPacketSize));
jokulik0e0a00c32016-06-13 21:51:58368 EXPECT_CALL(*send_algorithm_, PacingRate(_))
Ryan Hamilton8d9ee76e2018-05-29 23:52:52369 .WillRepeatedly(Return(quic::QuicBandwidth::Zero()));
Michael Warres74ee3ce2017-10-09 15:26:37370 EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true));
rtenneti44f4a2e2015-08-07 14:00:07371 EXPECT_CALL(*send_algorithm_, BandwidthEstimate())
Ryan Hamilton8d9ee76e2018-05-29 23:52:52372 .WillRepeatedly(Return(quic::QuicBandwidth::Zero()));
rch1e543ec2015-03-29 07:04:40373 EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(AnyNumber());
rch08cae032017-03-29 00:59:15374 EXPECT_CALL(*send_algorithm_, OnApplicationLimited(_)).Times(AnyNumber());
rch0d5bcf62017-05-24 22:48:45375 EXPECT_CALL(*send_algorithm_, GetCongestionControlType())
376 .Times(AnyNumber());
Renjie Tang6ff9a9b2021-02-03 22:11:09377 helper_ = std::make_unique<QuicChromiumConnectionHelper>(
378 &clock_, &random_generator_);
379 alarm_factory_ =
380 std::make_unique<QuicChromiumAlarmFactory>(runner_.get(), &clock_);
rch16c74d1d2016-04-22 06:14:07381
Michael Warres74ee3ce2017-10-09 15:26:37382 connection_ = new TestQuicConnection(
Nick Harper23290b82019-05-02 00:02:56383 quic::test::SupportedVersions(version_), connection_id_, peer_addr_,
384 helper_.get(), alarm_factory_.get(),
Ryan Hamilton9edcf1a2017-11-22 05:55:17385 new QuicChromiumPacketWriter(
386 socket.get(), base::ThreadTaskRunnerHandle::Get().get()));
[email protected]f702d572012-12-04 15:56:20387 connection_->set_visitor(&visitor_);
[email protected]fee17f72013-02-03 07:47:41388 connection_->SetSendAlgorithm(send_algorithm_);
rch03b7a202016-02-05 00:54:20389
390 // Load a certificate that is valid for *.example.org
391 scoped_refptr<X509Certificate> test_cert(
392 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
393 EXPECT_TRUE(test_cert.get());
394
395 verify_details_.cert_verify_result.verified_cert = test_cert;
396 verify_details_.cert_verify_result.is_issued_by_known_root = true;
397 crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details_);
398
xunjieli84adaab2016-09-20 01:12:28399 base::TimeTicks dns_end = base::TimeTicks::Now();
Peter Kastinge5a38ed2021-10-02 03:06:35400 base::TimeTicks dns_start = dns_end - base::Milliseconds(1);
Renjie Tang6ff9a9b2021-02-03 22:11:09401 session_ = std::make_unique<QuicChromiumClientSession>(
xunjielib53b38c2016-03-24 15:54:36402 connection_, std::move(socket),
rtenneti1cd3b162015-09-29 02:58:28403 /*stream_factory=*/nullptr, &crypto_client_stream_factory_, &clock_,
Nick Harper89bc7212018-07-31 19:07:57404 &transport_security_state_, /*ssl_config_service=*/nullptr,
danakjad1777e2016-04-16 00:56:42405 base::WrapUnique(static_cast<QuicServerInfo*>(nullptr)),
Paul Jensen8e3c5d32018-02-19 17:06:33406 QuicSessionKey(kDefaultServerHostName, kDefaultServerPort,
dalyk51ab46b2019-10-15 15:14:34407 PRIVACY_MODE_DISABLED, SocketTag(),
Ben Schwartz3ff4dc1e62021-04-27 21:15:23408 NetworkIsolationKey(), SecureDnsPolicy::kAllow),
Bence Béky1ceba552019-07-19 17:11:05409 /*require_confirmation=*/false,
Bence Béky1ceba552019-07-19 17:11:05410 /*migrate_session_early_v2=*/false,
Zhongyi Shi757fcce2018-06-27 05:41:27411 /*migrate_session_on_network_change_v2=*/false,
412 /*default_network=*/NetworkChangeNotifier::kInvalidNetworkHandle,
Zhongyi Shie01f2db2019-02-22 19:53:23413 quic::QuicTime::Delta::FromMilliseconds(
Ryan Sleevi2e8255b2019-07-17 21:02:21414 kDefaultRetransmittableOnWireTimeout.InMilliseconds()),
Zhongyi Shiaf38c4e42019-08-29 22:49:05415 /*migrate_idle_session=*/false, /*allow_port_migration=*/false,
416 kDefaultIdleSessionMigrationPeriod, kMaxTimeOnNonDefaultNetwork,
Zhongyi Shiee760762018-08-01 00:54:29417 kMaxMigrationsToNonDefaultNetworkOnWriteError,
Zhongyi Shi8b1e43f2017-12-13 20:46:30418 kMaxMigrationsToNonDefaultNetworkOnPathDegrading,
Zhongyi Shi5f587cc2017-11-21 23:24:17419 kQuicYieldAfterPacketsRead,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52420 quic::QuicTime::Delta::FromMilliseconds(
421 kQuicYieldAfterDurationMilliseconds),
Yixin Wang079ad542018-01-11 04:06:05422 client_headers_include_h2_stream_dependency_, /*cert_verify_flags=*/0,
Matt Menkefca05b62019-09-20 23:15:56423 quic::test::DefaultQuicConfig(),
424 std::make_unique<TestQuicCryptoClientConfigHandle>(&crypto_config_),
Matt Menked804aaf2020-07-21 21:25:48425 "CONNECTION_UNKNOWN", dns_start, dns_end,
426 std::make_unique<quic::QuicClientPushPromiseIndex>(), nullptr,
Zhongyi Shic16b4102019-02-12 00:37:40427 base::DefaultTickClock::GetInstance(),
xunjieli84adaab2016-09-20 01:12:28428 base::ThreadTaskRunnerHandle::Get().get(),
Matt Reichhoff0049a0b72021-10-20 20:44:26429 /*socket_performance_watcher=*/nullptr, NetLog::Get());
rtennetid39bd762015-06-12 01:05:52430 session_->Initialize();
rchf0b18c8a2017-05-05 19:31:57431
Bence Béky6e243aa2019-12-13 19:01:07432 // Blackhole QPACK decoder stream instead of constructing mock writes.
433 if (VersionUsesHttp3(version_.transport_version)) {
434 session_->qpack_decoder()->set_qpack_stream_sender_delegate(
435 &noop_qpack_stream_sender_delegate_);
436 }
437
438 TestCompletionCallback callback;
rch433bf5f2017-02-14 04:10:47439 session_->CryptoConnect(callback.callback());
Ryan Hamilton6c2a2a82017-12-15 02:06:28440 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>());
Ryan Hamilton6c2a2a82017-12-15 02:06:28444 promised_stream_ = std::make_unique<QuicHttpStream>(
Dan McArdle68a5f622021-07-09 20:56:53445 session_->CreateHandle(
446 url::SchemeHostPort(url::kHttpsScheme, "www.example.org", 443)),
Eric Orthac661912022-01-10 21:44:17447 /*dns_aliases=*/std::set<std::string>());
ckrasic3865ee0f2016-02-29 22:04:56448 push_promise_[":path"] = "/bar";
449 push_promise_[":authority"] = "www.example.org";
450 push_promise_[":version"] = "HTTP/1.1";
451 push_promise_[":method"] = "GET";
452 push_promise_[":scheme"] = "https";
453
Kenichi Ishibashif8634ab2021-03-16 23:41:28454 promised_response_[":status"] = "200";
ckrasic3865ee0f2016-02-29 22:04:56455 promised_response_[":version"] = "HTTP/1.1";
456 promised_response_["content-type"] = "text/plain";
457
David Schinazi3f7465c2019-07-12 01:57:05458 promise_url_ =
459 quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
[email protected]6cca996b2013-01-25 07:43:36460 }
461
bnc614a92d32016-04-04 13:56:07462 void SetRequest(const string& method,
463 const string& path,
[email protected]1e960032013-12-20 19:00:20464 RequestPriority priority) {
rchcd379012017-04-12 21:53:32465 request_headers_ = client_maker_.GetRequestHeaders(method, "https", path);
[email protected]6cca996b2013-01-25 07:43:36466 }
467
bnc614a92d32016-04-04 13:56:07468 void SetResponse(const string& status, const string& body) {
alyssar2adf3ac2016-05-03 17:12:58469 response_headers_ = server_maker_.GetResponseHeaders(status);
[email protected]92bf17c2014-03-03 21:14:03470 response_data_ = body;
[email protected]6cca996b2013-01-25 07:43:36471 }
[email protected]f702d572012-12-04 15:56:20472
Ryan Hamilton8d9ee76e2018-05-29 23:52:52473 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientDataPacket(
Fan Yangac867502019-01-28 21:10:23474 uint64_t packet_number,
[email protected]e8ff26842013-03-22 21:02:05475 bool should_include_version,
[email protected]f702d572012-12-04 15:56:20476 bool fin,
Victor Vasiliev47ecb6a2020-10-14 17:22:10477 absl::string_view data) {
Ryan Hamilton7505eb92019-06-08 00:22:17478 return client_maker_.MakeDataPacket(packet_number, stream_id_,
479 should_include_version, fin, data);
alyssar2adf3ac2016-05-03 17:12:58480 }
481
Ryan Hamilton8d9ee76e2018-05-29 23:52:52482 std::unique_ptr<quic::QuicReceivedPacket> ConstructServerDataPacket(
Fan Yangac867502019-01-28 21:10:23483 uint64_t packet_number,
alyssar2adf3ac2016-05-03 17:12:58484 bool should_include_version,
485 bool fin,
Victor Vasiliev47ecb6a2020-10-14 17:22:10486 absl::string_view data) {
Ryan Hamilton7505eb92019-06-08 00:22:17487 return server_maker_.MakeDataPacket(packet_number, stream_id_,
488 should_include_version, fin, data);
ckrasic3865ee0f2016-02-29 22:04:56489 }
490
Ryan Hamilton8d9ee76e2018-05-29 23:52:52491 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23492 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52493 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56494 bool should_include_version,
495 bool fin,
496 RequestPriority request_priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02497 size_t* spdy_headers_frame_length) {
Yixin Wang7a3f1b8d2018-01-17 21:40:48498 return InnerConstructRequestHeadersPacket(
499 packet_number, stream_id, should_include_version, fin, request_priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02500 0, spdy_headers_frame_length);
Yixin Wang7a3f1b8d2018-01-17 21:40:48501 }
502
Ryan Hamilton8d9ee76e2018-05-29 23:52:52503 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23504 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52505 quic::QuicStreamId stream_id,
Yixin Wang7a3f1b8d2018-01-17 21:40:48506 bool should_include_version,
507 bool fin,
508 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52509 quic::QuicStreamId parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02510 size_t* spdy_headers_frame_length) {
Ryan Hamilton0239aac2018-05-19 00:03:13511 spdy::SpdyPriority priority =
ckrasic3865ee0f2016-02-29 22:04:56512 ConvertRequestPriorityToQuicPriority(request_priority);
alyssar2adf3ac2016-05-03 17:12:58513 return client_maker_.MakeRequestHeadersPacket(
ckrasic3865ee0f2016-02-29 22:04:56514 packet_number, stream_id, should_include_version, fin, priority,
Yixin Wang7a3f1b8d2018-01-17 21:40:48515 std::move(request_headers_), parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02516 spdy_headers_frame_length);
[email protected]f702d572012-12-04 15:56:20517 }
518
Ryan Hamilton8d9ee76e2018-05-29 23:52:52519 std::unique_ptr<quic::QuicReceivedPacket>
Yixin Wange7ecc472018-03-06 19:00:25520 ConstructRequestHeadersAndDataFramesPacket(
Fan Yangac867502019-01-28 21:10:23521 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52522 quic::QuicStreamId stream_id,
Yixin Wange7ecc472018-03-06 19:00:25523 bool should_include_version,
524 bool fin,
525 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52526 quic::QuicStreamId parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25527 size_t* spdy_headers_frame_length,
528 const std::vector<std::string>& data_writes) {
Ryan Hamilton0239aac2018-05-19 00:03:13529 spdy::SpdyPriority priority =
Yixin Wange7ecc472018-03-06 19:00:25530 ConvertRequestPriorityToQuicPriority(request_priority);
531 return client_maker_.MakeRequestHeadersAndMultipleDataFramesPacket(
532 packet_number, stream_id, should_include_version, fin, priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02533 std::move(request_headers_), parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25534 spdy_headers_frame_length, data_writes);
535 }
536
Ryan Hamilton8d9ee76e2018-05-29 23:52:52537 std::unique_ptr<quic::QuicReceivedPacket> ConstructRequestAndRstPacket(
Fan Yangac867502019-01-28 21:10:23538 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52539 quic::QuicStreamId stream_id,
Yixin Wange7ecc472018-03-06 19:00:25540 bool should_include_version,
541 bool fin,
542 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52543 quic::QuicStreamId parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25544 size_t* spdy_headers_frame_length,
Ryan Hamiltonb5d4c5a2019-06-21 22:08:41545 quic::QuicRstStreamErrorCode error_code) {
Ryan Hamilton0239aac2018-05-19 00:03:13546 spdy::SpdyPriority priority =
Yixin Wange7ecc472018-03-06 19:00:25547 ConvertRequestPriorityToQuicPriority(request_priority);
548 return client_maker_.MakeRequestHeadersAndRstPacket(
549 packet_number, stream_id, should_include_version, fin, priority,
550 std::move(request_headers_), parent_stream_id,
Ryan Hamiltonb5d4c5a2019-06-21 22:08:41551 spdy_headers_frame_length, error_code);
Yixin Wange7ecc472018-03-06 19:00:25552 }
553
Ryan Hamilton8d9ee76e2018-05-29 23:52:52554 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructResponseHeadersPacket(
Fan Yangac867502019-01-28 21:10:23555 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52556 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56557 bool fin,
558 size_t* spdy_headers_frame_length) {
alyssar2adf3ac2016-05-03 17:12:58559 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26560 packet_number, stream_id, !kIncludeVersion, fin,
Ryan Hamilton0d65a8c2019-06-07 00:46:02561 std::move(response_headers_), spdy_headers_frame_length);
[email protected]1e960032013-12-20 19:00:20562 }
563
Ryan Hamilton8d9ee76e2018-05-29 23:52:52564 std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseHeadersPacket(
Fan Yangac867502019-01-28 21:10:23565 uint64_t packet_number,
sclittlec4dc1a32015-09-24 00:15:45566 bool fin,
567 size_t* spdy_headers_frame_length) {
ckrasic3865ee0f2016-02-29 22:04:56568 return InnerConstructResponseHeadersPacket(packet_number, stream_id_, fin,
569 spdy_headers_frame_length);
[email protected]1e960032013-12-20 19:00:20570 }
571
Ryan Hamilton8d9ee76e2018-05-29 23:52:52572 std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseTrailersPacket(
Fan Yangac867502019-01-28 21:10:23573 uint64_t packet_number,
xunjieli34291fe12016-03-02 13:58:38574 bool fin,
Bence Béky4c325e52020-10-22 20:48:01575 spdy::Http2HeaderBlock trailers,
Ryan Hamilton0d65a8c2019-06-07 00:46:02576 size_t* spdy_headers_frame_length) {
alyssar2adf3ac2016-05-03 17:12:58577 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26578 packet_number, stream_id_, !kIncludeVersion, fin, std::move(trailers),
Ryan Hamilton0d65a8c2019-06-07 00:46:02579 spdy_headers_frame_length);
xunjieli34291fe12016-03-02 13:58:38580 }
581
Ryan Hamilton8d9ee76e2018-05-29 23:52:52582 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientRstStreamErrorPacket(
Fan Yangac867502019-01-28 21:10:23583 uint64_t packet_number,
maksim.sisov84e20c92016-06-23 08:49:34584 bool include_version) {
585 return client_maker_.MakeRstPacket(packet_number, include_version,
586 stream_id_,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52587 quic::QUIC_ERROR_PROCESSING_STREAM);
maksim.sisov84e20c92016-06-23 08:49:34588 }
589
Ryan Hamilton8d9ee76e2018-05-29 23:52:52590 std::unique_ptr<quic::QuicReceivedPacket> ConstructAckAndRstStreamPacket(
Fan Yangac867502019-01-28 21:10:23591 uint64_t packet_number) {
Renjie Tangcd594f32020-07-11 20:18:34592 return client_maker_.MakeAckAndRstPacket(packet_number, !kIncludeVersion,
593 stream_id_,
594 quic::QUIC_STREAM_CANCELLED, 2, 1);
[email protected]c5e1aca2014-01-30 04:03:04595 }
596
Ryan Hamilton8d9ee76e2018-05-29 23:52:52597 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientAckPacket(
Fan Yangac867502019-01-28 21:10:23598 uint64_t packet_number,
599 uint64_t largest_received,
Renjie Tangcd594f32020-07-11 20:18:34600 uint64_t smallest_received) {
alyssar2adf3ac2016-05-03 17:12:58601 return client_maker_.MakeAckPacket(packet_number, largest_received,
Renjie Tangcd594f32020-07-11 20:18:34602 smallest_received);
alyssar2adf3ac2016-05-03 17:12:58603 }
604
Ryan Hamilton8d9ee76e2018-05-29 23:52:52605 std::unique_ptr<quic::QuicReceivedPacket> ConstructServerAckPacket(
Fan Yangac867502019-01-28 21:10:23606 uint64_t packet_number,
607 uint64_t largest_received,
608 uint64_t smallest_received,
609 uint64_t least_unacked) {
alyssar2adf3ac2016-05-03 17:12:58610 return server_maker_.MakeAckPacket(packet_number, largest_received,
Bence Béky7a45d4d2020-05-08 01:59:23611 smallest_received, least_unacked);
[email protected]63534512012-12-23 18:49:00612 }
613
Ryan Hamilton0d65a8c2019-06-07 00:46:02614 std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket() {
615 return client_maker_.MakeInitialSettingsPacket(1);
fayang3bcb8b502016-12-07 21:44:37616 }
617
Renjie Tangaadb84b2019-08-31 01:00:23618 std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket(
619 int packet_number) {
620 return client_maker_.MakeInitialSettingsPacket(packet_number);
621 }
622
Victor Vasiliev076657c2019-03-12 02:46:43623 std::string ConstructDataHeader(size_t body_len) {
Nick Harperc6cb7a612020-02-24 20:03:32624 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:41625 return "";
626 }
Victor Vasilievc617d452022-03-07 15:54:25627 quiche::QuicheBuffer buffer = quic::HttpEncoder::SerializeDataFrameHeader(
628 body_len, quiche::SimpleBufferAllocator::Get());
Ian Swett17d4d1c02021-06-08 19:52:41629 return std::string(buffer.data(), buffer.size());
Renjief49758b2019-01-11 23:32:41630 }
631
Ryan Hamilton8d9ee76e2018-05-29 23:52:52632 void ReceivePromise(quic::QuicStreamId id) {
633 auto headers = quic::test::AsHeaderList(push_promise_);
rch08e198572017-05-09 16:56:55634 QuicChromiumClientStream::Handle* stream =
ckrasic3865ee0f2016-02-29 22:04:56635 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
ckrasic32b17dcd2016-10-31 06:15:35636 stream->OnPromiseHeaderList(id, headers.uncompressed_header_bytes(),
637 headers);
ckrasic3865ee0f2016-02-29 22:04:56638 }
639
xunjieli84adaab2016-09-20 01:12:28640 void ExpectLoadTimingValid(const LoadTimingInfo& load_timing_info,
xunjieli100937eb52016-09-15 20:09:37641 bool session_reused) {
642 EXPECT_EQ(session_reused, load_timing_info.socket_reused);
xunjieli84adaab2016-09-20 01:12:28643 if (session_reused) {
644 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
645 } else {
646 ExpectConnectTimingHasTimes(
647 load_timing_info.connect_timing,
648 CONNECT_TIMING_HAS_SSL_TIMES | CONNECT_TIMING_HAS_DNS_TIMES);
649 }
650 ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info);
xunjieli100937eb52016-09-15 20:09:37651 }
652
Fan Yang32c5a112018-12-10 20:06:33653 quic::QuicStreamId GetNthClientInitiatedBidirectionalStreamId(int n) {
Nick Harper23290b82019-05-02 00:02:56654 return quic::test::GetNthClientInitiatedBidirectionalStreamId(
655 version_.transport_version, n);
ckrasicbf2f59c2017-05-04 23:54:36656 }
657
Fan Yang32c5a112018-12-10 20:06:33658 quic::QuicStreamId GetNthServerInitiatedUnidirectionalStreamId(int n) {
Nick Harper23290b82019-05-02 00:02:56659 return quic::test::GetNthServerInitiatedUnidirectionalStreamId(
660 version_.transport_version, n);
ckrasicbf2f59c2017-05-04 23:54:36661 }
662
Ryan Hamiltona1d1f4a2019-06-26 14:43:04663 QuicFlagSaver saver_;
664
Nick Harper23290b82019-05-02 00:02:56665 const quic::ParsedQuicVersion version_;
Yixin Wang079ad542018-01-11 04:06:05666 const bool client_headers_include_h2_stream_dependency_;
667
Matt Reichhoff0049a0b72021-10-20 20:44:26668 NetLogWithSource net_log_with_source_{
669 NetLogWithSource::Make(NetLog::Get(), NetLogSourceType::NONE)};
670 RecordingNetLogObserver net_log_observer_;
Keishi Hattori0e45c022021-11-27 09:25:52671 raw_ptr<quic::test::MockSendAlgorithm> send_algorithm_;
[email protected]f702d572012-12-04 15:56:20672 scoped_refptr<TestTaskRunner> runner_;
danakjad1777e2016-04-16 00:56:42673 std::unique_ptr<MockWrite[]> mock_writes_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52674 quic::MockClock clock_;
Keishi Hattori0e45c022021-11-27 09:25:52675 raw_ptr<TestQuicConnection> connection_;
danakjad1777e2016-04-16 00:56:42676 std::unique_ptr<QuicChromiumConnectionHelper> helper_;
rch16c74d1d2016-04-22 06:14:07677 std::unique_ptr<QuicChromiumAlarmFactory> alarm_factory_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52678 testing::StrictMock<quic::test::MockQuicConnectionVisitor> visitor_;
rch97827ee2017-05-24 23:49:12679 std::unique_ptr<UploadDataStream> upload_data_stream_;
danakjad1777e2016-04-16 00:56:42680 std::unique_ptr<QuicHttpStream> stream_;
[email protected]5db452202014-08-19 05:22:15681 TransportSecurityState transport_security_state_;
danakjad1777e2016-04-16 00:56:42682 std::unique_ptr<QuicChromiumClientSession> session_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52683 quic::QuicCryptoClientConfig crypto_config_;
[email protected]f702d572012-12-04 15:56:20684 TestCompletionCallback callback_;
685 HttpRequestInfo request_;
686 HttpRequestHeaders headers_;
687 HttpResponseInfo response_;
688 scoped_refptr<IOBufferWithSize> read_buffer_;
Bence Béky4c325e52020-10-22 20:48:01689 spdy::Http2HeaderBlock request_headers_;
690 spdy::Http2HeaderBlock response_headers_;
bnc614a92d32016-04-04 13:56:07691 string request_data_;
692 string response_data_;
[email protected]f702d572012-12-04 15:56:20693
ckrasic3865ee0f2016-02-29 22:04:56694 // For server push testing
danakjad1777e2016-04-16 00:56:42695 std::unique_ptr<QuicHttpStream> promised_stream_;
Bence Béky4c325e52020-10-22 20:48:01696 spdy::Http2HeaderBlock push_promise_;
697 spdy::Http2HeaderBlock promised_response_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52698 const quic::QuicStreamId promise_id_;
ckrasic3865ee0f2016-02-29 22:04:56699 string promise_url_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52700 const quic::QuicStreamId stream_id_;
ckrasic3865ee0f2016-02-29 22:04:56701
Ryan Hamilton8d9ee76e2018-05-29 23:52:52702 const quic::QuicConnectionId connection_id_;
alyssar2adf3ac2016-05-03 17:12:58703 QuicTestPacketMaker client_maker_;
704 QuicTestPacketMaker server_maker_;
[email protected]f702d572012-12-04 15:56:20705 IPEndPoint self_addr_;
706 IPEndPoint peer_addr_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52707 quic::test::MockRandom random_generator_;
rch03b7a202016-02-05 00:54:20708 ProofVerifyDetailsChromium verify_details_;
[email protected]e8ff26842013-03-22 21:02:05709 MockCryptoClientStreamFactory crypto_client_stream_factory_;
danakjad1777e2016-04-16 00:56:42710 std::unique_ptr<StaticSocketDataProvider> socket_data_;
Ryan Hamilton0d65a8c2019-06-07 00:46:02711 QuicPacketPrinter printer_;
[email protected]f702d572012-12-04 15:56:20712 std::vector<PacketToWrite> writes_;
Bence Béky6e243aa2019-12-13 19:01:07713 quic::test::NoopQpackStreamSenderDelegate noop_qpack_stream_sender_delegate_;
[email protected]f702d572012-12-04 15:56:20714};
715
David Schinazi09e9a6012019-10-03 17:37:57716INSTANTIATE_TEST_SUITE_P(VersionIncludeStreamDependencySequence,
717 QuicHttpStreamTest,
718 ::testing::ValuesIn(GetTestParams()),
719 ::testing::PrintToStringParamName());
[email protected]1e960032013-12-20 19:00:20720
721TEST_P(QuicHttpStreamTest, RenewStreamForAuth) {
[email protected]ed3fc15d2013-03-08 18:37:44722 Initialize();
rtennetibe635732014-10-02 22:51:42723 EXPECT_EQ(nullptr, stream_->RenewStreamForAuth());
[email protected]f702d572012-12-04 15:56:20724}
725
mmenkebd84c392015-09-02 14:12:34726TEST_P(QuicHttpStreamTest, CanReuseConnection) {
[email protected]ed3fc15d2013-03-08 18:37:44727 Initialize();
mmenkebd84c392015-09-02 14:12:34728 EXPECT_FALSE(stream_->CanReuseConnection());
[email protected]f702d572012-12-04 15:56:20729}
730
jri231c2972016-03-08 19:50:11731TEST_P(QuicHttpStreamTest, DisableConnectionMigrationForStream) {
Zhongyi Shibb28b1f2018-07-18 02:41:26732 request_.load_flags |= LOAD_DISABLE_CONNECTION_MIGRATION_TO_CELLULAR;
jri231c2972016-03-08 19:50:11733 Initialize();
Matt Reichhoff0049a0b72021-10-20 20:44:26734 EXPECT_EQ(OK, stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
735 net_log_with_source_,
736 callback_.callback()));
rch08e198572017-05-09 16:56:55737 QuicChromiumClientStream::Handle* client_stream =
jri231c2972016-03-08 19:50:11738 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
Zhongyi Shibb28b1f2018-07-18 02:41:26739 EXPECT_FALSE(client_stream->can_migrate_to_cellular_network());
jri231c2972016-03-08 19:50:11740}
741
[email protected]1e960032013-12-20 19:00:20742TEST_P(QuicHttpStreamTest, GetRequest) {
743 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:45744 size_t spdy_request_header_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:23745 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:25746 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:23747 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:37748 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23749 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
750 kIncludeVersion, kFin, DEFAULT_PRIORITY,
751 &spdy_request_header_frame_length));
fayang3bcb8b502016-12-07 21:44:37752
[email protected]f702d572012-12-04 15:56:20753 Initialize();
754
755 request_.method = "GET";
rchcd379012017-04-12 21:53:32756 request_.url = GURL("https://www.example.org/");
[email protected]f702d572012-12-04 15:56:20757
xunjieli100937eb52016-09-15 20:09:37758 // Make sure getting load timing from the stream early does not crash.
759 LoadTimingInfo load_timing_info;
760 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
761
Matt Reichhoff0049a0b72021-10-20 20:44:26762 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
763 net_log_with_source_,
764 callback_.callback()));
rjshaded5ced072015-12-18 19:26:02765 EXPECT_EQ(OK,
766 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20767
768 // Ack the request.
Renjie90e808e2019-01-24 07:24:04769 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]f702d572012-12-04 15:56:20770
robpercival214763f2016-07-01 23:27:01771 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
772 IsError(ERR_IO_PENDING));
[email protected]f702d572012-12-04 15:56:20773
Kenichi Ishibashif8634ab2021-03-16 23:41:28774 SetResponse("404", string());
sclittlec4dc1a32015-09-24 00:15:45775 size_t spdy_response_header_frame_length;
776 ProcessPacket(ConstructResponseHeadersPacket(
777 2, kFin, &spdy_response_header_frame_length));
[email protected]f702d572012-12-04 15:56:20778
779 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:01780 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]cadac622013-06-11 16:46:36781 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:20782 EXPECT_EQ(404, response_.headers->response_code());
783 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
[email protected]6ed67432014-06-24 01:53:53784 EXPECT_FALSE(response_.response_time.is_null());
785 EXPECT_FALSE(response_.request_time.is_null());
[email protected]f702d572012-12-04 15:56:20786
787 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:02788 EXPECT_EQ(0,
789 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
790 callback_.callback()));
[email protected]f702d572012-12-04 15:56:20791 EXPECT_TRUE(stream_->IsResponseBodyComplete());
792 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:10793
xunjieli100937eb52016-09-15 20:09:37794 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
xunjieli84adaab2016-09-20 01:12:28795 ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
xunjieli100937eb52016-09-15 20:09:37796
sclittle1edeeb22015-09-02 20:46:10797 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:45798 // headers and payload.
799 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
800 stream_->GetTotalSentBytes());
801 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length),
802 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:20803}
804
xunjieli100937eb52016-09-15 20:09:37805TEST_P(QuicHttpStreamTest, LoadTimingTwoRequests) {
806 SetRequest("GET", "/", DEFAULT_PRIORITY);
807 size_t spdy_request_header_frame_length;
808
Renjie Tangaadb84b2019-08-31 01:00:23809 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:25810 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:23811 AddWrite(ConstructInitialSettingsPacket(packet_number++));
xunjieli100937eb52016-09-15 20:09:37812 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23813 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
814 kIncludeVersion, kFin, DEFAULT_PRIORITY,
815 &spdy_request_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37816
817 // SetRequest() again for second request as |request_headers_| was moved.
818 SetRequest("GET", "/", DEFAULT_PRIORITY);
819 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23820 packet_number++, GetNthClientInitiatedBidirectionalStreamId(1),
821 kIncludeVersion, kFin, DEFAULT_PRIORITY,
822 GetNthClientInitiatedBidirectionalStreamId(0),
Ryan Hamilton0d65a8c2019-06-07 00:46:02823 &spdy_request_header_frame_length));
Renjie Tangcd594f32020-07-11 20:18:34824 AddWrite(
825 ConstructClientAckPacket(packet_number++, 3, 1)); // Ack the responses.
xunjieli100937eb52016-09-15 20:09:37826
827 Initialize();
828
829 request_.method = "GET";
rchcd379012017-04-12 21:53:32830 request_.url = GURL("https://www.example.org/");
xunjieli100937eb52016-09-15 20:09:37831 // Start first request.
Matt Reichhoff0049a0b72021-10-20 20:44:26832 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
833 net_log_with_source_,
834 callback_.callback()));
xunjieli100937eb52016-09-15 20:09:37835 EXPECT_EQ(OK,
836 stream_->SendRequest(headers_, &response_, callback_.callback()));
837
838 // Start a second request.
Dan McArdle68a5f622021-07-09 20:56:53839 QuicHttpStream stream2(session_->CreateHandle(url::SchemeHostPort(
840 url::kHttpsScheme, "www.example.org", 443)),
841 {} /* dns_aliases */);
xunjieli100937eb52016-09-15 20:09:37842 TestCompletionCallback callback2;
Matt Reichhoff0049a0b72021-10-20 20:44:26843 EXPECT_EQ(
844 OK, stream2.InitializeStream(&request_, true, DEFAULT_PRIORITY,
845 net_log_with_source_, callback2.callback()));
xunjieli100937eb52016-09-15 20:09:37846 EXPECT_EQ(OK,
847 stream2.SendRequest(headers_, &response_, callback2.callback()));
848
849 // Ack both requests.
Renjie90e808e2019-01-24 07:24:04850 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
xunjieli100937eb52016-09-15 20:09:37851
852 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
853 IsError(ERR_IO_PENDING));
854 size_t spdy_response_header_frame_length;
Kenichi Ishibashif8634ab2021-03-16 23:41:28855 SetResponse("200", string());
xunjieli100937eb52016-09-15 20:09:37856 ProcessPacket(InnerConstructResponseHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33857 2, GetNthClientInitiatedBidirectionalStreamId(0), kFin,
ckrasicbf2f59c2017-05-04 23:54:36858 &spdy_response_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37859
860 // Now that the headers have been processed, the callback will return.
861 EXPECT_THAT(callback_.WaitForResult(), IsOk());
862 EXPECT_EQ(200, response_.headers->response_code());
863
864 // There is no body, so this should return immediately.
865 EXPECT_EQ(0,
866 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
867 callback_.callback()));
868 EXPECT_TRUE(stream_->IsResponseBodyComplete());
869
870 LoadTimingInfo load_timing_info;
871 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
xunjieli84adaab2016-09-20 01:12:28872 ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
xunjieli100937eb52016-09-15 20:09:37873
874 // SetResponse() again for second request as |response_headers_| was moved.
Kenichi Ishibashif8634ab2021-03-16 23:41:28875 SetResponse("200", string());
xunjieli100937eb52016-09-15 20:09:37876 EXPECT_THAT(stream2.ReadResponseHeaders(callback2.callback()),
877 IsError(ERR_IO_PENDING));
878
879 ProcessPacket(InnerConstructResponseHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33880 3, GetNthClientInitiatedBidirectionalStreamId(1), kFin,
ckrasicbf2f59c2017-05-04 23:54:36881 &spdy_response_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37882
883 EXPECT_THAT(callback2.WaitForResult(), IsOk());
884
885 // There is no body, so this should return immediately.
886 EXPECT_EQ(0,
887 stream2.ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
888 callback2.callback()));
889 EXPECT_TRUE(stream2.IsResponseBodyComplete());
890
891 LoadTimingInfo load_timing_info2;
892 EXPECT_TRUE(stream2.GetLoadTimingInfo(&load_timing_info2));
xunjieli84adaab2016-09-20 01:12:28893 ExpectLoadTimingValid(load_timing_info2, /*session_reused=*/true);
xunjieli100937eb52016-09-15 20:09:37894}
895
xunjieli34291fe12016-03-02 13:58:38896// QuicHttpStream does not currently support trailers. It should ignore
897// trailers upon receiving them.
898TEST_P(QuicHttpStreamTest, GetRequestWithTrailers) {
899 SetRequest("GET", "/", DEFAULT_PRIORITY);
900 size_t spdy_request_header_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:23901 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:25902 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:23903 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:37904 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23905 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
906 kIncludeVersion, kFin, DEFAULT_PRIORITY,
907 &spdy_request_header_frame_length));
Renjie Tangcd594f32020-07-11 20:18:34908 AddWrite(
909 ConstructClientAckPacket(packet_number++, 3, 1)); // Ack the data packet.
xunjieli34291fe12016-03-02 13:58:38910
911 Initialize();
912
913 request_.method = "GET";
rchcd379012017-04-12 21:53:32914 request_.url = GURL("https://www.example.org/");
xunjieli34291fe12016-03-02 13:58:38915
Matt Reichhoff0049a0b72021-10-20 20:44:26916 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
917 net_log_with_source_,
918 callback_.callback()));
xunjieli5fafe142016-03-23 23:32:54919
xunjieli34291fe12016-03-02 13:58:38920 EXPECT_EQ(OK,
921 stream_->SendRequest(headers_, &response_, callback_.callback()));
xunjieli34291fe12016-03-02 13:58:38922 // Ack the request.
Renjie90e808e2019-01-24 07:24:04923 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
xunjieli34291fe12016-03-02 13:58:38924
robpercival214763f2016-07-01 23:27:01925 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
926 IsError(ERR_IO_PENDING));
xunjieli34291fe12016-03-02 13:58:38927
Kenichi Ishibashif8634ab2021-03-16 23:41:28928 SetResponse("200", string());
xunjieli34291fe12016-03-02 13:58:38929
930 // Send the response headers.
931 size_t spdy_response_header_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:02932 ProcessPacket(ConstructResponseHeadersPacket(
933 2, !kFin, &spdy_response_header_frame_length));
xunjieli34291fe12016-03-02 13:58:38934 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:01935 EXPECT_THAT(callback_.WaitForResult(), IsOk());
xunjieli34291fe12016-03-02 13:58:38936 ASSERT_TRUE(response_.headers.get());
937 EXPECT_EQ(200, response_.headers->response_code());
938 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
939 EXPECT_FALSE(response_.response_time.is_null());
940 EXPECT_FALSE(response_.request_time.is_null());
941
942 // Send the response body.
943 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:43944 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:17945 ProcessPacket(
946 ConstructServerDataPacket(3, false, !kFin, header + kResponseBody));
Bence Béky4c325e52020-10-22 20:48:01947 spdy::Http2HeaderBlock trailers;
xunjieli34291fe12016-03-02 13:58:38948 size_t spdy_trailers_frame_length;
949 trailers["foo"] = "bar";
Victor Vasiliev7da08172019-10-14 06:04:25950 if (!quic::VersionUsesHttp3(version_.transport_version)) {
Ryan Hamiltona1d1f4a2019-06-26 14:43:04951 trailers[quic::kFinalOffsetHeaderKey] =
952 base::NumberToString(strlen(kResponseBody) + header.length());
953 }
Ryan Hamilton0d65a8c2019-06-07 00:46:02954 ProcessPacket(ConstructResponseTrailersPacket(4, kFin, std::move(trailers),
955 &spdy_trailers_frame_length));
xunjieli34291fe12016-03-02 13:58:38956
957 // Make sure trailers are processed.
fdoray92e35a72016-06-10 15:54:55958 base::RunLoop().RunUntilIdle();
xunjieli34291fe12016-03-02 13:58:38959
960 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
961 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
962 callback_.callback()));
963 EXPECT_TRUE(stream_->IsResponseBodyComplete());
964
965 EXPECT_EQ(OK,
966 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
967 callback_.callback()));
968
969 EXPECT_TRUE(stream_->IsResponseBodyComplete());
970 EXPECT_TRUE(AtEof());
971
972 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
973 // headers and payload.
974 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
975 stream_->GetTotalSentBytes());
Renjief49758b2019-01-11 23:32:41976 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length +
977 strlen(kResponseBody) + header.length() +
978 +spdy_trailers_frame_length),
979 stream_->GetTotalReceivedBytes());
xunjieli5fafe142016-03-23 23:32:54980 // Check that NetLog was filled as expected.
Matt Reichhoff0049a0b72021-10-20 20:44:26981 auto entries = net_log_observer_.GetEntries();
xunjieli5fafe142016-03-23 23:32:54982 size_t pos = ExpectLogContainsSomewhere(
983 entries, /*min_offset=*/0,
mikecirone8b85c432016-09-08 19:11:00984 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
985 NetLogEventPhase::NONE);
xunjieli5fafe142016-03-23 23:32:54986 pos = ExpectLogContainsSomewhere(
987 entries, /*min_offset=*/pos,
mikecirone8b85c432016-09-08 19:11:00988 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
989 NetLogEventPhase::NONE);
xunjieli5fafe142016-03-23 23:32:54990 ExpectLogContainsSomewhere(
991 entries, /*min_offset=*/pos,
mikecirone8b85c432016-09-08 19:11:00992 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
993 NetLogEventPhase::NONE);
xunjieli34291fe12016-03-02 13:58:38994}
995
Bence Béky6c2c78f2020-08-28 16:49:06996TEST_P(QuicHttpStreamTest, ElideHeadersInNetLog) {
997 Initialize();
998
999 // QuicHttp3Logger is only used with HTTP/3.
1000 if (!VersionUsesHttp3(version_.transport_version)) {
1001 return;
1002 }
1003
Matt Reichhoff0049a0b72021-10-20 20:44:261004 net_log_observer_.SetObserverCaptureMode(NetLogCaptureMode::kDefault);
Bence Béky6c2c78f2020-08-28 16:49:061005
Bence Békye0d3747d2020-08-28 23:16:401006 // Send first request.
Bence Béky6c2c78f2020-08-28 16:49:061007 SetRequest("GET", "/", DEFAULT_PRIORITY);
1008 request_.method = "GET";
1009 request_.url = GURL("https://www.example.org/");
1010 headers_.SetHeader(HttpRequestHeaders::kCookie, "secret");
1011
1012 size_t spdy_request_header_frame_length;
Bence Békye0d3747d2020-08-28 23:16:401013 int outgoing_packet_number = 1;
1014 AddWrite(ConstructInitialSettingsPacket(outgoing_packet_number++));
Bence Béky6c2c78f2020-08-28 16:49:061015 AddWrite(InnerConstructRequestHeadersPacket(
Bence Békye0d3747d2020-08-28 23:16:401016 outgoing_packet_number++, stream_id_, kIncludeVersion, kFin,
1017 DEFAULT_PRIORITY, &spdy_request_header_frame_length));
Bence Béky6c2c78f2020-08-28 16:49:061018
Matt Reichhoff0049a0b72021-10-20 20:44:261019 EXPECT_THAT(
1020 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
1021 net_log_with_source_, callback_.callback()),
1022 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>());
Matt Reichhoff0049a0b72021-10-20 20:44:261057 EXPECT_THAT(
1058 stream->InitializeStream(&request_, true, DEFAULT_PRIORITY,
1059 net_log_with_source_, callback_.callback()),
1060 IsOk());
Bence Békye0d3747d2020-08-28 23:16:401061 EXPECT_THAT(stream->SendRequest(headers_, &response_, callback_.callback()),
1062 IsOk());
1063 ProcessPacket(ConstructServerAckPacket(incoming_packet_number++, 1, 1,
1064 1)); // Ack the request.
Bence Béky6c2c78f2020-08-28 16:49:061065
Bence Békye0d3747d2020-08-28 23:16:401066 // Process second response.
Kenichi Ishibashif8634ab2021-03-16 23:41:281067 SetResponse("200", string());
Bence Békye0d3747d2020-08-28 23:16:401068 response_headers_["set-cookie"] = "secret";
1069 ProcessPacket(InnerConstructResponseHeadersPacket(
1070 incoming_packet_number++, stream_id, kFin,
1071 &spdy_response_header_frame_length));
1072 EXPECT_THAT(stream->ReadResponseHeaders(callback_.callback()), IsOk());
Bence Béky6c2c78f2020-08-28 16:49:061073
Bence Békye0d3747d2020-08-28 23:16:401074 ASSERT_TRUE(response_.headers.get());
1075 EXPECT_EQ(200, response_.headers->response_code());
1076 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1077 EXPECT_TRUE(response_.headers->HasHeaderValue("set-cookie", "secret"));
1078
1079 EXPECT_TRUE(AtEof());
1080
1081 // Check that sensitive header value were stripped
1082 // for the first transaction (logged with NetLogCaptureMode::kDefault)
1083 // but not for the second (logged with NetLogCaptureMode::kIncludeSensitive).
1084 auto entries =
Matt Reichhoff0049a0b72021-10-20 20:44:261085 net_log_observer_.GetEntriesWithType(NetLogEventType::HTTP3_HEADERS_SENT);
Bence Békye0d3747d2020-08-28 23:16:401086 ASSERT_EQ(2u, entries.size());
1087 EXPECT_TRUE(
1088 CheckHeader(entries[0].params, "cookie", "[6 bytes were stripped]"));
1089 EXPECT_TRUE(CheckHeader(entries[1].params, "cookie", "secret"));
1090
Matt Reichhoff0049a0b72021-10-20 20:44:261091 entries = net_log_observer_.GetEntriesWithType(
1092 NetLogEventType::HTTP3_HEADERS_DECODED);
Bence Békye0d3747d2020-08-28 23:16:401093 ASSERT_EQ(2u, entries.size());
1094 EXPECT_TRUE(
1095 CheckHeader(entries[0].params, "set-cookie", "[6 bytes were stripped]"));
1096 EXPECT_TRUE(CheckHeader(entries[1].params, "set-cookie", "secret"));
Bence Béky6c2c78f2020-08-28 16:49:061097}
1098
[email protected]3e7dca62013-09-10 16:14:231099// Regression test for http://crbug.com/288128
[email protected]1e960032013-12-20 19:00:201100TEST_P(QuicHttpStreamTest, GetRequestLargeResponse) {
1101 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451102 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231103 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251104 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231105 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371106 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231107 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1108 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1109 &spdy_request_headers_frame_length));
[email protected]3e7dca62013-09-10 16:14:231110 Initialize();
1111
1112 request_.method = "GET";
rchcd379012017-04-12 21:53:321113 request_.url = GURL("https://www.example.org/");
[email protected]3e7dca62013-09-10 16:14:231114
Matt Reichhoff0049a0b72021-10-20 20:44:261115 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
1116 net_log_with_source_,
1117 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021118 EXPECT_EQ(OK,
1119 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:231120
1121 // Ack the request.
Renjie90e808e2019-01-24 07:24:041122 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]3e7dca62013-09-10 16:14:231123
robpercival214763f2016-07-01 23:27:011124 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1125 IsError(ERR_IO_PENDING));
[email protected]3e7dca62013-09-10 16:14:231126
Kenichi Ishibashif8634ab2021-03-16 23:41:281127 response_headers_[":status"] = "200";
bnc086b39e12016-06-24 13:05:261128 response_headers_[":version"] = "HTTP/1.1";
1129 response_headers_["content-type"] = "text/plain";
1130 response_headers_["big6"] = string(1000, 'x'); // Lots of x's.
[email protected]3e7dca62013-09-10 16:14:231131
sclittlec4dc1a32015-09-24 00:15:451132 size_t spdy_response_headers_frame_length;
1133 ProcessPacket(ConstructResponseHeadersPacket(
1134 2, kFin, &spdy_response_headers_frame_length));
[email protected]3e7dca62013-09-10 16:14:231135
1136 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:011137 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]3e7dca62013-09-10 16:14:231138 ASSERT_TRUE(response_.headers.get());
1139 EXPECT_EQ(200, response_.headers->response_code());
1140 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1141
1142 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:021143 EXPECT_EQ(0,
1144 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1145 callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:231146 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1147 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101148
1149 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451150 // headers and payload.
1151 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1152 stream_->GetTotalSentBytes());
1153 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length),
1154 stream_->GetTotalReceivedBytes());
[email protected]3e7dca62013-09-10 16:14:231155}
1156
rchf9f103cbc2014-08-30 05:28:041157// Regression test for http://crbug.com/409101
1158TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendRequest) {
1159 SetRequest("GET", "/", DEFAULT_PRIORITY);
1160 Initialize();
1161
1162 request_.method = "GET";
rchcd379012017-04-12 21:53:321163 request_.url = GURL("https://www.example.org/");
rchf9f103cbc2014-08-30 05:28:041164
Matt Reichhoff0049a0b72021-10-20 20:44:261165 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
1166 net_log_with_source_,
1167 callback_.callback()));
rchf9f103cbc2014-08-30 05:28:041168
jri78ec06a2016-03-31 18:19:401169 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521170 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rchf9f103cbc2014-08-30 05:28:041171
1172 EXPECT_EQ(ERR_CONNECTION_CLOSED,
rjshaded5ced072015-12-18 19:26:021173 stream_->SendRequest(headers_, &response_, callback_.callback()));
sclittle1edeeb22015-09-02 20:46:101174
1175 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1176 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rchf9f103cbc2014-08-30 05:28:041177}
1178
rch03b7a202016-02-05 00:54:201179// Regression test for http://crbug.com/584441
1180TEST_P(QuicHttpStreamTest, GetSSLInfoAfterSessionClosed) {
1181 SetRequest("GET", "/", DEFAULT_PRIORITY);
1182 Initialize();
1183
1184 request_.method = "GET";
rchcd379012017-04-12 21:53:321185 request_.url = GURL("https://www.example.org/");
rch03b7a202016-02-05 00:54:201186
Matt Reichhoff0049a0b72021-10-20 20:44:261187 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
1188 net_log_with_source_,
1189 callback_.callback()));
rch03b7a202016-02-05 00:54:201190
1191 SSLInfo ssl_info;
rch11565e02016-02-09 20:13:471192 EXPECT_FALSE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:201193 stream_->GetSSLInfo(&ssl_info);
rch11565e02016-02-09 20:13:471194 EXPECT_TRUE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:201195
jri78ec06a2016-03-31 18:19:401196 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521197 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rch03b7a202016-02-05 00:54:201198
rch11565e02016-02-09 20:13:471199 SSLInfo ssl_info2;
1200 stream_->GetSSLInfo(&ssl_info2);
1201 EXPECT_TRUE(ssl_info2.is_valid());
rch03b7a202016-02-05 00:54:201202}
1203
rchcd379012017-04-12 21:53:321204TEST_P(QuicHttpStreamTest, GetAlternativeService) {
1205 SetRequest("GET", "/", DEFAULT_PRIORITY);
1206 Initialize();
1207
1208 request_.method = "GET";
1209 request_.url = GURL("https://www.example.org/");
1210
Matt Reichhoff0049a0b72021-10-20 20:44:261211 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
1212 net_log_with_source_,
1213 callback_.callback()));
rchcd379012017-04-12 21:53:321214
1215 AlternativeService alternative_service;
1216 EXPECT_TRUE(stream_->GetAlternativeService(&alternative_service));
1217 EXPECT_EQ(AlternativeService(kProtoQUIC, "www.example.org", 443),
1218 alternative_service);
1219
1220 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521221 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rchcd379012017-04-12 21:53:321222
1223 AlternativeService alternative_service2;
1224 EXPECT_TRUE(stream_->GetAlternativeService(&alternative_service2));
1225 EXPECT_EQ(AlternativeService(kProtoQUIC, "www.example.org", 443),
1226 alternative_service2);
1227}
1228
zhongyica364fbb2015-12-12 03:39:121229TEST_P(QuicHttpStreamTest, LogGranularQuicConnectionError) {
1230 SetRequest("GET", "/", DEFAULT_PRIORITY);
1231 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231232 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251233 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231234 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371235 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231236 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1237 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1238 &spdy_request_headers_frame_length));
fayang3bcb8b502016-12-07 21:44:371239 AddWrite(ConstructAckAndRstStreamPacket(3));
zhongyica364fbb2015-12-12 03:39:121240 Initialize();
1241
1242 request_.method = "GET";
rchcd379012017-04-12 21:53:321243 request_.url = GURL("https://www.example.org/");
zhongyica364fbb2015-12-12 03:39:121244
Matt Reichhoff0049a0b72021-10-20 20:44:261245 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
1246 net_log_with_source_,
1247 callback_.callback()));
zhongyica364fbb2015-12-12 03:39:121248 EXPECT_EQ(OK,
1249 stream_->SendRequest(headers_, &response_, callback_.callback()));
1250
1251 // Ack the request.
Renjie90e808e2019-01-24 07:24:041252 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011253 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1254 IsError(ERR_IO_PENDING));
zhongyica364fbb2015-12-12 03:39:121255
Ryan Hamilton8d9ee76e2018-05-29 23:52:521256 quic::QuicConnectionCloseFrame frame;
Zhongyi Shica576df2019-04-12 17:43:401257 frame.quic_error_code = quic::QUIC_PEER_GOING_AWAY;
rch1c5b74a2016-06-23 22:10:551258 session_->connection()->OnConnectionCloseFrame(frame);
zhongyica364fbb2015-12-12 03:39:121259
1260 NetErrorDetails details;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521261 EXPECT_EQ(quic::QUIC_NO_ERROR, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121262 stream_->PopulateNetErrorDetails(&details);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521263 EXPECT_EQ(quic::QUIC_PEER_GOING_AWAY, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121264}
1265
Ryan Hamiltone316e482017-08-17 02:48:531266TEST_P(QuicHttpStreamTest, LogGranularQuicErrorIfHandshakeNotConfirmed) {
rch617e0652017-04-26 17:57:511267 // By default the test setup defaults handshake to be confirmed. Manually set
1268 // it to be not confirmed.
rch617e0652017-04-26 17:57:511269 crypto_client_stream_factory_.set_handshake_mode(
Ryan Hamilton9835e662018-08-02 05:36:271270 MockCryptoClientStream::ZERO_RTT);
rch617e0652017-04-26 17:57:511271
zhongyica364fbb2015-12-12 03:39:121272 SetRequest("GET", "/", DEFAULT_PRIORITY);
1273 size_t spdy_request_headers_frame_length;
Michael Warres167db3e2019-03-01 21:38:031274 client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
Nick Harper057264a82019-09-12 23:33:491275 client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
1276 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251277 if (VersionUsesHttp3(version_.transport_version))
Nick Harper057264a82019-09-12 23:33:491278 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371279 AddWrite(InnerConstructRequestHeadersPacket(
Nick Harper057264a82019-09-12 23:33:491280 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1281 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1282 &spdy_request_headers_frame_length));
zhongyica364fbb2015-12-12 03:39:121283 Initialize();
1284
1285 request_.method = "GET";
rchcd379012017-04-12 21:53:321286 request_.url = GURL("https://www.example.org/");
zhongyica364fbb2015-12-12 03:39:121287
Matt Reichhoff0049a0b72021-10-20 20:44:261288 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
1289 net_log_with_source_,
1290 callback_.callback()));
zhongyica364fbb2015-12-12 03:39:121291 EXPECT_EQ(OK,
1292 stream_->SendRequest(headers_, &response_, callback_.callback()));
1293
1294 // Ack the request.
Renjie90e808e2019-01-24 07:24:041295 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011296 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1297 IsError(ERR_IO_PENDING));
zhongyica364fbb2015-12-12 03:39:121298
Ryan Hamilton8d9ee76e2018-05-29 23:52:521299 quic::QuicConnectionCloseFrame frame;
Zhongyi Shica576df2019-04-12 17:43:401300 frame.quic_error_code = quic::QUIC_PEER_GOING_AWAY;
rch1c5b74a2016-06-23 22:10:551301 session_->connection()->OnConnectionCloseFrame(frame);
zhongyica364fbb2015-12-12 03:39:121302
1303 NetErrorDetails details;
zhongyica364fbb2015-12-12 03:39:121304 stream_->PopulateNetErrorDetails(&details);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521305 EXPECT_EQ(quic::QUIC_PEER_GOING_AWAY, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121306}
1307
rch11a114a2014-09-04 23:41:591308// Regression test for http://crbug.com/409871
1309TEST_P(QuicHttpStreamTest, SessionClosedBeforeReadResponseHeaders) {
1310 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451311 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231312 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251313 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231314 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371315 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231316 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1317 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1318 &spdy_request_headers_frame_length));
rch11a114a2014-09-04 23:41:591319 Initialize();
1320
1321 request_.method = "GET";
rchcd379012017-04-12 21:53:321322 request_.url = GURL("https://www.example.org/");
rch11a114a2014-09-04 23:41:591323
Matt Reichhoff0049a0b72021-10-20 20:44:261324 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
1325 net_log_with_source_,
1326 callback_.callback()));
rch11a114a2014-09-04 23:41:591327
rjshaded5ced072015-12-18 19:26:021328 EXPECT_EQ(OK,
1329 stream_->SendRequest(headers_, &response_, callback_.callback()));
rch11a114a2014-09-04 23:41:591330
jri78ec06a2016-03-31 18:19:401331 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521332 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rch11a114a2014-09-04 23:41:591333
1334 EXPECT_NE(OK, stream_->ReadResponseHeaders(callback_.callback()));
sclittle1edeeb22015-09-02 20:46:101335
1336 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451337 // headers and payload.
1338 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1339 stream_->GetTotalSentBytes());
sclittle1edeeb22015-09-02 20:46:101340 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rch11a114a2014-09-04 23:41:591341}
1342
[email protected]1e960032013-12-20 19:00:201343TEST_P(QuicHttpStreamTest, SendPostRequest) {
1344 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451345 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231346 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251347 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231348 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Yixin Wange7ecc472018-03-06 19:00:251349
Victor Vasiliev076657c2019-03-12 02:46:431350 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:321351 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411352 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231353 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1354 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1355 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411356 } else {
1357 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231358 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1359 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1360 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411361 }
Yixin Wange7ecc472018-03-06 19:00:251362
Renjie Tangcd594f32020-07-11 20:18:341363 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]f702d572012-12-04 15:56:201364
1365 Initialize();
1366
danakjad1777e2016-04-16 00:56:421367 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:191368 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
ricea2deef682016-09-09 08:04:071369 kUploadData, strlen(kUploadData)));
rch97827ee2017-05-24 23:49:121370 upload_data_stream_ =
Jeremy Roman0579ed62017-08-29 15:56:191371 std::make_unique<ElementsUploadDataStream>(std::move(element_readers), 0);
[email protected]f702d572012-12-04 15:56:201372 request_.method = "POST";
rchcd379012017-04-12 21:53:321373 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121374 request_.upload_data_stream = upload_data_stream_.get();
Bence Békyd8a21fc32018-06-27 18:29:581375 ASSERT_THAT(request_.upload_data_stream->Init(CompletionOnceCallback(),
tfarina42834112016-09-22 13:38:201376 NetLogWithSource()),
1377 IsOk());
[email protected]f702d572012-12-04 15:56:201378
Matt Reichhoff0049a0b72021-10-20 20:44:261379 EXPECT_EQ(OK, stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1380 net_log_with_source_,
1381 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021382 EXPECT_EQ(OK,
1383 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:201384
1385 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041386 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]f702d572012-12-04 15:56:201387
1388 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281389 SetResponse("200", string());
sclittlec4dc1a32015-09-24 00:15:451390 size_t spdy_response_headers_frame_length;
1391 ProcessPacket(ConstructResponseHeadersPacket(
1392 2, !kFin, &spdy_response_headers_frame_length));
[email protected]f702d572012-12-04 15:56:201393
rchfb47f712017-05-21 03:24:001394 // The headers have already arrived.
1395 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]cadac622013-06-11 16:46:361396 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:201397 EXPECT_EQ(200, response_.headers->response_code());
1398 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1399
1400 // Send the response body.
1401 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431402 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:411403 ProcessPacket(
Ryan Hamilton7505eb92019-06-08 00:22:171404 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
[email protected]f702d572012-12-04 15:56:201405 // Since the body has already arrived, this should return immediately.
1406 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
1407 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1408 callback_.callback()));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291409 EXPECT_EQ(0,
1410 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1411 callback_.callback()));
1412
1413 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1414 EXPECT_TRUE(AtEof());
1415
1416 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
1417 // headers and payload.
1418 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411419 strlen(kUploadData) + header.length()),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291420 stream_->GetTotalSentBytes());
1421 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411422 strlen(kResponseBody) + header2.length()),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291423 stream_->GetTotalReceivedBytes());
1424}
1425
1426TEST_P(QuicHttpStreamTest, SendPostRequestAndReceiveSoloFin) {
1427 SetRequest("POST", "/", DEFAULT_PRIORITY);
1428 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231429 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251430 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231431 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431432 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:321433 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411434 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231435 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1436 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1437 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411438 } else {
1439 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231440 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1441 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1442 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411443 }
1444
Renjie Tangcd594f32020-07-11 20:18:341445 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291446
1447 Initialize();
1448
1449 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:191450 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
Ryan Hamilton2ef0a9c2017-07-25 03:18:291451 kUploadData, strlen(kUploadData)));
1452 upload_data_stream_ =
Jeremy Roman0579ed62017-08-29 15:56:191453 std::make_unique<ElementsUploadDataStream>(std::move(element_readers), 0);
Ryan Hamilton2ef0a9c2017-07-25 03:18:291454 request_.method = "POST";
1455 request_.url = GURL("https://www.example.org/");
1456 request_.upload_data_stream = upload_data_stream_.get();
Bence Békyd8a21fc32018-06-27 18:29:581457 ASSERT_THAT(request_.upload_data_stream->Init(CompletionOnceCallback(),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291458 NetLogWithSource()),
1459 IsOk());
1460
Matt Reichhoff0049a0b72021-10-20 20:44:261461 EXPECT_EQ(OK, stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1462 net_log_with_source_,
1463 callback_.callback()));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291464 EXPECT_EQ(OK,
1465 stream_->SendRequest(headers_, &response_, callback_.callback()));
1466
1467 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041468 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291469
1470 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281471 SetResponse("200", string());
Ryan Hamilton2ef0a9c2017-07-25 03:18:291472 size_t spdy_response_headers_frame_length;
1473 ProcessPacket(ConstructResponseHeadersPacket(
1474 2, !kFin, &spdy_response_headers_frame_length));
1475
1476 // The headers have already arrived.
1477 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
1478 ASSERT_TRUE(response_.headers.get());
1479 EXPECT_EQ(200, response_.headers->response_code());
1480 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1481
1482 // Send the response body.
1483 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431484 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:411485 ProcessPacket(
Ryan Hamilton7505eb92019-06-08 00:22:171486 ConstructServerDataPacket(3, false, !kFin, header2 + kResponseBody));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291487 // Since the body has already arrived, this should return immediately.
1488 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
1489 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1490 callback_.callback()));
Ryan Hamilton7505eb92019-06-08 00:22:171491 ProcessPacket(ConstructServerDataPacket(4, false, kFin, ""));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291492 EXPECT_EQ(0,
1493 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1494 callback_.callback()));
[email protected]f702d572012-12-04 15:56:201495
1496 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1497 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101498
1499 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451500 // headers and payload.
1501 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411502 strlen(kUploadData) + header.length()),
sclittle1edeeb22015-09-02 20:46:101503 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451504 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411505 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101506 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:201507}
1508
[email protected]1e960032013-12-20 19:00:201509TEST_P(QuicHttpStreamTest, SendChunkedPostRequest) {
1510 SetRequest("POST", "/", DEFAULT_PRIORITY);
[email protected]c9e49a02013-02-26 05:56:471511 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:451512 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231513 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251514 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231515 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431516 std::string header = ConstructDataHeader(chunk_size);
Nick Harperc6cb7a612020-02-24 20:03:321517 if (version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411518 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231519 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1520 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1521 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjie Tangd5133972019-12-06 00:20:281522 AddWrite(ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin,
1523 {header + kUploadData}));
Renjief49758b2019-01-11 23:32:411524 } else {
1525 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231526 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1527 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1528 &spdy_request_headers_frame_length, {kUploadData}));
1529 AddWrite(ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin,
1530 kUploadData));
Renjief49758b2019-01-11 23:32:411531 }
1532
Renjie Tangcd594f32020-07-11 20:18:341533 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]c9e49a02013-02-26 05:56:471534 Initialize();
1535
Jeremy Roman0579ed62017-08-29 15:56:191536 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121537 auto* chunked_upload_stream =
1538 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1539 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
[email protected]c9e49a02013-02-26 05:56:471540
1541 request_.method = "POST";
rchcd379012017-04-12 21:53:321542 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121543 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071544 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201545 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]c9e49a02013-02-26 05:56:471546
Matt Reichhoff0049a0b72021-10-20 20:44:261547 ASSERT_EQ(OK, stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1548 net_log_with_source_,
1549 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021550 ASSERT_EQ(ERR_IO_PENDING,
1551 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]c9e49a02013-02-26 05:56:471552
rch97827ee2017-05-24 23:49:121553 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
robpercival214763f2016-07-01 23:27:011554 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]c9e49a02013-02-26 05:56:471555
1556 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041557 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]c9e49a02013-02-26 05:56:471558
1559 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281560 SetResponse("200", string());
sclittlec4dc1a32015-09-24 00:15:451561 size_t spdy_response_headers_frame_length;
1562 ProcessPacket(ConstructResponseHeadersPacket(
1563 2, !kFin, &spdy_response_headers_frame_length));
[email protected]c9e49a02013-02-26 05:56:471564
rchfb47f712017-05-21 03:24:001565 // The headers have already arrived.
1566 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]cadac622013-06-11 16:46:361567 ASSERT_TRUE(response_.headers.get());
[email protected]c9e49a02013-02-26 05:56:471568 EXPECT_EQ(200, response_.headers->response_code());
1569 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1570
1571 // Send the response body.
1572 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431573 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171574 ProcessPacket(
1575 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
[email protected]c9e49a02013-02-26 05:56:471576
1577 // Since the body has already arrived, this should return immediately.
1578 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1579 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1580 callback_.callback()));
1581
1582 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1583 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101584
1585 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451586 // headers and payload.
1587 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411588 strlen(kUploadData) * 2 + header.length() * 2),
sclittle1edeeb22015-09-02 20:46:101589 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451590 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411591 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101592 stream_->GetTotalReceivedBytes());
[email protected]c9e49a02013-02-26 05:56:471593}
1594
[email protected]16ba7742014-08-22 00:57:251595TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithFinalEmptyDataPacket) {
1596 SetRequest("POST", "/", DEFAULT_PRIORITY);
1597 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:451598 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231599 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251600 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231601 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431602 std::string header = ConstructDataHeader(chunk_size);
Renjief49758b2019-01-11 23:32:411603
Nick Harperc6cb7a612020-02-24 20:03:321604 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411605 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231606 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1607 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1608 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411609 } else {
1610 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231611 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1612 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1613 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411614 }
Renjie Tangaadb84b2019-08-31 01:00:231615 AddWrite(
1616 ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin, ""));
Renjie Tangcd594f32020-07-11 20:18:341617 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]16ba7742014-08-22 00:57:251618 Initialize();
1619
Jeremy Roman0579ed62017-08-29 15:56:191620 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121621 auto* chunked_upload_stream =
1622 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1623 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
[email protected]16ba7742014-08-22 00:57:251624
1625 request_.method = "POST";
rchcd379012017-04-12 21:53:321626 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121627 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071628 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201629 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]16ba7742014-08-22 00:57:251630
Matt Reichhoff0049a0b72021-10-20 20:44:261631 ASSERT_EQ(OK, stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1632 net_log_with_source_,
1633 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021634 ASSERT_EQ(ERR_IO_PENDING,
1635 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251636
rch97827ee2017-05-24 23:49:121637 chunked_upload_stream->AppendData(nullptr, 0, true);
robpercival214763f2016-07-01 23:27:011638 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]16ba7742014-08-22 00:57:251639
Renjie90e808e2019-01-24 07:24:041640 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]16ba7742014-08-22 00:57:251641
1642 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281643 SetResponse("200", string());
sclittlec4dc1a32015-09-24 00:15:451644 size_t spdy_response_headers_frame_length;
1645 ProcessPacket(ConstructResponseHeadersPacket(
1646 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251647
rchfb47f712017-05-21 03:24:001648 // The headers have already arrived.
1649 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]16ba7742014-08-22 00:57:251650 ASSERT_TRUE(response_.headers.get());
1651 EXPECT_EQ(200, response_.headers->response_code());
1652 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1653
1654 // Send the response body.
1655 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431656 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171657 ProcessPacket(
1658 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
[email protected]16ba7742014-08-22 00:57:251659
rchb27683c2015-07-29 23:53:501660 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251661 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1662 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1663 callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251664 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1665 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101666
1667 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451668 // headers and payload.
1669 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411670 strlen(kUploadData) + header.length()),
sclittle1edeeb22015-09-02 20:46:101671 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451672 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411673 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101674 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251675}
1676
1677TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithOneEmptyDataPacket) {
1678 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451679 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231680 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251681 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231682 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371683 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231684 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1685 kIncludeVersion, !kFin, DEFAULT_PRIORITY,
1686 &spdy_request_headers_frame_length));
1687 AddWrite(
1688 ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin, ""));
Renjie Tangcd594f32020-07-11 20:18:341689 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]16ba7742014-08-22 00:57:251690 Initialize();
1691
Jeremy Roman0579ed62017-08-29 15:56:191692 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121693 auto* chunked_upload_stream =
1694 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
[email protected]16ba7742014-08-22 00:57:251695
1696 request_.method = "POST";
rchcd379012017-04-12 21:53:321697 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121698 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071699 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201700 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]16ba7742014-08-22 00:57:251701
Matt Reichhoff0049a0b72021-10-20 20:44:261702 ASSERT_EQ(OK, stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1703 net_log_with_source_,
1704 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021705 ASSERT_EQ(ERR_IO_PENDING,
1706 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251707
rch97827ee2017-05-24 23:49:121708 chunked_upload_stream->AppendData(nullptr, 0, true);
robpercival214763f2016-07-01 23:27:011709 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]16ba7742014-08-22 00:57:251710
Renjie90e808e2019-01-24 07:24:041711 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]16ba7742014-08-22 00:57:251712
1713 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281714 SetResponse("200", string());
sclittlec4dc1a32015-09-24 00:15:451715 size_t spdy_response_headers_frame_length;
1716 ProcessPacket(ConstructResponseHeadersPacket(
1717 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251718
rchfb47f712017-05-21 03:24:001719 // The headers have already arrived.
1720 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]16ba7742014-08-22 00:57:251721 ASSERT_TRUE(response_.headers.get());
1722 EXPECT_EQ(200, response_.headers->response_code());
1723 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1724
1725 // Send the response body.
1726 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431727 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171728 ProcessPacket(
1729 ConstructServerDataPacket(3, false, kFin, header + kResponseBody));
[email protected]16ba7742014-08-22 00:57:251730
rchb27683c2015-07-29 23:53:501731 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251732 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1733 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1734 callback_.callback()));
1735
1736 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1737 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101738
1739 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451740 // headers and payload.
1741 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1742 stream_->GetTotalSentBytes());
1743 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411744 strlen(kResponseBody) + header.length()),
sclittle1edeeb22015-09-02 20:46:101745 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251746}
1747
Bence Békye3c6f122020-05-08 01:09:471748TEST_P(QuicHttpStreamTest, SendChunkedPostRequestAbortedByResetStream) {
1749 SetRequest("POST", "/", DEFAULT_PRIORITY);
1750 size_t chunk_size = strlen(kUploadData);
1751 size_t spdy_request_headers_frame_length;
1752 int packet_number = 1;
1753
1754 if (version_.UsesHttp3()) {
1755 AddWrite(ConstructInitialSettingsPacket(packet_number++));
1756 }
1757
1758 std::string header = ConstructDataHeader(chunk_size);
1759 if (version_.HasIetfQuicFrames()) {
1760 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1761 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1762 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1763 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjie Tangcd594f32020-07-11 20:18:341764 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
Fan Yang8d4177792021-07-16 17:48:531765 AddWrite(client_maker_.MakeAckAndRstPacket(
1766 packet_number++, true, stream_id_, quic::QUIC_STREAM_NO_ERROR, 4, 1,
Renjie Tangcd594f32020-07-11 20:18:341767 /* include_stop_sending_if_v99 = */ false));
Bence Békye3c6f122020-05-08 01:09:471768 } else {
1769 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1770 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1771 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1772 &spdy_request_headers_frame_length, {kUploadData}));
Renjie Tangcd594f32020-07-11 20:18:341773 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
Bence Békye3c6f122020-05-08 01:09:471774 AddWrite(client_maker_.MakeAckAndRstPacket(
1775 packet_number++,
1776 /* include_version = */ false, stream_id_,
Renjie Tangcd594f32020-07-11 20:18:341777 quic::QUIC_RST_ACKNOWLEDGEMENT, 4, 1,
Bence Békye3c6f122020-05-08 01:09:471778 /* include_stop_sending_if_v99 = */ false));
1779 }
1780
1781 Initialize();
1782
1783 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
1784 auto* chunked_upload_stream =
1785 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1786 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
1787
1788 request_.method = "POST";
1789 request_.url = GURL("https://www.example.org/");
1790 request_.upload_data_stream = upload_data_stream_.get();
1791 ASSERT_THAT(request_.upload_data_stream->Init(
1792 TestCompletionCallback().callback(), NetLogWithSource()),
1793 IsOk());
Matt Reichhoff0049a0b72021-10-20 20:44:261794 ASSERT_THAT(
1795 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1796 net_log_with_source_, callback_.callback()),
1797 IsOk());
Bence Békye3c6f122020-05-08 01:09:471798 ASSERT_THAT(stream_->SendRequest(headers_, &response_, callback_.callback()),
1799 IsError(ERR_IO_PENDING));
1800
1801 // Ack both packets in the request.
1802 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
1803
1804 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281805 SetResponse("200", string());
Bence Békye3c6f122020-05-08 01:09:471806 size_t spdy_response_headers_frame_length;
1807 ProcessPacket(ConstructResponseHeadersPacket(
1808 2, !kFin, &spdy_response_headers_frame_length));
1809
1810 // Send the response body.
1811 const char kResponseBody[] = "Hello world!";
1812 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
1813 ProcessPacket(
1814 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
1815
Bence Béky050ec6d2021-02-25 22:07:051816 if (version_.HasIetfQuicFrames()) {
1817 // In IETF QUIC, the server uses a STOP_SENDING frame to notify the client
1818 // that it does not need any further data to fully process the request.
1819 ProcessPacket(server_maker_.MakeStopSendingPacket(
1820 4, /* include_version = */ false, stream_id_,
1821 quic::QUIC_STREAM_NO_ERROR));
1822 } else {
1823 // Server resets stream with H3_NO_ERROR before request body is complete.
1824 ProcessPacket(server_maker_.MakeRstPacket(4, /* include_version = */ false,
1825 stream_id_,
1826 quic::QUIC_STREAM_NO_ERROR));
1827 }
Bence Békye3c6f122020-05-08 01:09:471828
1829 // Finish feeding request body to QuicHttpStream. Data will be discarded.
1830 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1831 EXPECT_THAT(callback_.WaitForResult(), IsOk());
1832
1833 // Verify response.
1834 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
1835 ASSERT_TRUE(response_.headers.get());
1836 EXPECT_EQ(200, response_.headers->response_code());
1837 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1838 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1839 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1840 callback_.callback()));
1841 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1842 EXPECT_TRUE(AtEof());
1843
1844 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
1845 // headers and payload.
1846 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
1847 strlen(kUploadData) + header.length()),
1848 stream_->GetTotalSentBytes());
1849 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1850 strlen(kResponseBody) + header2.length()),
1851 stream_->GetTotalReceivedBytes());
1852}
1853
[email protected]1e960032013-12-20 19:00:201854TEST_P(QuicHttpStreamTest, DestroyedEarly) {
1855 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451856 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231857 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251858 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231859 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371860 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231861 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1862 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1863 &spdy_request_headers_frame_length));
1864 AddWrite(ConstructAckAndRstStreamPacket(packet_number++));
[email protected]63534512012-12-23 18:49:001865 Initialize();
1866
1867 request_.method = "GET";
rchcd379012017-04-12 21:53:321868 request_.url = GURL("https://www.example.org/");
[email protected]63534512012-12-23 18:49:001869
Matt Reichhoff0049a0b72021-10-20 20:44:261870 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
1871 net_log_with_source_,
1872 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021873 EXPECT_EQ(OK,
1874 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]63534512012-12-23 18:49:001875
1876 // Ack the request.
Renjie90e808e2019-01-24 07:24:041877 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
rchfb47f712017-05-21 03:24:001878 EXPECT_THAT(stream_->ReadResponseHeaders(
Yannic Bonenberger3c96beb2019-09-03 20:41:371879 base::BindOnce(&QuicHttpStreamTest::CloseStream,
1880 base::Unretained(this), stream_.get())),
robpercival214763f2016-07-01 23:27:011881 IsError(ERR_IO_PENDING));
[email protected]63534512012-12-23 18:49:001882
1883 // Send the response with a body.
Kenichi Ishibashif8634ab2021-03-16 23:41:281884 SetResponse("404", "hello world!");
[email protected]63534512012-12-23 18:49:001885 // In the course of processing this packet, the QuicHttpStream close itself.
rchfb47f712017-05-21 03:24:001886 size_t response_size = 0;
rch1bcfddf22017-06-03 00:26:291887 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin, &response_size));
[email protected]63534512012-12-23 18:49:001888
fdoray92e35a72016-06-10 15:54:551889 base::RunLoop().RunUntilIdle();
rchb27683c2015-07-29 23:53:501890
[email protected]63534512012-12-23 18:49:001891 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101892
1893 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451894 // headers and payload.
1895 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1896 stream_->GetTotalSentBytes());
rchfb47f712017-05-21 03:24:001897 // The stream was closed after receiving the headers.
1898 EXPECT_EQ(static_cast<int64_t>(response_size),
1899 stream_->GetTotalReceivedBytes());
[email protected]63534512012-12-23 18:49:001900}
1901
[email protected]1e960032013-12-20 19:00:201902TEST_P(QuicHttpStreamTest, Priority) {
1903 SetRequest("GET", "/", MEDIUM);
sclittlec4dc1a32015-09-24 00:15:451904 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231905 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251906 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231907 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371908 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231909 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1910 kIncludeVersion, kFin, MEDIUM, &spdy_request_headers_frame_length));
[email protected]24e5bc52013-09-18 15:36:581911 Initialize();
1912
1913 request_.method = "GET";
rchcd379012017-04-12 21:53:321914 request_.url = GURL("https://www.example.org/");
[email protected]24e5bc52013-09-18 15:36:581915
Matt Reichhoff0049a0b72021-10-20 20:44:261916 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, MEDIUM,
1917 net_log_with_source_,
1918 callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581919
rjshaded5ced072015-12-18 19:26:021920 EXPECT_EQ(OK,
1921 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581922
[email protected]24e5bc52013-09-18 15:36:581923 // Ack the request.
Renjie90e808e2019-01-24 07:24:041924 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011925 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1926 IsError(ERR_IO_PENDING));
[email protected]24e5bc52013-09-18 15:36:581927
1928 // Send the response with a body.
Kenichi Ishibashif8634ab2021-03-16 23:41:281929 SetResponse("404", "hello world!");
rchfb47f712017-05-21 03:24:001930 size_t response_size = 0;
1931 ProcessPacket(ConstructResponseHeadersPacket(2, kFin, &response_size));
[email protected]24e5bc52013-09-18 15:36:581932
rchfb47f712017-05-21 03:24:001933 EXPECT_EQ(OK, callback_.WaitForResult());
rchb27683c2015-07-29 23:53:501934
[email protected]24e5bc52013-09-18 15:36:581935 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101936
1937 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451938 // headers and payload.
1939 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1940 stream_->GetTotalSentBytes());
rchfb47f712017-05-21 03:24:001941 EXPECT_EQ(static_cast<int64_t>(response_size),
1942 stream_->GetTotalReceivedBytes());
[email protected]24e5bc52013-09-18 15:36:581943}
1944
xunjieli8dff50b2016-07-22 14:19:061945TEST_P(QuicHttpStreamTest, SessionClosedDuringDoLoop) {
1946 SetRequest("POST", "/", DEFAULT_PRIORITY);
1947 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231948 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251949 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231950 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431951 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:321952 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411953 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231954 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1955 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1956 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411957 } else {
1958 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231959 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1960 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1961 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411962 }
1963
xunjieli8dff50b2016-07-22 14:19:061964 // Second data write will result in a synchronous failure which will close
1965 // the session.
1966 AddWrite(SYNCHRONOUS, ERR_FAILED);
1967 Initialize();
1968
Jeremy Roman0579ed62017-08-29 15:56:191969 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121970 auto* chunked_upload_stream =
1971 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
xunjieli8dff50b2016-07-22 14:19:061972
1973 request_.method = "POST";
rchcd379012017-04-12 21:53:321974 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121975 request_.upload_data_stream = upload_data_stream_.get();
xunjieli8dff50b2016-07-22 14:19:061976 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201977 TestCompletionCallback().callback(), NetLogWithSource()));
xunjieli8dff50b2016-07-22 14:19:061978
1979 size_t chunk_size = strlen(kUploadData);
rch97827ee2017-05-24 23:49:121980 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
Matt Reichhoff0049a0b72021-10-20 20:44:261981 ASSERT_EQ(OK, stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1982 net_log_with_source_,
1983 callback_.callback()));
xunjieli8dff50b2016-07-22 14:19:061984 QuicHttpStream* stream = stream_.get();
1985 DeleteStreamCallback delete_stream_callback(std::move(stream_));
1986 // SendRequest() completes asynchronously after the final chunk is added.
Yixin Wange7ecc472018-03-06 19:00:251987 // Error does not surface yet since packet write is triggered by a packet
1988 // flusher that tries to bundle request body writes.
xunjieli8dff50b2016-07-22 14:19:061989 ASSERT_EQ(ERR_IO_PENDING,
1990 stream->SendRequest(headers_, &response_, callback_.callback()));
rch97827ee2017-05-24 23:49:121991 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
xunjieli8dff50b2016-07-22 14:19:061992 int rv = callback_.WaitForResult();
Yixin Wange7ecc472018-03-06 19:00:251993 EXPECT_EQ(OK, rv);
1994 // Error will be surfaced once an attempt to read the response occurs.
1995 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1996 stream->ReadResponseHeaders(callback_.callback()));
xunjieli8dff50b2016-07-22 14:19:061997}
1998
rtenneti15656ae2016-01-23 03:05:031999TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersComplete) {
2000 SetRequest("POST", "/", DEFAULT_PRIORITY);
Victor Vasiliev7da08172019-10-14 06:04:252001 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232002 AddWrite(ConstructInitialSettingsPacket());
rtenneti15656ae2016-01-23 03:05:032003 AddWrite(SYNCHRONOUS, ERR_FAILED);
2004 Initialize();
2005
Jeremy Roman0579ed62017-08-29 15:56:192006 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
Yixin Wange7ecc472018-03-06 19:00:252007 auto* chunked_upload_stream =
2008 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
rtenneti15656ae2016-01-23 03:05:032009
2010 request_.method = "POST";
rchcd379012017-04-12 21:53:322011 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122012 request_.upload_data_stream = upload_data_stream_.get();
rtenneti15656ae2016-01-23 03:05:032013 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202014 TestCompletionCallback().callback(), NetLogWithSource()));
rtenneti15656ae2016-01-23 03:05:032015
Matt Reichhoff0049a0b72021-10-20 20:44:262016 ASSERT_EQ(OK, stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
2017 net_log_with_source_,
2018 callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252019 ASSERT_EQ(ERR_IO_PENDING,
rtenneti15656ae2016-01-23 03:05:032020 stream_->SendRequest(headers_, &response_, callback_.callback()));
mmenkeffff3642017-06-15 17:37:242021
Yixin Wange7ecc472018-03-06 19:00:252022 // Error will be surfaced once |upload_data_stream| triggers the next write.
2023 size_t chunk_size = strlen(kUploadData);
2024 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2025 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR, callback_.WaitForResult());
2026
2027 EXPECT_LE(0, stream_->GetTotalSentBytes());
2028 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2029}
2030
2031TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersCompleteReadResponse) {
2032 SetRequest("POST", "/", DEFAULT_PRIORITY);
Victor Vasiliev7da08172019-10-14 06:04:252033 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232034 AddWrite(ConstructInitialSettingsPacket());
Yixin Wange7ecc472018-03-06 19:00:252035 AddWrite(SYNCHRONOUS, ERR_FAILED);
2036 Initialize();
2037
2038 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
2039 auto* chunked_upload_stream =
2040 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
2041
2042 request_.method = "POST";
2043 request_.url = GURL("https://www.example.org/");
2044 request_.upload_data_stream = upload_data_stream_.get();
2045
2046 size_t chunk_size = strlen(kUploadData);
2047 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2048
2049 ASSERT_EQ(OK, request_.upload_data_stream->Init(
2050 TestCompletionCallback().callback(), NetLogWithSource()));
2051
Matt Reichhoff0049a0b72021-10-20 20:44:262052 ASSERT_EQ(OK, stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
2053 net_log_with_source_,
2054 callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252055 ASSERT_EQ(OK,
2056 stream_->SendRequest(headers_, &response_, callback_.callback()));
2057
2058 // Error will be surfaced once an attempt to read the response occurs.
2059 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
2060 stream_->ReadResponseHeaders(callback_.callback()));
2061
mmenkeffff3642017-06-15 17:37:242062 EXPECT_LE(0, stream_->GetTotalSentBytes());
2063 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rtenneti15656ae2016-01-23 03:05:032064}
2065
2066TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBodyComplete) {
2067 SetRequest("POST", "/", DEFAULT_PRIORITY);
2068 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232069 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252070 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232071 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:372072 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:232073 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2074 kIncludeVersion, !kFin, DEFAULT_PRIORITY,
2075 &spdy_request_headers_frame_length));
rtenneti15656ae2016-01-23 03:05:032076 AddWrite(SYNCHRONOUS, ERR_FAILED);
2077 Initialize();
2078
Jeremy Roman0579ed62017-08-29 15:56:192079 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:122080 auto* chunked_upload_stream =
2081 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
rtenneti15656ae2016-01-23 03:05:032082
2083 request_.method = "POST";
rchcd379012017-04-12 21:53:322084 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122085 request_.upload_data_stream = upload_data_stream_.get();
rtenneti15656ae2016-01-23 03:05:032086 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202087 TestCompletionCallback().callback(), NetLogWithSource()));
rtenneti15656ae2016-01-23 03:05:032088
Matt Reichhoff0049a0b72021-10-20 20:44:262089 ASSERT_EQ(OK, stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
2090 net_log_with_source_,
2091 callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252092 ASSERT_EQ(ERR_IO_PENDING,
rtenneti15656ae2016-01-23 03:05:032093 stream_->SendRequest(headers_, &response_, callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252094
2095 size_t chunk_size = strlen(kUploadData);
2096 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2097 // Error does not surface yet since packet write is triggered by a packet
2098 // flusher that tries to bundle request body writes.
2099 ASSERT_EQ(OK, callback_.WaitForResult());
2100 // Error will be surfaced once an attempt to read the response occurs.
2101 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
2102 stream_->ReadResponseHeaders(callback_.callback()));
2103
2104 EXPECT_LE(0, stream_->GetTotalSentBytes());
2105 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2106}
2107
2108TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBundledBodyComplete) {
2109 SetRequest("POST", "/", DEFAULT_PRIORITY);
2110 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232111 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252112 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232113 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:432114 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:322115 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:412116 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:232117 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2118 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
2119 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:412120 } else {
2121 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:232122 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2123 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
2124 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:412125 }
2126
Yixin Wange7ecc472018-03-06 19:00:252127 AddWrite(SYNCHRONOUS, ERR_FAILED);
2128 Initialize();
2129
2130 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
2131 auto* chunked_upload_stream =
2132 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
2133
2134 request_.method = "POST";
2135 request_.url = GURL("https://www.example.org/");
2136 request_.upload_data_stream = upload_data_stream_.get();
2137
2138 size_t chunk_size = strlen(kUploadData);
2139 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
2140
2141 ASSERT_EQ(OK, request_.upload_data_stream->Init(
2142 TestCompletionCallback().callback(), NetLogWithSource()));
2143
Matt Reichhoff0049a0b72021-10-20 20:44:262144 ASSERT_EQ(OK, stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
2145 net_log_with_source_,
2146 callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252147 ASSERT_EQ(ERR_IO_PENDING,
2148 stream_->SendRequest(headers_, &response_, callback_.callback()));
2149
2150 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2151
2152 // Error does not surface yet since packet write is triggered by a packet
2153 // flusher that tries to bundle request body writes.
2154 ASSERT_EQ(OK, callback_.WaitForResult());
2155 // Error will be surfaced once an attempt to read the response occurs.
2156 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
2157 stream_->ReadResponseHeaders(callback_.callback()));
2158
2159 EXPECT_LE(0, stream_->GetTotalSentBytes());
2160 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rtenneti15656ae2016-01-23 03:05:032161}
2162
ckrasic3865ee0f2016-02-29 22:04:562163TEST_P(QuicHttpStreamTest, ServerPushGetRequest) {
2164 SetRequest("GET", "/", DEFAULT_PRIORITY);
2165 Initialize();
2166
Bin Wue8408792021-08-24 23:25:162167 // Server push is not supported in HTTP/3.
2168 if (version_.UsesHttp3())
2169 return;
2170
ckrasic3865ee0f2016-02-29 22:04:562171 // Initialize the first stream, for receiving the promise on.
2172 request_.method = "GET";
rchcd379012017-04-12 21:53:322173 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562174
Matt Reichhoff0049a0b72021-10-20 20:44:262175 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
2176 net_log_with_source_,
2177 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232178 ASSERT_EQ(OK,
2179 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562180
2181 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2182 // packet, but does it matter?
2183 ReceivePromise(promise_id_);
2184 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2185
2186 request_.url = GURL(promise_url_);
2187
2188 // Make the second stream that will exercise the first step of the
2189 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272190 EXPECT_EQ(OK, promised_stream_->InitializeStream(
Matt Reichhoff0049a0b72021-10-20 20:44:262191 &request_, true, DEFAULT_PRIORITY, net_log_with_source_,
Steven Valdezb4ff0412018-01-18 22:39:272192 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562193
2194 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252195 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562196 size_t spdy_response_headers_frame_length;
2197 ProcessPacket(InnerConstructResponseHeadersPacket(
2198 1, promise_id_, false, &spdy_response_headers_frame_length));
2199
2200 // Receive the promised response body.
2201 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432202 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172203 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2204 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562205
2206 // Now sending a matching request will have successful rendezvous
2207 // with the promised stream.
Ryan Hamiltona1d1f4a2019-06-26 14:43:042208 ASSERT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
ckrasic3865ee0f2016-02-29 22:04:562209 callback_.callback()));
2210
2211 EXPECT_EQ(
2212 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2213 ->id(),
2214 promise_id_);
2215
2216 // The headers will be immediately available.
robpercival214763f2016-07-01 23:27:012217 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2218 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562219
2220 // As will be the body.
2221 EXPECT_EQ(
2222 static_cast<int>(strlen(kResponseBody)),
2223 promised_stream_->ReadResponseBody(
2224 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2225 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2226 EXPECT_TRUE(AtEof());
2227
ckrasic3865ee0f2016-02-29 22:04:562228 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2229 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412230 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562231 promised_stream_->GetTotalReceivedBytes());
2232}
2233
2234TEST_P(QuicHttpStreamTest, ServerPushGetRequestSlowResponse) {
2235 SetRequest("GET", "/", DEFAULT_PRIORITY);
2236 Initialize();
2237
Bin Wue8408792021-08-24 23:25:162238 // Server push is not supported in HTTP/3.
2239 if (version_.UsesHttp3())
2240 return;
2241
ckrasic3865ee0f2016-02-29 22:04:562242 // Initialize the first stream, for receiving the promise on.
2243 request_.method = "GET";
rchcd379012017-04-12 21:53:322244 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562245
Matt Reichhoff0049a0b72021-10-20 20:44:262246 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
2247 net_log_with_source_,
2248 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232249 ASSERT_EQ(OK,
2250 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562251
2252 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2253 // packet, but does it matter?
2254 ReceivePromise(promise_id_);
2255 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2256
2257 request_.url = GURL(promise_url_);
2258
2259 // Make the second stream that will exercise the first step of the
2260 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272261 EXPECT_EQ(OK, promised_stream_->InitializeStream(
Matt Reichhoff0049a0b72021-10-20 20:44:262262 &request_, true, DEFAULT_PRIORITY, net_log_with_source_,
Steven Valdezb4ff0412018-01-18 22:39:272263 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562264
2265 // Now sending a matching request will rendezvous with the promised
2266 // stream, but pending secondary validation.
2267 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2268 headers_, &response_, callback_.callback()));
2269
2270 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252271 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562272 size_t spdy_response_headers_frame_length;
2273 ProcessPacket(InnerConstructResponseHeadersPacket(
2274 1, promise_id_, false, &spdy_response_headers_frame_length));
2275
2276 // Receive the promised response body.
2277 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432278 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172279 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2280 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562281
fdoray92e35a72016-06-10 15:54:552282 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562283
2284 // Rendezvous should have succeeded now, so the promised stream
2285 // should point at our push stream, and we should be able read
2286 // headers and data from it.
robpercival214763f2016-07-01 23:27:012287 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562288
2289 EXPECT_EQ(
2290 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2291 ->id(),
2292 promise_id_);
2293
robpercival214763f2016-07-01 23:27:012294 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2295 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562296
2297 EXPECT_EQ(
2298 static_cast<int>(strlen(kResponseBody)),
2299 promised_stream_->ReadResponseBody(
2300 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2301
2302 // Callback should return
2303 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2304 EXPECT_TRUE(AtEof());
2305
ckrasic3865ee0f2016-02-29 22:04:562306 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2307 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412308 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562309 promised_stream_->GetTotalReceivedBytes());
2310}
2311
ckrasic2c63f9b2016-08-16 23:54:072312// Verify fix for crbug.com/637349
2313TEST_P(QuicHttpStreamTest, ServerPushCancelHttpStreamBeforeResponse) {
2314 SetRequest("GET", "/", DEFAULT_PRIORITY);
2315 Initialize();
2316
Bin Wue8408792021-08-24 23:25:162317 // Server push is not supported in HTTP/3.
2318 if (version_.UsesHttp3())
2319 return;
2320
ckrasic2c63f9b2016-08-16 23:54:072321 // Initialize the first stream, for receiving the promise on.
2322 request_.method = "GET";
rchcd379012017-04-12 21:53:322323 request_.url = GURL("https://www.example.org/");
ckrasic2c63f9b2016-08-16 23:54:072324
Matt Reichhoff0049a0b72021-10-20 20:44:262325 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
2326 net_log_with_source_,
2327 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232328 ASSERT_EQ(OK,
2329 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic2c63f9b2016-08-16 23:54:072330
2331 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2332 // packet, but does it matter?
2333 ReceivePromise(promise_id_);
2334 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2335
2336 request_.url = GURL(promise_url_);
2337
2338 // Make the second stream that will exercise the first step of the
2339 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272340 EXPECT_EQ(OK, promised_stream_->InitializeStream(
Matt Reichhoff0049a0b72021-10-20 20:44:262341 &request_, true, DEFAULT_PRIORITY, net_log_with_source_,
Steven Valdezb4ff0412018-01-18 22:39:272342 callback_.callback()));
ckrasic2c63f9b2016-08-16 23:54:072343
2344 // Now sending a matching request will rendezvous with the promised
2345 // stream, but pending secondary validation.
2346 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2347 headers_, &response_, callback_.callback()));
2348
2349 base::RunLoop().RunUntilIdle();
2350
2351 // Cause of FinalValidation() crash as per bug.
2352 promised_stream_.reset();
2353
2354 // Receive the promised response headers.
2355 response_headers_ = promised_response_.Clone();
2356 size_t spdy_response_headers_frame_length;
2357 ProcessPacket(InnerConstructResponseHeadersPacket(
2358 1, promise_id_, false, &spdy_response_headers_frame_length));
2359}
2360
ckrasic3865ee0f2016-02-29 22:04:562361TEST_P(QuicHttpStreamTest, ServerPushCrossOriginOK) {
2362 SetRequest("GET", "/", DEFAULT_PRIORITY);
2363 Initialize();
2364
Bin Wue8408792021-08-24 23:25:162365 // Server push is not supported in HTTP/3.
2366 if (version_.UsesHttp3())
2367 return;
2368
ckrasic3865ee0f2016-02-29 22:04:562369 // Initialize the first stream, for receiving the promise on.
2370 request_.method = "GET";
rchcd379012017-04-12 21:53:322371 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562372
Matt Reichhoff0049a0b72021-10-20 20:44:262373 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
2374 net_log_with_source_,
2375 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232376 ASSERT_EQ(OK,
2377 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562378
2379 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2380 // packet, but does it matter?
2381
2382 push_promise_[":authority"] = "mail.example.org";
David Schinazi3f7465c2019-07-12 01:57:052383 promise_url_ =
2384 quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
ckrasic3865ee0f2016-02-29 22:04:562385
2386 ReceivePromise(promise_id_);
2387 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2388
2389 request_.url = GURL(promise_url_);
2390
2391 // Make the second stream that will exercise the first step of the
2392 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272393 EXPECT_EQ(OK, promised_stream_->InitializeStream(
Matt Reichhoff0049a0b72021-10-20 20:44:262394 &request_, true, DEFAULT_PRIORITY, net_log_with_source_,
Steven Valdezb4ff0412018-01-18 22:39:272395 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562396
2397 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252398 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562399 size_t spdy_response_headers_frame_length;
2400 ProcessPacket(InnerConstructResponseHeadersPacket(
2401 1, promise_id_, false, &spdy_response_headers_frame_length));
2402
2403 // Receive the promised response body.
2404 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432405 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172406 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2407 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562408
2409 // Now sending a matching request will have successful rendezvous
2410 // with the promised stream.
2411 EXPECT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
2412 callback_.callback()));
2413
2414 EXPECT_EQ(
2415 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2416 ->id(),
2417 promise_id_);
2418
2419 // The headers will be immediately available.
robpercival214763f2016-07-01 23:27:012420 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2421 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562422
2423 // As will be the body.
2424 EXPECT_EQ(
2425 static_cast<int>(strlen(kResponseBody)),
2426 promised_stream_->ReadResponseBody(
2427 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2428 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2429 EXPECT_TRUE(AtEof());
2430
ckrasic3865ee0f2016-02-29 22:04:562431 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2432 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412433 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562434 promised_stream_->GetTotalReceivedBytes());
2435}
2436
2437TEST_P(QuicHttpStreamTest, ServerPushCrossOriginFail) {
2438 SetRequest("GET", "/", DEFAULT_PRIORITY);
2439 Initialize();
2440
Bin Wue8408792021-08-24 23:25:162441 // Server push is not supported in HTTP/3.
2442 if (version_.UsesHttp3())
2443 return;
2444
ckrasic3865ee0f2016-02-29 22:04:562445 // Initialize the first stream, for receiving the promise on.
2446 request_.method = "GET";
rchcd379012017-04-12 21:53:322447 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562448
Matt Reichhoff0049a0b72021-10-20 20:44:262449 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
2450 net_log_with_source_,
2451 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232452 ASSERT_EQ(OK,
2453 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562454
2455 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2456 // packet, but does it matter?
2457 push_promise_[":authority"] = "www.notexample.org";
David Schinazi3f7465c2019-07-12 01:57:052458 promise_url_ =
2459 quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
ckrasic3865ee0f2016-02-29 22:04:562460
2461 ReceivePromise(promise_id_);
2462 // The promise will have been rejected because the cert doesn't
2463 // match.
2464 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
2465}
2466
2467TEST_P(QuicHttpStreamTest, ServerPushVaryCheckOK) {
2468 SetRequest("GET", "/", DEFAULT_PRIORITY);
2469 Initialize();
2470
Bin Wue8408792021-08-24 23:25:162471 // Server push is not supported in HTTP/3.
2472 if (version_.UsesHttp3())
2473 return;
2474
ckrasic3865ee0f2016-02-29 22:04:562475 // Initialize the first stream, for receiving the promise on.
2476 request_.method = "GET";
rchcd379012017-04-12 21:53:322477 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562478
Matt Reichhoff0049a0b72021-10-20 20:44:262479 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
2480 net_log_with_source_,
2481 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232482 ASSERT_EQ(OK,
2483 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562484
2485 push_promise_["accept-encoding"] = "gzip";
ckrasic3865ee0f2016-02-29 22:04:562486
2487 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2488 // packet, but does it matter?
2489 ReceivePromise(promise_id_);
2490 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2491
2492 request_.url = GURL(promise_url_);
2493
2494 // Make the second stream that will exercise the first step of the
2495 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272496 EXPECT_EQ(OK, promised_stream_->InitializeStream(
Matt Reichhoff0049a0b72021-10-20 20:44:262497 &request_, true, DEFAULT_PRIORITY, net_log_with_source_,
Steven Valdezb4ff0412018-01-18 22:39:272498 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562499
2500 headers_.SetHeader("accept-encoding", "gzip");
2501
2502 // Now sending a matching request will rendezvous with the promised
2503 // stream, but pending secondary validation.
2504 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2505 headers_, &response_, callback_.callback()));
2506
2507 // Receive the promised response headers.
2508 promised_response_["vary"] = "accept-encoding";
bnc94893a72016-06-30 13:45:252509 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562510 size_t spdy_response_headers_frame_length;
2511 ProcessPacket(InnerConstructResponseHeadersPacket(
2512 1, promise_id_, false, &spdy_response_headers_frame_length));
2513
2514 // Receive the promised response body.
2515 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432516 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172517 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2518 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562519
fdoray92e35a72016-06-10 15:54:552520 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562521
2522 // Rendezvous should have succeeded now, so the promised stream
2523 // should point at our push stream, and we should be able read
2524 // headers and data from it.
robpercival214763f2016-07-01 23:27:012525 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562526
2527 EXPECT_EQ(
2528 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2529 ->id(),
2530 promise_id_);
2531
robpercival214763f2016-07-01 23:27:012532 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2533 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562534
2535 EXPECT_EQ(
2536 static_cast<int>(strlen(kResponseBody)),
2537 promised_stream_->ReadResponseBody(
2538 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2539
2540 // Callback should return
2541 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2542 EXPECT_TRUE(AtEof());
2543
ckrasic3865ee0f2016-02-29 22:04:562544 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2545 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412546 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562547 promised_stream_->GetTotalReceivedBytes());
2548}
2549
2550TEST_P(QuicHttpStreamTest, ServerPushVaryCheckFail) {
2551 SetRequest("GET", "/", DEFAULT_PRIORITY);
2552 request_headers_[":scheme"] = "https";
2553 request_headers_[":path"] = "/bar";
2554 request_headers_["accept-encoding"] = "sdch";
2555
ckrasic3865ee0f2016-02-29 22:04:562556 Initialize();
2557
Bin Wue8408792021-08-24 23:25:162558 // Server push is not supported in HTTP/3.
2559 if (version_.UsesHttp3())
2560 return;
2561
ckrasic3865ee0f2016-02-29 22:04:562562 // Initialize the first stream, for receiving the promise on.
2563 request_.method = "GET";
rchcd379012017-04-12 21:53:322564 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562565
Matt Reichhoff0049a0b72021-10-20 20:44:262566 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
2567 net_log_with_source_,
2568 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232569 ASSERT_EQ(OK,
2570 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562571
2572 push_promise_["accept-encoding"] = "gzip";
ckrasic3865ee0f2016-02-29 22:04:562573
2574 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2575 // packet, but does it matter?
2576 ReceivePromise(promise_id_);
2577 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2578
2579 request_.url = GURL(promise_url_);
2580
2581 // Make the second stream that will exercise the first step of the
2582 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272583 EXPECT_EQ(OK, promised_stream_->InitializeStream(
Matt Reichhoff0049a0b72021-10-20 20:44:262584 &request_, true, DEFAULT_PRIORITY, net_log_with_source_,
Steven Valdezb4ff0412018-01-18 22:39:272585 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562586
2587 headers_.SetHeader("accept-encoding", "sdch");
2588
2589 // Now sending a matching request will rendezvous with the promised
2590 // stream, but pending secondary validation.
2591 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2592 headers_, &response_, callback_.callback()));
2593
2594 // Receive the promised response headers.
2595 promised_response_["vary"] = "accept-encoding";
bnc94893a72016-06-30 13:45:252596 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562597 size_t spdy_response_headers_frame_length;
2598 ProcessPacket(InnerConstructResponseHeadersPacket(
2599 1, promise_id_, false, &spdy_response_headers_frame_length));
2600
fdoray92e35a72016-06-10 15:54:552601 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562602
2603 // Rendezvous should have failed due to vary mismatch, so the
2604 // promised stream should have been aborted, and instead we have a
2605 // new, regular client initiated stream.
robpercival214763f2016-07-01 23:27:012606 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562607
2608 // Not a server-initiated stream.
2609 EXPECT_NE(
2610 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2611 ->id(),
2612 promise_id_);
2613
2614 // Instead, a new client-initiated stream.
2615 EXPECT_EQ(
2616 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2617 ->id(),
Nick Harper23290b82019-05-02 00:02:562618 stream_id_ + quic::QuicUtils::StreamIdDelta(version_.transport_version));
ckrasic3865ee0f2016-02-29 22:04:562619
2620 // After rendezvous failure, the push stream has been cancelled.
2621 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
2622
2623 // The rest of the test verifies that the retried as
2624 // client-initiated version of |promised_stream_| works as intended.
2625
2626 // Ack the request.
Renjie90e808e2019-01-24 07:24:042627 ProcessPacket(ConstructServerAckPacket(2, 1, 1, 1));
ckrasic3865ee0f2016-02-29 22:04:562628
Kenichi Ishibashif8634ab2021-03-16 23:41:282629 SetResponse("404", string());
ckrasic3865ee0f2016-02-29 22:04:562630 size_t spdy_response_header_frame_length;
2631 ProcessPacket(InnerConstructResponseHeadersPacket(
Nick Harper23290b82019-05-02 00:02:562632 3,
2633 stream_id_ + quic::QuicUtils::StreamIdDelta(version_.transport_version),
2634 kFin, &spdy_response_header_frame_length));
ckrasic3865ee0f2016-02-29 22:04:562635
fdoray92e35a72016-06-10 15:54:552636 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562637
robpercival214763f2016-07-01 23:27:012638 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2639 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562640 ASSERT_TRUE(response_.headers.get());
2641 EXPECT_EQ(404, response_.headers->response_code());
2642 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
2643 EXPECT_FALSE(response_.response_time.is_null());
2644 EXPECT_FALSE(response_.request_time.is_null());
2645
2646 // There is no body, so this should return immediately.
2647 EXPECT_EQ(
2648 0, promised_stream_->ReadResponseBody(
2649 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2650 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2651
2652 stream_->Close(true);
2653
2654 EXPECT_TRUE(AtEof());
ckrasic3865ee0f2016-02-29 22:04:562655}
2656
maksim.sisov84e20c92016-06-23 08:49:342657TEST_P(QuicHttpStreamTest, DataReadErrorSynchronous) {
2658 SetRequest("POST", "/", DEFAULT_PRIORITY);
2659 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232660 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252661 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232662 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Yixin Wange7ecc472018-03-06 19:00:252663 AddWrite(ConstructRequestAndRstPacket(
Renjie Tangaadb84b2019-08-31 01:00:232664 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2665 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
2666 &spdy_request_headers_frame_length, quic::QUIC_ERROR_PROCESSING_STREAM));
maksim.sisov84e20c92016-06-23 08:49:342667
2668 Initialize();
2669
Jeremy Roman0579ed62017-08-29 15:56:192670 upload_data_stream_ = std::make_unique<ReadErrorUploadDataStream>(
maksim.sisov84e20c92016-06-23 08:49:342671 ReadErrorUploadDataStream::FailureMode::SYNC);
2672 request_.method = "POST";
rchcd379012017-04-12 21:53:322673 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122674 request_.upload_data_stream = upload_data_stream_.get();
maksim.sisov84e20c92016-06-23 08:49:342675 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202676 TestCompletionCallback().callback(), NetLogWithSource()));
maksim.sisov84e20c92016-06-23 08:49:342677
Matt Reichhoff0049a0b72021-10-20 20:44:262678 EXPECT_EQ(OK, stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
2679 net_log_with_source_,
2680 callback_.callback()));
maksim.sisov84e20c92016-06-23 08:49:342681
2682 int result = stream_->SendRequest(headers_, &response_, callback_.callback());
robpercival214763f2016-07-01 23:27:012683 EXPECT_THAT(result, IsError(ERR_FAILED));
maksim.sisov84e20c92016-06-23 08:49:342684
2685 EXPECT_TRUE(AtEof());
2686
2687 // QuicHttpStream::GetTotalSent/ReceivedBytes includes only headers.
2688 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
2689 stream_->GetTotalSentBytes());
2690 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2691}
2692
2693TEST_P(QuicHttpStreamTest, DataReadErrorAsynchronous) {
2694 SetRequest("POST", "/", DEFAULT_PRIORITY);
2695 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232696 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252697 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232698 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:372699 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:232700 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2701 kIncludeVersion, !kFin, DEFAULT_PRIORITY,
2702 &spdy_request_headers_frame_length));
2703 AddWrite(
2704 ConstructClientRstStreamErrorPacket(packet_number++, !kIncludeVersion));
maksim.sisov84e20c92016-06-23 08:49:342705
2706 Initialize();
2707
Jeremy Roman0579ed62017-08-29 15:56:192708 upload_data_stream_ = std::make_unique<ReadErrorUploadDataStream>(
maksim.sisov84e20c92016-06-23 08:49:342709 ReadErrorUploadDataStream::FailureMode::ASYNC);
2710 request_.method = "POST";
rchcd379012017-04-12 21:53:322711 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122712 request_.upload_data_stream = upload_data_stream_.get();
maksim.sisov84e20c92016-06-23 08:49:342713 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202714 TestCompletionCallback().callback(), NetLogWithSource()));
maksim.sisov84e20c92016-06-23 08:49:342715
Matt Reichhoff0049a0b72021-10-20 20:44:262716 EXPECT_EQ(OK, stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
2717 net_log_with_source_,
2718 callback_.callback()));
maksim.sisov84e20c92016-06-23 08:49:342719
2720 int result = stream_->SendRequest(headers_, &response_, callback_.callback());
2721
Renjie90e808e2019-01-24 07:24:042722 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
Kenichi Ishibashif8634ab2021-03-16 23:41:282723 SetResponse("200", string());
maksim.sisov84e20c92016-06-23 08:49:342724
robpercival214763f2016-07-01 23:27:012725 EXPECT_THAT(result, IsError(ERR_IO_PENDING));
2726 EXPECT_THAT(callback_.GetResult(result), IsError(ERR_FAILED));
maksim.sisov84e20c92016-06-23 08:49:342727
2728 EXPECT_TRUE(AtEof());
2729
2730 // QuicHttpStream::GetTotalSent/ReceivedBytes includes only headers.
2731 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
2732 stream_->GetTotalSentBytes());
2733 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2734}
2735
Bence Béky97ec688c2021-03-16 13:48:502736TEST_P(QuicHttpStreamTest, GetAcceptChViaAlps) {
2737 AddWrite(ConstructInitialSettingsPacket());
2738 Initialize();
2739
2740 if (!VersionUsesHttp3(version_.transport_version)) {
2741 // ALPS is only implemented for HTTP/3.
2742 return;
2743 }
2744
2745 base::HistogramTester histogram_tester;
2746
2747 session_->OnAcceptChFrameReceivedViaAlps(
Bence Béky41a34f02021-05-07 00:27:482748 {{{"https://www.example.org", "Sec-CH-UA-Platform"}}});
Bence Béky97ec688c2021-03-16 13:48:502749
2750 request_.method = "GET";
2751 request_.url = GURL("https://www.example.org/foo");
2752
Matt Reichhoff0049a0b72021-10-20 20:44:262753 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
2754 net_log_with_source_,
2755 callback_.callback()));
Bence Béky41a34f02021-05-07 00:27:482756 EXPECT_EQ("Sec-CH-UA-Platform", stream_->GetAcceptChViaAlps());
Bence Béky97ec688c2021-03-16 13:48:502757 EXPECT_TRUE(AtEof());
2758
2759 histogram_tester.ExpectBucketCount(
2760 "Net.QuicSession.AcceptChFrameReceivedViaAlps", 1, 1);
2761 histogram_tester.ExpectTotalCount(
2762 "Net.QuicSession.AcceptChFrameReceivedViaAlps", 1);
2763 histogram_tester.ExpectBucketCount("Net.QuicSession.AcceptChForOrigin", 1, 1);
2764 histogram_tester.ExpectTotalCount("Net.QuicSession.AcceptChForOrigin", 1);
2765}
2766
[email protected]f702d572012-12-04 15:56:202767} // namespace test
[email protected]f702d572012-12-04 15:56:202768} // namespace net