blob: d984117b49da1149cc5ad8c9512828aed5402109 [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 Hamiltona1d1f4a2019-06-26 14:43:0440#include "net/quic/platform/impl/quic_test_impl.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0841#include "net/quic/quic_chromium_alarm_factory.h"
42#include "net/quic/quic_chromium_connection_helper.h"
43#include "net/quic/quic_chromium_packet_reader.h"
44#include "net/quic/quic_chromium_packet_writer.h"
Matt Menkefca05b62019-09-20 23:15:5645#include "net/quic/quic_crypto_client_config_handle.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0846#include "net/quic/quic_http_utils.h"
47#include "net/quic/quic_server_info.h"
48#include "net/quic/quic_stream_factory.h"
49#include "net/quic/quic_test_packet_maker.h"
Ryan Hamilton0d65a8c2019-06-07 00:46:0250#include "net/quic/quic_test_packet_printer.h"
Matt Menkefca05b62019-09-20 23:15:5651#include "net/quic/test_quic_crypto_client_config_handle.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0852#include "net/quic/test_task_runner.h"
tbansalca83c002016-04-28 20:56:2853#include "net/socket/socket_performance_watcher.h"
[email protected]f702d572012-12-04 15:56:2054#include "net/socket/socket_test_util.h"
Bence Béky94658bf2018-05-11 19:22:5855#include "net/spdy/spdy_http_utils.h"
rch03b7a202016-02-05 00:54:2056#include "net/test/cert_test_util.h"
robpercival214763f2016-07-01 23:27:0157#include "net/test/gtest_util.h"
rsleevia69c79a2016-06-22 03:28:4358#include "net/test/test_data_directory.h"
Gabriel Charettec7108742019-08-23 03:31:4059#include "net/test/test_with_task_environment.h"
Victor Vasiliev6bb59d22019-03-08 21:34:5160#include "net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.h"
61#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
62#include "net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h"
63#include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
David Schinazi3f7465c2019-07-12 01:57:0564#include "net/third_party/quiche/src/quic/core/http/spdy_server_push_utils.h"
Victor Vasiliev6bb59d22019-03-08 21:34:5165#include "net/third_party/quiche/src/quic/core/quic_connection.h"
66#include "net/third_party/quiche/src/quic/core/quic_utils.h"
67#include "net/third_party/quiche/src/quic/core/quic_write_blocked_list.h"
Ryan Hamiltona1d1f4a2019-06-26 14:43:0468#include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h"
69#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
Victor Vasiliev6bb59d22019-03-08 21:34:5170#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
71#include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
72#include "net/third_party/quiche/src/quic/test_tools/mock_random.h"
Bence Béky6e243aa2019-12-13 19:01:0773#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h"
Victor Vasiliev6bb59d22019-03-08 21:34:5174#include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
75#include "net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h"
76#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
Victor Vasiliev27cc7712019-01-24 11:50:1477#include "net/third_party/quiche/src/spdy/core/spdy_frame_builder.h"
78#include "net/third_party/quiche/src/spdy/core/spdy_framer.h"
79#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
Ramin Halavati683bcaa92018-02-14 08:42:3980#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
[email protected]f702d572012-12-04 15:56:2081#include "testing/gmock/include/gmock/gmock.h"
82#include "testing/gtest/include/gtest/gtest.h"
Dan McArdle68a5f622021-07-09 20:56:5383#include "url/scheme_host_port.h"
84#include "url/url_constants.h"
[email protected]f702d572012-12-04 15:56:2085
bnc614a92d32016-04-04 13:56:0786using std::string;
[email protected]f702d572012-12-04 15:56:2087using testing::_;
[email protected]06ff5152013-08-29 01:03:0588using testing::AnyNumber;
89using testing::Return;
[email protected]f702d572012-12-04 15:56:2090
91namespace net {
[email protected]f702d572012-12-04 15:56:2092namespace test {
[email protected]f702d572012-12-04 15:56:2093namespace {
94
[email protected]16ba7742014-08-22 00:57:2595const char kUploadData[] = "Really nifty data!";
rch9ae5b3b2016-02-11 00:36:2996const char kDefaultServerHostName[] = "www.example.org";
rchcd379012017-04-12 21:53:3297const uint16_t kDefaultServerPort = 443;
[email protected]f702d572012-12-04 15:56:2098
David Schinazi09e9a6012019-10-03 17:37:5799struct TestParams {
100 quic::ParsedQuicVersion version;
101 bool client_headers_include_h2_stream_dependency;
102};
103
104// Used by ::testing::PrintToStringParamName().
105std::string PrintToString(const TestParams& p) {
Victor Vasiliev62c09dc2020-11-06 18:18:29106 return base::StrCat(
107 {ParsedQuicVersionToString(p.version), "_",
108 (p.client_headers_include_h2_stream_dependency ? "" : "No"),
109 "Dependency"});
David Schinazi09e9a6012019-10-03 17:37:57110}
111
112std::vector<TestParams> GetTestParams() {
113 std::vector<TestParams> params;
114 quic::ParsedQuicVersionVector all_supported_versions =
115 quic::AllSupportedVersions();
116 for (const auto& version : all_supported_versions) {
117 params.push_back(TestParams{version, false});
118 params.push_back(TestParams{version, true});
119 }
120 return params;
121}
122
Bence Békye0d3747d2020-08-28 23:16:40123// Returns true if |params| is a dict, has an entry with key "headers", that
124// entry is a list of strings, which when interpreted as colon-separated
125// key-value pairs has exactly one entry with |key| and that entry has value
126// |expected_value|.
127bool CheckHeader(const base::Value& params,
128 base::StringPiece key,
129 base::StringPiece expected_value) {
130 if (!params.is_dict()) {
131 return false;
132 }
133 const base::Value* headers = params.FindListKey("headers");
134 if (!headers) {
135 return false;
136 }
137
138 std::string header_prefix = base::StrCat({key, ": "});
139 std::string expected_header = base::StrCat({header_prefix, expected_value});
140
141 auto header_list = headers->GetList();
142 auto header_it = header_list.begin();
143 bool header_found = false;
144 while (header_it != header_list.end()) {
145 if (!header_it->is_string()) {
146 return false;
147 }
148 const std::string& header = header_it->GetString();
149 if (base::StartsWith(header, header_prefix)) {
150 if (header_found) {
151 return false;
152 }
153 if (header != expected_header) {
154 return false;
155 }
156 header_found = true;
157 }
158 ++header_it;
159 }
160 return header_found;
161}
162
Ryan Hamilton8d9ee76e2018-05-29 23:52:52163class TestQuicConnection : public quic::QuicConnection {
[email protected]f702d572012-12-04 15:56:20164 public:
Ryan Hamilton8d9ee76e2018-05-29 23:52:52165 TestQuicConnection(const quic::ParsedQuicVersionVector& versions,
166 quic::QuicConnectionId connection_id,
[email protected]f702d572012-12-04 15:56:20167 IPEndPoint address,
rch12fef552016-01-15 16:26:31168 QuicChromiumConnectionHelper* helper,
rch16c74d1d2016-04-22 06:14:07169 QuicChromiumAlarmFactory* alarm_factory,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52170 quic::QuicPacketWriter* writer)
Victor Vasiliev4f6fb892019-05-31 16:58:31171 : quic::QuicConnection(connection_id,
Nick Harperd049f192020-10-02 02:56:10172 quic::QuicSocketAddress(),
Victor Vasiliev4f6fb892019-05-31 16:58:31173 ToQuicSocketAddress(address),
174 helper,
175 alarm_factory,
176 writer,
177 true /* owns_writer */,
178 quic::Perspective::IS_CLIENT,
179 versions) {}
[email protected]f702d572012-12-04 15:56:20180
Ryan Hamilton8d9ee76e2018-05-29 23:52:52181 void SetSendAlgorithm(quic::SendAlgorithmInterface* send_algorithm) {
182 quic::test::QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
[email protected]f702d572012-12-04 15:56:20183 }
184};
185
maksim.sisov84e20c92016-06-23 08:49:34186// UploadDataStream that always returns errors on data read.
187class ReadErrorUploadDataStream : public UploadDataStream {
188 public:
189 enum class FailureMode { SYNC, ASYNC };
190
191 explicit ReadErrorUploadDataStream(FailureMode mode)
Jeremy Romand54000b22019-07-08 18:40:16192 : UploadDataStream(true, 0), async_(mode) {}
Peter Boström293b1342021-09-22 17:31:43193
194 ReadErrorUploadDataStream(const ReadErrorUploadDataStream&) = delete;
195 ReadErrorUploadDataStream& operator=(const ReadErrorUploadDataStream&) =
196 delete;
197
maksim.sisov84e20c92016-06-23 08:49:34198 ~ReadErrorUploadDataStream() override {}
199
200 private:
201 void CompleteRead() { UploadDataStream::OnReadCompleted(ERR_FAILED); }
202
203 // UploadDataStream implementation:
tfarina42834112016-09-22 13:38:20204 int InitInternal(const NetLogWithSource& net_log) override { return OK; }
maksim.sisov84e20c92016-06-23 08:49:34205
206 int ReadInternal(IOBuffer* buf, int buf_len) override {
207 if (async_ == FailureMode::ASYNC) {
208 base::ThreadTaskRunnerHandle::Get()->PostTask(
kylecharf4fe5172019-02-15 18:53:49209 FROM_HERE, base::BindOnce(&ReadErrorUploadDataStream::CompleteRead,
210 weak_factory_.GetWeakPtr()));
maksim.sisov84e20c92016-06-23 08:49:34211 return ERR_IO_PENDING;
212 }
213 return ERR_FAILED;
214 }
215
216 void ResetInternal() override {}
217
218 const FailureMode async_;
219
Jeremy Romand54000b22019-07-08 18:40:16220 base::WeakPtrFactory<ReadErrorUploadDataStream> weak_factory_{this};
maksim.sisov84e20c92016-06-23 08:49:34221};
222
Bence Béky8ddc2492018-06-13 01:02:04223// A helper class that will delete |stream| when the callback is invoked.
xunjieli8dff50b2016-07-22 14:19:06224class DeleteStreamCallback : public TestCompletionCallbackBase {
225 public:
Bence Béky8ddc2492018-06-13 01:02:04226 explicit DeleteStreamCallback(std::unique_ptr<QuicHttpStream> stream)
227 : stream_(std::move(stream)) {}
xunjieli8dff50b2016-07-22 14:19:06228
Bence Béky8ddc2492018-06-13 01:02:04229 CompletionOnceCallback callback() {
230 return base::BindOnce(&DeleteStreamCallback::DeleteStream,
231 base::Unretained(this));
232 }
xunjieli8dff50b2016-07-22 14:19:06233
234 private:
235 void DeleteStream(int result) {
236 stream_.reset();
237 SetResult(result);
238 }
239
240 std::unique_ptr<QuicHttpStream> stream_;
xunjieli8dff50b2016-07-22 14:19:06241};
242
[email protected]f702d572012-12-04 15:56:20243} // namespace
244
[email protected]24e5bc52013-09-18 15:36:58245class QuicHttpStreamPeer {
246 public:
rch08e198572017-05-09 16:56:55247 static QuicChromiumClientStream::Handle* GetQuicChromiumClientStream(
[email protected]24e5bc52013-09-18 15:36:58248 QuicHttpStream* stream) {
rch08e198572017-05-09 16:56:55249 return stream->stream_.get();
[email protected]24e5bc52013-09-18 15:36:58250 }
251};
252
David Schinazi09e9a6012019-10-03 17:37:57253class QuicHttpStreamTest : public ::testing::TestWithParam<TestParams>,
Gabriel Charette694c3c332019-08-19 14:53:05254 public WithTaskEnvironment {
rchfb47f712017-05-21 03:24:00255 public:
256 void CloseStream(QuicHttpStream* stream, int /*rv*/) { stream->Close(false); }
257
[email protected]f702d572012-12-04 15:56:20258 protected:
[email protected]1e960032013-12-20 19:00:20259 static const bool kFin = true;
260 static const bool kIncludeVersion = true;
[email protected]1e960032013-12-20 19:00:20261
[email protected]f702d572012-12-04 15:56:20262 // Holds a packet to be written to the wire, and the IO mode that should
263 // be used by the mock socket when performing the write.
264 struct PacketToWrite {
Ryan Hamilton8d9ee76e2018-05-29 23:52:52265 PacketToWrite(IoMode mode, quic::QuicReceivedPacket* packet)
rjshaded5ced072015-12-18 19:26:02266 : mode(mode), packet(packet) {}
rtenneti15656ae2016-01-23 03:05:03267 PacketToWrite(IoMode mode, int rv) : mode(mode), packet(nullptr), rv(rv) {}
[email protected]f702d572012-12-04 15:56:20268 IoMode mode;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52269 quic::QuicReceivedPacket* packet;
rtenneti15656ae2016-01-23 03:05:03270 int rv;
[email protected]f702d572012-12-04 15:56:20271 };
272
273 QuicHttpStreamTest()
David Schinazi09e9a6012019-10-03 17:37:57274 : version_(GetParam().version),
275 client_headers_include_h2_stream_dependency_(
276 GetParam().client_headers_include_h2_stream_dependency),
Nick Harpera598fc5f2019-06-21 08:46:50277 crypto_config_(
278 quic::test::crypto_test_utils::ProofVerifierForTesting()),
Victor Costan9c7302b2018-08-27 16:39:44279 read_buffer_(base::MakeRefCounted<IOBufferWithSize>(4096)),
Fan Yang32c5a112018-12-10 20:06:33280 promise_id_(GetNthServerInitiatedUnidirectionalStreamId(0)),
281 stream_id_(GetNthClientInitiatedBidirectionalStreamId(0)),
David Schinazic8281052019-01-24 06:14:17282 connection_id_(quic::test::TestConnectionId(2)),
Yixin Wang079ad542018-01-11 04:06:05283 client_maker_(version_,
alyssar2adf3ac2016-05-03 17:12:58284 connection_id_,
285 &clock_,
286 kDefaultServerHostName,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52287 quic::Perspective::IS_CLIENT,
Yixin Wang079ad542018-01-11 04:06:05288 client_headers_include_h2_stream_dependency_),
289 server_maker_(version_,
zhongyi5dbfdd42017-06-20 05:22:15290 connection_id_,
alyssar2adf3ac2016-05-03 17:12:58291 &clock_,
292 kDefaultServerHostName,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52293 quic::Perspective::IS_SERVER,
Yixin Wang079ad542018-01-11 04:06:05294 false),
ckrasic3865ee0f2016-02-29 22:04:56295 random_generator_(0),
Ryan Hamilton0d65a8c2019-06-07 00:46:02296 printer_(version_) {
Renjie Tang98b4d512020-02-08 01:24:19297 FLAGS_quic_enable_http3_grease_randomness = false;
Zhongyi Shi49f8ad2fd2019-12-13 01:20:31298 quic::QuicEnableVersion(version_);
martijn21968ea2016-02-24 18:46:20299 IPAddress ip(192, 0, 2, 33);
[email protected]f702d572012-12-04 15:56:20300 peer_addr_ = IPEndPoint(ip, 443);
301 self_addr_ = IPEndPoint(ip, 8435);
Ryan Hamilton8d9ee76e2018-05-29 23:52:52302 clock_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(20));
Ramin Halavati683bcaa92018-02-14 08:42:39303 request_.traffic_annotation =
304 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f702d572012-12-04 15:56:20305 }
306
307 ~QuicHttpStreamTest() {
Renjieba55fae2018-09-20 03:05:16308 session_->CloseSessionOnError(ERR_ABORTED, quic::QUIC_INTERNAL_ERROR,
309 quic::ConnectionCloseBehavior::SILENT_CLOSE);
[email protected]f702d572012-12-04 15:56:20310 for (size_t i = 0; i < writes_.size(); i++) {
311 delete writes_[i].packet;
312 }
313 }
314
315 // Adds a packet to the list of expected writes.
Ryan Hamilton8d9ee76e2018-05-29 23:52:52316 void AddWrite(std::unique_ptr<quic::QuicReceivedPacket> packet) {
[email protected]1e960032013-12-20 19:00:20317 writes_.push_back(PacketToWrite(SYNCHRONOUS, packet.release()));
[email protected]f702d572012-12-04 15:56:20318 }
319
rtenneti15656ae2016-01-23 03:05:03320 void AddWrite(IoMode mode, int rv) {
321 writes_.push_back(PacketToWrite(mode, rv));
322 }
323
[email protected]f702d572012-12-04 15:56:20324 // Returns the packet to be written at position |pos|.
Ryan Hamilton8d9ee76e2018-05-29 23:52:52325 quic::QuicReceivedPacket* GetWrite(size_t pos) { return writes_[pos].packet; }
[email protected]f702d572012-12-04 15:56:20326
327 bool AtEof() {
rch37de576c2015-05-17 20:28:17328 return socket_data_->AllReadDataConsumed() &&
329 socket_data_->AllWriteDataConsumed();
[email protected]f702d572012-12-04 15:56:20330 }
331
Ryan Hamilton8d9ee76e2018-05-29 23:52:52332 void ProcessPacket(std::unique_ptr<quic::QuicReceivedPacket> packet) {
Victor Vasiliev4f6fb892019-05-31 16:58:31333 connection_->ProcessUdpPacket(ToQuicSocketAddress(self_addr_),
334 ToQuicSocketAddress(peer_addr_), *packet);
[email protected]f702d572012-12-04 15:56:20335 }
336
337 // Configures the test fixture to use the list of expected writes.
338 void Initialize() {
Renjie Tang6ff9a9b2021-02-03 22:11:09339 mock_writes_ = std::make_unique<MockWrite[]>(writes_.size());
[email protected]f702d572012-12-04 15:56:20340 for (size_t i = 0; i < writes_.size(); i++) {
rtenneti15656ae2016-01-23 03:05:03341 if (writes_[i].packet == nullptr) {
342 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].rv, i);
343 } else {
344 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].packet->data(),
345 writes_[i].packet->length());
346 }
bnc614a92d32016-04-04 13:56:07347 }
[email protected]f702d572012-12-04 15:56:20348
Renjie Tang6ff9a9b2021-02-03 22:11:09349 socket_data_ = std::make_unique<StaticSocketDataProvider>(
Ryan Sleevib8d7ea02018-05-07 20:01:01350 base::span<MockRead>(),
Renjie Tang6ff9a9b2021-02-03 22:11:09351 base::make_span(mock_writes_.get(), writes_.size()));
Ryan Hamilton0d65a8c2019-06-07 00:46:02352 socket_data_->set_printer(&printer_);
[email protected]f702d572012-12-04 15:56:20353
Matt Reichhoff0049a0b72021-10-20 20:44:26354 std::unique_ptr<MockUDPClientSocket> socket(
355 new MockUDPClientSocket(socket_data_.get(), NetLog::Get()));
[email protected]e13201d82012-12-12 05:00:32356 socket->Connect(peer_addr_);
[email protected]f702d572012-12-04 15:56:20357 runner_ = new TestTaskRunner(&clock_);
Ryan Hamilton8d9ee76e2018-05-29 23:52:52358 send_algorithm_ = new quic::test::MockSendAlgorithm();
rch7dd15702015-07-01 18:57:57359 EXPECT_CALL(*send_algorithm_, InRecovery()).WillRepeatedly(Return(false));
360 EXPECT_CALL(*send_algorithm_, InSlowStart()).WillRepeatedly(Return(false));
Victor Vasiliev7da08172019-10-14 06:04:25361 if (VersionUsesHttp3(version_.transport_version)) {
Renjie Tangaadb84b2019-08-31 01:00:23362 EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
363 .Times(testing::AtLeast(1));
364 }
Ryan Hamiltona1d1f4a2019-06-26 14:43:04365 EXPECT_CALL(*send_algorithm_, OnCongestionEvent(_, _, _, _, _))
366 .Times(AnyNumber());
rtenneti44f4a2e2015-08-07 14:00:07367 EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
Zhongyi Shica576df2019-04-12 17:43:40368 .WillRepeatedly(Return(quic::kMaxOutgoingPacketSize));
jokulik0e0a00c32016-06-13 21:51:58369 EXPECT_CALL(*send_algorithm_, PacingRate(_))
Ryan Hamilton8d9ee76e2018-05-29 23:52:52370 .WillRepeatedly(Return(quic::QuicBandwidth::Zero()));
Michael Warres74ee3ce2017-10-09 15:26:37371 EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true));
rtenneti44f4a2e2015-08-07 14:00:07372 EXPECT_CALL(*send_algorithm_, BandwidthEstimate())
Ryan Hamilton8d9ee76e2018-05-29 23:52:52373 .WillRepeatedly(Return(quic::QuicBandwidth::Zero()));
rch1e543ec2015-03-29 07:04:40374 EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(AnyNumber());
rch08cae032017-03-29 00:59:15375 EXPECT_CALL(*send_algorithm_, OnApplicationLimited(_)).Times(AnyNumber());
rch0d5bcf62017-05-24 22:48:45376 EXPECT_CALL(*send_algorithm_, GetCongestionControlType())
377 .Times(AnyNumber());
Renjie Tang6ff9a9b2021-02-03 22:11:09378 helper_ = std::make_unique<QuicChromiumConnectionHelper>(
379 &clock_, &random_generator_);
380 alarm_factory_ =
381 std::make_unique<QuicChromiumAlarmFactory>(runner_.get(), &clock_);
rch16c74d1d2016-04-22 06:14:07382
Michael Warres74ee3ce2017-10-09 15:26:37383 connection_ = new TestQuicConnection(
Nick Harper23290b82019-05-02 00:02:56384 quic::test::SupportedVersions(version_), connection_id_, peer_addr_,
385 helper_.get(), alarm_factory_.get(),
Ryan Hamilton9edcf1a2017-11-22 05:55:17386 new QuicChromiumPacketWriter(
387 socket.get(), base::ThreadTaskRunnerHandle::Get().get()));
[email protected]f702d572012-12-04 15:56:20388 connection_->set_visitor(&visitor_);
[email protected]fee17f72013-02-03 07:47:41389 connection_->SetSendAlgorithm(send_algorithm_);
rch03b7a202016-02-05 00:54:20390
391 // Load a certificate that is valid for *.example.org
392 scoped_refptr<X509Certificate> test_cert(
393 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
394 EXPECT_TRUE(test_cert.get());
395
396 verify_details_.cert_verify_result.verified_cert = test_cert;
397 verify_details_.cert_verify_result.is_issued_by_known_root = true;
398 crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details_);
399
xunjieli84adaab2016-09-20 01:12:28400 base::TimeTicks dns_end = base::TimeTicks::Now();
Peter Kastinge5a38ed2021-10-02 03:06:35401 base::TimeTicks dns_start = dns_end - base::Milliseconds(1);
Renjie Tang6ff9a9b2021-02-03 22:11:09402 session_ = std::make_unique<QuicChromiumClientSession>(
xunjielib53b38c2016-03-24 15:54:36403 connection_, std::move(socket),
rtenneti1cd3b162015-09-29 02:58:28404 /*stream_factory=*/nullptr, &crypto_client_stream_factory_, &clock_,
Nick Harper89bc7212018-07-31 19:07:57405 &transport_security_state_, /*ssl_config_service=*/nullptr,
danakjad1777e2016-04-16 00:56:42406 base::WrapUnique(static_cast<QuicServerInfo*>(nullptr)),
Paul Jensen8e3c5d32018-02-19 17:06:33407 QuicSessionKey(kDefaultServerHostName, kDefaultServerPort,
dalyk51ab46b2019-10-15 15:14:34408 PRIVACY_MODE_DISABLED, SocketTag(),
Ben Schwartz3ff4dc1e62021-04-27 21:15:23409 NetworkIsolationKey(), SecureDnsPolicy::kAllow),
Bence Béky1ceba552019-07-19 17:11:05410 /*require_confirmation=*/false,
Bence Béky1ceba552019-07-19 17:11:05411 /*migrate_session_early_v2=*/false,
Zhongyi Shi757fcce2018-06-27 05:41:27412 /*migrate_session_on_network_change_v2=*/false,
413 /*default_network=*/NetworkChangeNotifier::kInvalidNetworkHandle,
Zhongyi Shie01f2db2019-02-22 19:53:23414 quic::QuicTime::Delta::FromMilliseconds(
Ryan Sleevi2e8255b2019-07-17 21:02:21415 kDefaultRetransmittableOnWireTimeout.InMilliseconds()),
Zhongyi Shiaf38c4e42019-08-29 22:49:05416 /*migrate_idle_session=*/false, /*allow_port_migration=*/false,
417 kDefaultIdleSessionMigrationPeriod, kMaxTimeOnNonDefaultNetwork,
Zhongyi Shiee760762018-08-01 00:54:29418 kMaxMigrationsToNonDefaultNetworkOnWriteError,
Zhongyi Shi8b1e43f2017-12-13 20:46:30419 kMaxMigrationsToNonDefaultNetworkOnPathDegrading,
Zhongyi Shi5f587cc2017-11-21 23:24:17420 kQuicYieldAfterPacketsRead,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52421 quic::QuicTime::Delta::FromMilliseconds(
422 kQuicYieldAfterDurationMilliseconds),
Zhongyi Shidbce7f412019-02-01 23:16:29423 /*go_away_on_path_degrading*/ false,
Yixin Wang079ad542018-01-11 04:06:05424 client_headers_include_h2_stream_dependency_, /*cert_verify_flags=*/0,
Matt Menkefca05b62019-09-20 23:15:56425 quic::test::DefaultQuicConfig(),
426 std::make_unique<TestQuicCryptoClientConfigHandle>(&crypto_config_),
Matt Menked804aaf2020-07-21 21:25:48427 "CONNECTION_UNKNOWN", dns_start, dns_end,
428 std::make_unique<quic::QuicClientPushPromiseIndex>(), nullptr,
Zhongyi Shic16b4102019-02-12 00:37:40429 base::DefaultTickClock::GetInstance(),
xunjieli84adaab2016-09-20 01:12:28430 base::ThreadTaskRunnerHandle::Get().get(),
Matt Reichhoff0049a0b72021-10-20 20:44:26431 /*socket_performance_watcher=*/nullptr, NetLog::Get());
rtennetid39bd762015-06-12 01:05:52432 session_->Initialize();
rchf0b18c8a2017-05-05 19:31:57433
Bence Béky6e243aa2019-12-13 19:01:07434 // Blackhole QPACK decoder stream instead of constructing mock writes.
435 if (VersionUsesHttp3(version_.transport_version)) {
436 session_->qpack_decoder()->set_qpack_stream_sender_delegate(
437 &noop_qpack_stream_sender_delegate_);
438 }
439
440 TestCompletionCallback callback;
rch433bf5f2017-02-14 04:10:47441 session_->CryptoConnect(callback.callback());
Ryan Hamilton6c2a2a82017-12-15 02:06:28442 stream_ = std::make_unique<QuicHttpStream>(
Dan McArdle68a5f622021-07-09 20:56:53443 session_->CreateHandle(
444 url::SchemeHostPort(url::kHttpsScheme, "www.example.org", 443)),
Eric Orthac661912022-01-10 21:44:17445 /*dns_aliases=*/std::set<std::string>());
Ryan Hamilton6c2a2a82017-12-15 02:06:28446 promised_stream_ = std::make_unique<QuicHttpStream>(
Dan McArdle68a5f622021-07-09 20:56:53447 session_->CreateHandle(
448 url::SchemeHostPort(url::kHttpsScheme, "www.example.org", 443)),
Eric Orthac661912022-01-10 21:44:17449 /*dns_aliases=*/std::set<std::string>());
ckrasic3865ee0f2016-02-29 22:04:56450 push_promise_[":path"] = "/bar";
451 push_promise_[":authority"] = "www.example.org";
452 push_promise_[":version"] = "HTTP/1.1";
453 push_promise_[":method"] = "GET";
454 push_promise_[":scheme"] = "https";
455
Kenichi Ishibashif8634ab2021-03-16 23:41:28456 promised_response_[":status"] = "200";
ckrasic3865ee0f2016-02-29 22:04:56457 promised_response_[":version"] = "HTTP/1.1";
458 promised_response_["content-type"] = "text/plain";
459
David Schinazi3f7465c2019-07-12 01:57:05460 promise_url_ =
461 quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
[email protected]6cca996b2013-01-25 07:43:36462 }
463
bnc614a92d32016-04-04 13:56:07464 void SetRequest(const string& method,
465 const string& path,
[email protected]1e960032013-12-20 19:00:20466 RequestPriority priority) {
rchcd379012017-04-12 21:53:32467 request_headers_ = client_maker_.GetRequestHeaders(method, "https", path);
[email protected]6cca996b2013-01-25 07:43:36468 }
469
bnc614a92d32016-04-04 13:56:07470 void SetResponse(const string& status, const string& body) {
alyssar2adf3ac2016-05-03 17:12:58471 response_headers_ = server_maker_.GetResponseHeaders(status);
[email protected]92bf17c2014-03-03 21:14:03472 response_data_ = body;
[email protected]6cca996b2013-01-25 07:43:36473 }
[email protected]f702d572012-12-04 15:56:20474
Ryan Hamilton8d9ee76e2018-05-29 23:52:52475 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientDataPacket(
Fan Yangac867502019-01-28 21:10:23476 uint64_t packet_number,
[email protected]e8ff26842013-03-22 21:02:05477 bool should_include_version,
[email protected]f702d572012-12-04 15:56:20478 bool fin,
Victor Vasiliev47ecb6a2020-10-14 17:22:10479 absl::string_view data) {
Ryan Hamilton7505eb92019-06-08 00:22:17480 return client_maker_.MakeDataPacket(packet_number, stream_id_,
481 should_include_version, fin, data);
alyssar2adf3ac2016-05-03 17:12:58482 }
483
Ryan Hamilton8d9ee76e2018-05-29 23:52:52484 std::unique_ptr<quic::QuicReceivedPacket> ConstructServerDataPacket(
Fan Yangac867502019-01-28 21:10:23485 uint64_t packet_number,
alyssar2adf3ac2016-05-03 17:12:58486 bool should_include_version,
487 bool fin,
Victor Vasiliev47ecb6a2020-10-14 17:22:10488 absl::string_view data) {
Ryan Hamilton7505eb92019-06-08 00:22:17489 return server_maker_.MakeDataPacket(packet_number, stream_id_,
490 should_include_version, fin, data);
ckrasic3865ee0f2016-02-29 22:04:56491 }
492
Ryan Hamilton8d9ee76e2018-05-29 23:52:52493 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23494 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52495 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56496 bool should_include_version,
497 bool fin,
498 RequestPriority request_priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02499 size_t* spdy_headers_frame_length) {
Yixin Wang7a3f1b8d2018-01-17 21:40:48500 return InnerConstructRequestHeadersPacket(
501 packet_number, stream_id, should_include_version, fin, request_priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02502 0, spdy_headers_frame_length);
Yixin Wang7a3f1b8d2018-01-17 21:40:48503 }
504
Ryan Hamilton8d9ee76e2018-05-29 23:52:52505 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23506 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52507 quic::QuicStreamId stream_id,
Yixin Wang7a3f1b8d2018-01-17 21:40:48508 bool should_include_version,
509 bool fin,
510 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52511 quic::QuicStreamId parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02512 size_t* spdy_headers_frame_length) {
Ryan Hamilton0239aac2018-05-19 00:03:13513 spdy::SpdyPriority priority =
ckrasic3865ee0f2016-02-29 22:04:56514 ConvertRequestPriorityToQuicPriority(request_priority);
alyssar2adf3ac2016-05-03 17:12:58515 return client_maker_.MakeRequestHeadersPacket(
ckrasic3865ee0f2016-02-29 22:04:56516 packet_number, stream_id, should_include_version, fin, priority,
Yixin Wang7a3f1b8d2018-01-17 21:40:48517 std::move(request_headers_), parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02518 spdy_headers_frame_length);
[email protected]f702d572012-12-04 15:56:20519 }
520
Ryan Hamilton8d9ee76e2018-05-29 23:52:52521 std::unique_ptr<quic::QuicReceivedPacket>
Yixin Wange7ecc472018-03-06 19:00:25522 ConstructRequestHeadersAndDataFramesPacket(
Fan Yangac867502019-01-28 21:10:23523 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52524 quic::QuicStreamId stream_id,
Yixin Wange7ecc472018-03-06 19:00:25525 bool should_include_version,
526 bool fin,
527 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52528 quic::QuicStreamId parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25529 size_t* spdy_headers_frame_length,
530 const std::vector<std::string>& data_writes) {
Ryan Hamilton0239aac2018-05-19 00:03:13531 spdy::SpdyPriority priority =
Yixin Wange7ecc472018-03-06 19:00:25532 ConvertRequestPriorityToQuicPriority(request_priority);
533 return client_maker_.MakeRequestHeadersAndMultipleDataFramesPacket(
534 packet_number, stream_id, should_include_version, fin, priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02535 std::move(request_headers_), parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25536 spdy_headers_frame_length, data_writes);
537 }
538
Ryan Hamilton8d9ee76e2018-05-29 23:52:52539 std::unique_ptr<quic::QuicReceivedPacket> ConstructRequestAndRstPacket(
Fan Yangac867502019-01-28 21:10:23540 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52541 quic::QuicStreamId stream_id,
Yixin Wange7ecc472018-03-06 19:00:25542 bool should_include_version,
543 bool fin,
544 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52545 quic::QuicStreamId parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25546 size_t* spdy_headers_frame_length,
Ryan Hamiltonb5d4c5a2019-06-21 22:08:41547 quic::QuicRstStreamErrorCode error_code) {
Ryan Hamilton0239aac2018-05-19 00:03:13548 spdy::SpdyPriority priority =
Yixin Wange7ecc472018-03-06 19:00:25549 ConvertRequestPriorityToQuicPriority(request_priority);
550 return client_maker_.MakeRequestHeadersAndRstPacket(
551 packet_number, stream_id, should_include_version, fin, priority,
552 std::move(request_headers_), parent_stream_id,
Ryan Hamiltonb5d4c5a2019-06-21 22:08:41553 spdy_headers_frame_length, error_code);
Yixin Wange7ecc472018-03-06 19:00:25554 }
555
Ryan Hamilton8d9ee76e2018-05-29 23:52:52556 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructResponseHeadersPacket(
Fan Yangac867502019-01-28 21:10:23557 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52558 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56559 bool fin,
560 size_t* spdy_headers_frame_length) {
alyssar2adf3ac2016-05-03 17:12:58561 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26562 packet_number, stream_id, !kIncludeVersion, fin,
Ryan Hamilton0d65a8c2019-06-07 00:46:02563 std::move(response_headers_), spdy_headers_frame_length);
[email protected]1e960032013-12-20 19:00:20564 }
565
Ryan Hamilton8d9ee76e2018-05-29 23:52:52566 std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseHeadersPacket(
Fan Yangac867502019-01-28 21:10:23567 uint64_t packet_number,
sclittlec4dc1a32015-09-24 00:15:45568 bool fin,
569 size_t* spdy_headers_frame_length) {
ckrasic3865ee0f2016-02-29 22:04:56570 return InnerConstructResponseHeadersPacket(packet_number, stream_id_, fin,
571 spdy_headers_frame_length);
[email protected]1e960032013-12-20 19:00:20572 }
573
Ryan Hamilton8d9ee76e2018-05-29 23:52:52574 std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseTrailersPacket(
Fan Yangac867502019-01-28 21:10:23575 uint64_t packet_number,
xunjieli34291fe12016-03-02 13:58:38576 bool fin,
Bence Béky4c325e52020-10-22 20:48:01577 spdy::Http2HeaderBlock trailers,
Ryan Hamilton0d65a8c2019-06-07 00:46:02578 size_t* spdy_headers_frame_length) {
alyssar2adf3ac2016-05-03 17:12:58579 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26580 packet_number, stream_id_, !kIncludeVersion, fin, std::move(trailers),
Ryan Hamilton0d65a8c2019-06-07 00:46:02581 spdy_headers_frame_length);
xunjieli34291fe12016-03-02 13:58:38582 }
583
Ryan Hamilton8d9ee76e2018-05-29 23:52:52584 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientRstStreamErrorPacket(
Fan Yangac867502019-01-28 21:10:23585 uint64_t packet_number,
maksim.sisov84e20c92016-06-23 08:49:34586 bool include_version) {
587 return client_maker_.MakeRstPacket(packet_number, include_version,
588 stream_id_,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52589 quic::QUIC_ERROR_PROCESSING_STREAM);
maksim.sisov84e20c92016-06-23 08:49:34590 }
591
Ryan Hamilton8d9ee76e2018-05-29 23:52:52592 std::unique_ptr<quic::QuicReceivedPacket> ConstructAckAndRstStreamPacket(
Fan Yangac867502019-01-28 21:10:23593 uint64_t packet_number) {
Renjie Tangcd594f32020-07-11 20:18:34594 return client_maker_.MakeAckAndRstPacket(packet_number, !kIncludeVersion,
595 stream_id_,
596 quic::QUIC_STREAM_CANCELLED, 2, 1);
[email protected]c5e1aca2014-01-30 04:03:04597 }
598
Ryan Hamilton8d9ee76e2018-05-29 23:52:52599 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientAckPacket(
Fan Yangac867502019-01-28 21:10:23600 uint64_t packet_number,
601 uint64_t largest_received,
Renjie Tangcd594f32020-07-11 20:18:34602 uint64_t smallest_received) {
alyssar2adf3ac2016-05-03 17:12:58603 return client_maker_.MakeAckPacket(packet_number, largest_received,
Renjie Tangcd594f32020-07-11 20:18:34604 smallest_received);
alyssar2adf3ac2016-05-03 17:12:58605 }
606
Ryan Hamilton8d9ee76e2018-05-29 23:52:52607 std::unique_ptr<quic::QuicReceivedPacket> ConstructServerAckPacket(
Fan Yangac867502019-01-28 21:10:23608 uint64_t packet_number,
609 uint64_t largest_received,
610 uint64_t smallest_received,
611 uint64_t least_unacked) {
alyssar2adf3ac2016-05-03 17:12:58612 return server_maker_.MakeAckPacket(packet_number, largest_received,
Bence Béky7a45d4d2020-05-08 01:59:23613 smallest_received, least_unacked);
[email protected]63534512012-12-23 18:49:00614 }
615
Ryan Hamilton0d65a8c2019-06-07 00:46:02616 std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket() {
617 return client_maker_.MakeInitialSettingsPacket(1);
fayang3bcb8b502016-12-07 21:44:37618 }
619
Renjie Tangaadb84b2019-08-31 01:00:23620 std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket(
621 int packet_number) {
622 return client_maker_.MakeInitialSettingsPacket(packet_number);
623 }
624
Victor Vasiliev076657c2019-03-12 02:46:43625 std::string ConstructDataHeader(size_t body_len) {
Nick Harperc6cb7a612020-02-24 20:03:32626 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:41627 return "";
628 }
Ian Swett17d4d1c02021-06-08 19:52:41629 quic::QuicBuffer buffer = quic::HttpEncoder::SerializeDataFrameHeader(
630 body_len, quic::SimpleBufferAllocator::Get());
631 return std::string(buffer.data(), buffer.size());
Renjief49758b2019-01-11 23:32:41632 }
633
Ryan Hamilton8d9ee76e2018-05-29 23:52:52634 void ReceivePromise(quic::QuicStreamId id) {
635 auto headers = quic::test::AsHeaderList(push_promise_);
rch08e198572017-05-09 16:56:55636 QuicChromiumClientStream::Handle* stream =
ckrasic3865ee0f2016-02-29 22:04:56637 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
ckrasic32b17dcd2016-10-31 06:15:35638 stream->OnPromiseHeaderList(id, headers.uncompressed_header_bytes(),
639 headers);
ckrasic3865ee0f2016-02-29 22:04:56640 }
641
xunjieli84adaab2016-09-20 01:12:28642 void ExpectLoadTimingValid(const LoadTimingInfo& load_timing_info,
xunjieli100937eb52016-09-15 20:09:37643 bool session_reused) {
644 EXPECT_EQ(session_reused, load_timing_info.socket_reused);
xunjieli84adaab2016-09-20 01:12:28645 if (session_reused) {
646 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
647 } else {
648 ExpectConnectTimingHasTimes(
649 load_timing_info.connect_timing,
650 CONNECT_TIMING_HAS_SSL_TIMES | CONNECT_TIMING_HAS_DNS_TIMES);
651 }
652 ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info);
xunjieli100937eb52016-09-15 20:09:37653 }
654
Fan Yang32c5a112018-12-10 20:06:33655 quic::QuicStreamId GetNthClientInitiatedBidirectionalStreamId(int n) {
Nick Harper23290b82019-05-02 00:02:56656 return quic::test::GetNthClientInitiatedBidirectionalStreamId(
657 version_.transport_version, n);
ckrasicbf2f59c2017-05-04 23:54:36658 }
659
Fan Yang32c5a112018-12-10 20:06:33660 quic::QuicStreamId GetNthServerInitiatedUnidirectionalStreamId(int n) {
Nick Harper23290b82019-05-02 00:02:56661 return quic::test::GetNthServerInitiatedUnidirectionalStreamId(
662 version_.transport_version, n);
ckrasicbf2f59c2017-05-04 23:54:36663 }
664
Ryan Hamiltona1d1f4a2019-06-26 14:43:04665 QuicFlagSaver saver_;
666
Nick Harper23290b82019-05-02 00:02:56667 const quic::ParsedQuicVersion version_;
Yixin Wang079ad542018-01-11 04:06:05668 const bool client_headers_include_h2_stream_dependency_;
669
Matt Reichhoff0049a0b72021-10-20 20:44:26670 NetLogWithSource net_log_with_source_{
671 NetLogWithSource::Make(NetLog::Get(), NetLogSourceType::NONE)};
672 RecordingNetLogObserver net_log_observer_;
Keishi Hattori0e45c022021-11-27 09:25:52673 raw_ptr<quic::test::MockSendAlgorithm> send_algorithm_;
[email protected]f702d572012-12-04 15:56:20674 scoped_refptr<TestTaskRunner> runner_;
danakjad1777e2016-04-16 00:56:42675 std::unique_ptr<MockWrite[]> mock_writes_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52676 quic::MockClock clock_;
Keishi Hattori0e45c022021-11-27 09:25:52677 raw_ptr<TestQuicConnection> connection_;
danakjad1777e2016-04-16 00:56:42678 std::unique_ptr<QuicChromiumConnectionHelper> helper_;
rch16c74d1d2016-04-22 06:14:07679 std::unique_ptr<QuicChromiumAlarmFactory> alarm_factory_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52680 testing::StrictMock<quic::test::MockQuicConnectionVisitor> visitor_;
rch97827ee2017-05-24 23:49:12681 std::unique_ptr<UploadDataStream> upload_data_stream_;
danakjad1777e2016-04-16 00:56:42682 std::unique_ptr<QuicHttpStream> stream_;
[email protected]5db452202014-08-19 05:22:15683 TransportSecurityState transport_security_state_;
danakjad1777e2016-04-16 00:56:42684 std::unique_ptr<QuicChromiumClientSession> session_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52685 quic::QuicCryptoClientConfig crypto_config_;
[email protected]f702d572012-12-04 15:56:20686 TestCompletionCallback callback_;
687 HttpRequestInfo request_;
688 HttpRequestHeaders headers_;
689 HttpResponseInfo response_;
690 scoped_refptr<IOBufferWithSize> read_buffer_;
Bence Béky4c325e52020-10-22 20:48:01691 spdy::Http2HeaderBlock request_headers_;
692 spdy::Http2HeaderBlock response_headers_;
bnc614a92d32016-04-04 13:56:07693 string request_data_;
694 string response_data_;
[email protected]f702d572012-12-04 15:56:20695
ckrasic3865ee0f2016-02-29 22:04:56696 // For server push testing
danakjad1777e2016-04-16 00:56:42697 std::unique_ptr<QuicHttpStream> promised_stream_;
Bence Béky4c325e52020-10-22 20:48:01698 spdy::Http2HeaderBlock push_promise_;
699 spdy::Http2HeaderBlock promised_response_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52700 const quic::QuicStreamId promise_id_;
ckrasic3865ee0f2016-02-29 22:04:56701 string promise_url_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52702 const quic::QuicStreamId stream_id_;
ckrasic3865ee0f2016-02-29 22:04:56703
Ryan Hamilton8d9ee76e2018-05-29 23:52:52704 const quic::QuicConnectionId connection_id_;
alyssar2adf3ac2016-05-03 17:12:58705 QuicTestPacketMaker client_maker_;
706 QuicTestPacketMaker server_maker_;
[email protected]f702d572012-12-04 15:56:20707 IPEndPoint self_addr_;
708 IPEndPoint peer_addr_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52709 quic::test::MockRandom random_generator_;
rch03b7a202016-02-05 00:54:20710 ProofVerifyDetailsChromium verify_details_;
[email protected]e8ff26842013-03-22 21:02:05711 MockCryptoClientStreamFactory crypto_client_stream_factory_;
danakjad1777e2016-04-16 00:56:42712 std::unique_ptr<StaticSocketDataProvider> socket_data_;
Ryan Hamilton0d65a8c2019-06-07 00:46:02713 QuicPacketPrinter printer_;
[email protected]f702d572012-12-04 15:56:20714 std::vector<PacketToWrite> writes_;
Bence Béky6e243aa2019-12-13 19:01:07715 quic::test::NoopQpackStreamSenderDelegate noop_qpack_stream_sender_delegate_;
[email protected]f702d572012-12-04 15:56:20716};
717
David Schinazi09e9a6012019-10-03 17:37:57718INSTANTIATE_TEST_SUITE_P(VersionIncludeStreamDependencySequence,
719 QuicHttpStreamTest,
720 ::testing::ValuesIn(GetTestParams()),
721 ::testing::PrintToStringParamName());
[email protected]1e960032013-12-20 19:00:20722
723TEST_P(QuicHttpStreamTest, RenewStreamForAuth) {
[email protected]ed3fc15d2013-03-08 18:37:44724 Initialize();
rtennetibe635732014-10-02 22:51:42725 EXPECT_EQ(nullptr, stream_->RenewStreamForAuth());
[email protected]f702d572012-12-04 15:56:20726}
727
mmenkebd84c392015-09-02 14:12:34728TEST_P(QuicHttpStreamTest, CanReuseConnection) {
[email protected]ed3fc15d2013-03-08 18:37:44729 Initialize();
mmenkebd84c392015-09-02 14:12:34730 EXPECT_FALSE(stream_->CanReuseConnection());
[email protected]f702d572012-12-04 15:56:20731}
732
jri231c2972016-03-08 19:50:11733TEST_P(QuicHttpStreamTest, DisableConnectionMigrationForStream) {
Zhongyi Shibb28b1f2018-07-18 02:41:26734 request_.load_flags |= LOAD_DISABLE_CONNECTION_MIGRATION_TO_CELLULAR;
jri231c2972016-03-08 19:50:11735 Initialize();
Matt Reichhoff0049a0b72021-10-20 20:44:26736 EXPECT_EQ(OK, stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
737 net_log_with_source_,
738 callback_.callback()));
rch08e198572017-05-09 16:56:55739 QuicChromiumClientStream::Handle* client_stream =
jri231c2972016-03-08 19:50:11740 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
Zhongyi Shibb28b1f2018-07-18 02:41:26741 EXPECT_FALSE(client_stream->can_migrate_to_cellular_network());
jri231c2972016-03-08 19:50:11742}
743
[email protected]1e960032013-12-20 19:00:20744TEST_P(QuicHttpStreamTest, GetRequest) {
745 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:45746 size_t spdy_request_header_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:23747 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:25748 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:23749 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:37750 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23751 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
752 kIncludeVersion, kFin, DEFAULT_PRIORITY,
753 &spdy_request_header_frame_length));
fayang3bcb8b502016-12-07 21:44:37754
[email protected]f702d572012-12-04 15:56:20755 Initialize();
756
757 request_.method = "GET";
rchcd379012017-04-12 21:53:32758 request_.url = GURL("https://www.example.org/");
[email protected]f702d572012-12-04 15:56:20759
xunjieli100937eb52016-09-15 20:09:37760 // Make sure getting load timing from the stream early does not crash.
761 LoadTimingInfo load_timing_info;
762 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
763
Matt Reichhoff0049a0b72021-10-20 20:44:26764 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
765 net_log_with_source_,
766 callback_.callback()));
rjshaded5ced072015-12-18 19:26:02767 EXPECT_EQ(OK,
768 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20769
770 // Ack the request.
Renjie90e808e2019-01-24 07:24:04771 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]f702d572012-12-04 15:56:20772
robpercival214763f2016-07-01 23:27:01773 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
774 IsError(ERR_IO_PENDING));
[email protected]f702d572012-12-04 15:56:20775
Kenichi Ishibashif8634ab2021-03-16 23:41:28776 SetResponse("404", string());
sclittlec4dc1a32015-09-24 00:15:45777 size_t spdy_response_header_frame_length;
778 ProcessPacket(ConstructResponseHeadersPacket(
779 2, kFin, &spdy_response_header_frame_length));
[email protected]f702d572012-12-04 15:56:20780
781 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:01782 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]cadac622013-06-11 16:46:36783 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:20784 EXPECT_EQ(404, response_.headers->response_code());
785 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
[email protected]6ed67432014-06-24 01:53:53786 EXPECT_FALSE(response_.response_time.is_null());
787 EXPECT_FALSE(response_.request_time.is_null());
[email protected]f702d572012-12-04 15:56:20788
789 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:02790 EXPECT_EQ(0,
791 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
792 callback_.callback()));
[email protected]f702d572012-12-04 15:56:20793 EXPECT_TRUE(stream_->IsResponseBodyComplete());
794 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:10795
xunjieli100937eb52016-09-15 20:09:37796 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
xunjieli84adaab2016-09-20 01:12:28797 ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
xunjieli100937eb52016-09-15 20:09:37798
sclittle1edeeb22015-09-02 20:46:10799 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:45800 // headers and payload.
801 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
802 stream_->GetTotalSentBytes());
803 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length),
804 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:20805}
806
xunjieli100937eb52016-09-15 20:09:37807TEST_P(QuicHttpStreamTest, LoadTimingTwoRequests) {
808 SetRequest("GET", "/", DEFAULT_PRIORITY);
809 size_t spdy_request_header_frame_length;
810
Renjie Tangaadb84b2019-08-31 01:00:23811 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:25812 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:23813 AddWrite(ConstructInitialSettingsPacket(packet_number++));
xunjieli100937eb52016-09-15 20:09:37814 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23815 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
816 kIncludeVersion, kFin, DEFAULT_PRIORITY,
817 &spdy_request_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37818
819 // SetRequest() again for second request as |request_headers_| was moved.
820 SetRequest("GET", "/", DEFAULT_PRIORITY);
821 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23822 packet_number++, GetNthClientInitiatedBidirectionalStreamId(1),
823 kIncludeVersion, kFin, DEFAULT_PRIORITY,
824 GetNthClientInitiatedBidirectionalStreamId(0),
Ryan Hamilton0d65a8c2019-06-07 00:46:02825 &spdy_request_header_frame_length));
Renjie Tangcd594f32020-07-11 20:18:34826 AddWrite(
827 ConstructClientAckPacket(packet_number++, 3, 1)); // Ack the responses.
xunjieli100937eb52016-09-15 20:09:37828
829 Initialize();
830
831 request_.method = "GET";
rchcd379012017-04-12 21:53:32832 request_.url = GURL("https://www.example.org/");
xunjieli100937eb52016-09-15 20:09:37833 // Start first request.
Matt Reichhoff0049a0b72021-10-20 20:44:26834 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
835 net_log_with_source_,
836 callback_.callback()));
xunjieli100937eb52016-09-15 20:09:37837 EXPECT_EQ(OK,
838 stream_->SendRequest(headers_, &response_, callback_.callback()));
839
840 // Start a second request.
Dan McArdle68a5f622021-07-09 20:56:53841 QuicHttpStream stream2(session_->CreateHandle(url::SchemeHostPort(
842 url::kHttpsScheme, "www.example.org", 443)),
843 {} /* dns_aliases */);
xunjieli100937eb52016-09-15 20:09:37844 TestCompletionCallback callback2;
Matt Reichhoff0049a0b72021-10-20 20:44:26845 EXPECT_EQ(
846 OK, stream2.InitializeStream(&request_, true, DEFAULT_PRIORITY,
847 net_log_with_source_, callback2.callback()));
xunjieli100937eb52016-09-15 20:09:37848 EXPECT_EQ(OK,
849 stream2.SendRequest(headers_, &response_, callback2.callback()));
850
851 // Ack both requests.
Renjie90e808e2019-01-24 07:24:04852 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
xunjieli100937eb52016-09-15 20:09:37853
854 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
855 IsError(ERR_IO_PENDING));
856 size_t spdy_response_header_frame_length;
Kenichi Ishibashif8634ab2021-03-16 23:41:28857 SetResponse("200", string());
xunjieli100937eb52016-09-15 20:09:37858 ProcessPacket(InnerConstructResponseHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33859 2, GetNthClientInitiatedBidirectionalStreamId(0), kFin,
ckrasicbf2f59c2017-05-04 23:54:36860 &spdy_response_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37861
862 // Now that the headers have been processed, the callback will return.
863 EXPECT_THAT(callback_.WaitForResult(), IsOk());
864 EXPECT_EQ(200, response_.headers->response_code());
865
866 // There is no body, so this should return immediately.
867 EXPECT_EQ(0,
868 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
869 callback_.callback()));
870 EXPECT_TRUE(stream_->IsResponseBodyComplete());
871
872 LoadTimingInfo load_timing_info;
873 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
xunjieli84adaab2016-09-20 01:12:28874 ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
xunjieli100937eb52016-09-15 20:09:37875
876 // SetResponse() again for second request as |response_headers_| was moved.
Kenichi Ishibashif8634ab2021-03-16 23:41:28877 SetResponse("200", string());
xunjieli100937eb52016-09-15 20:09:37878 EXPECT_THAT(stream2.ReadResponseHeaders(callback2.callback()),
879 IsError(ERR_IO_PENDING));
880
881 ProcessPacket(InnerConstructResponseHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33882 3, GetNthClientInitiatedBidirectionalStreamId(1), kFin,
ckrasicbf2f59c2017-05-04 23:54:36883 &spdy_response_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37884
885 EXPECT_THAT(callback2.WaitForResult(), IsOk());
886
887 // There is no body, so this should return immediately.
888 EXPECT_EQ(0,
889 stream2.ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
890 callback2.callback()));
891 EXPECT_TRUE(stream2.IsResponseBodyComplete());
892
893 LoadTimingInfo load_timing_info2;
894 EXPECT_TRUE(stream2.GetLoadTimingInfo(&load_timing_info2));
xunjieli84adaab2016-09-20 01:12:28895 ExpectLoadTimingValid(load_timing_info2, /*session_reused=*/true);
xunjieli100937eb52016-09-15 20:09:37896}
897
xunjieli34291fe12016-03-02 13:58:38898// QuicHttpStream does not currently support trailers. It should ignore
899// trailers upon receiving them.
900TEST_P(QuicHttpStreamTest, GetRequestWithTrailers) {
901 SetRequest("GET", "/", DEFAULT_PRIORITY);
902 size_t spdy_request_header_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:23903 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:25904 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:23905 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:37906 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23907 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
908 kIncludeVersion, kFin, DEFAULT_PRIORITY,
909 &spdy_request_header_frame_length));
Renjie Tangcd594f32020-07-11 20:18:34910 AddWrite(
911 ConstructClientAckPacket(packet_number++, 3, 1)); // Ack the data packet.
xunjieli34291fe12016-03-02 13:58:38912
913 Initialize();
914
915 request_.method = "GET";
rchcd379012017-04-12 21:53:32916 request_.url = GURL("https://www.example.org/");
xunjieli34291fe12016-03-02 13:58:38917
Matt Reichhoff0049a0b72021-10-20 20:44:26918 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
919 net_log_with_source_,
920 callback_.callback()));
xunjieli5fafe142016-03-23 23:32:54921
xunjieli34291fe12016-03-02 13:58:38922 EXPECT_EQ(OK,
923 stream_->SendRequest(headers_, &response_, callback_.callback()));
xunjieli34291fe12016-03-02 13:58:38924 // Ack the request.
Renjie90e808e2019-01-24 07:24:04925 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
xunjieli34291fe12016-03-02 13:58:38926
robpercival214763f2016-07-01 23:27:01927 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
928 IsError(ERR_IO_PENDING));
xunjieli34291fe12016-03-02 13:58:38929
Kenichi Ishibashif8634ab2021-03-16 23:41:28930 SetResponse("200", string());
xunjieli34291fe12016-03-02 13:58:38931
932 // Send the response headers.
933 size_t spdy_response_header_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:02934 ProcessPacket(ConstructResponseHeadersPacket(
935 2, !kFin, &spdy_response_header_frame_length));
xunjieli34291fe12016-03-02 13:58:38936 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:01937 EXPECT_THAT(callback_.WaitForResult(), IsOk());
xunjieli34291fe12016-03-02 13:58:38938 ASSERT_TRUE(response_.headers.get());
939 EXPECT_EQ(200, response_.headers->response_code());
940 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
941 EXPECT_FALSE(response_.response_time.is_null());
942 EXPECT_FALSE(response_.request_time.is_null());
943
944 // Send the response body.
945 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:43946 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:17947 ProcessPacket(
948 ConstructServerDataPacket(3, false, !kFin, header + kResponseBody));
Bence Béky4c325e52020-10-22 20:48:01949 spdy::Http2HeaderBlock trailers;
xunjieli34291fe12016-03-02 13:58:38950 size_t spdy_trailers_frame_length;
951 trailers["foo"] = "bar";
Victor Vasiliev7da08172019-10-14 06:04:25952 if (!quic::VersionUsesHttp3(version_.transport_version)) {
Ryan Hamiltona1d1f4a2019-06-26 14:43:04953 trailers[quic::kFinalOffsetHeaderKey] =
954 base::NumberToString(strlen(kResponseBody) + header.length());
955 }
Ryan Hamilton0d65a8c2019-06-07 00:46:02956 ProcessPacket(ConstructResponseTrailersPacket(4, kFin, std::move(trailers),
957 &spdy_trailers_frame_length));
xunjieli34291fe12016-03-02 13:58:38958
959 // Make sure trailers are processed.
fdoray92e35a72016-06-10 15:54:55960 base::RunLoop().RunUntilIdle();
xunjieli34291fe12016-03-02 13:58:38961
962 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
963 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
964 callback_.callback()));
965 EXPECT_TRUE(stream_->IsResponseBodyComplete());
966
967 EXPECT_EQ(OK,
968 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
969 callback_.callback()));
970
971 EXPECT_TRUE(stream_->IsResponseBodyComplete());
972 EXPECT_TRUE(AtEof());
973
974 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
975 // headers and payload.
976 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
977 stream_->GetTotalSentBytes());
Renjief49758b2019-01-11 23:32:41978 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length +
979 strlen(kResponseBody) + header.length() +
980 +spdy_trailers_frame_length),
981 stream_->GetTotalReceivedBytes());
xunjieli5fafe142016-03-23 23:32:54982 // Check that NetLog was filled as expected.
Matt Reichhoff0049a0b72021-10-20 20:44:26983 auto entries = net_log_observer_.GetEntries();
xunjieli5fafe142016-03-23 23:32:54984 size_t pos = ExpectLogContainsSomewhere(
985 entries, /*min_offset=*/0,
mikecirone8b85c432016-09-08 19:11:00986 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
987 NetLogEventPhase::NONE);
xunjieli5fafe142016-03-23 23:32:54988 pos = ExpectLogContainsSomewhere(
989 entries, /*min_offset=*/pos,
mikecirone8b85c432016-09-08 19:11:00990 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
991 NetLogEventPhase::NONE);
xunjieli5fafe142016-03-23 23:32:54992 ExpectLogContainsSomewhere(
993 entries, /*min_offset=*/pos,
mikecirone8b85c432016-09-08 19:11:00994 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
995 NetLogEventPhase::NONE);
xunjieli34291fe12016-03-02 13:58:38996}
997
Bence Béky6c2c78f2020-08-28 16:49:06998TEST_P(QuicHttpStreamTest, ElideHeadersInNetLog) {
999 Initialize();
1000
1001 // QuicHttp3Logger is only used with HTTP/3.
1002 if (!VersionUsesHttp3(version_.transport_version)) {
1003 return;
1004 }
1005
Matt Reichhoff0049a0b72021-10-20 20:44:261006 net_log_observer_.SetObserverCaptureMode(NetLogCaptureMode::kDefault);
Bence Béky6c2c78f2020-08-28 16:49:061007
Bence Békye0d3747d2020-08-28 23:16:401008 // Send first request.
Bence Béky6c2c78f2020-08-28 16:49:061009 SetRequest("GET", "/", DEFAULT_PRIORITY);
1010 request_.method = "GET";
1011 request_.url = GURL("https://www.example.org/");
1012 headers_.SetHeader(HttpRequestHeaders::kCookie, "secret");
1013
1014 size_t spdy_request_header_frame_length;
Bence Békye0d3747d2020-08-28 23:16:401015 int outgoing_packet_number = 1;
1016 AddWrite(ConstructInitialSettingsPacket(outgoing_packet_number++));
Bence Béky6c2c78f2020-08-28 16:49:061017 AddWrite(InnerConstructRequestHeadersPacket(
Bence Békye0d3747d2020-08-28 23:16:401018 outgoing_packet_number++, stream_id_, kIncludeVersion, kFin,
1019 DEFAULT_PRIORITY, &spdy_request_header_frame_length));
Bence Béky6c2c78f2020-08-28 16:49:061020
Matt Reichhoff0049a0b72021-10-20 20:44:261021 EXPECT_THAT(
1022 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
1023 net_log_with_source_, callback_.callback()),
1024 IsOk());
Bence Béky6c2c78f2020-08-28 16:49:061025 EXPECT_THAT(stream_->SendRequest(headers_, &response_, callback_.callback()),
1026 IsOk());
Bence Békye0d3747d2020-08-28 23:16:401027 int incoming_packet_number = 1;
1028 ProcessPacket(ConstructServerAckPacket(incoming_packet_number++, 1, 1,
1029 1)); // Ack the request.
Bence Béky6c2c78f2020-08-28 16:49:061030
Bence Békye0d3747d2020-08-28 23:16:401031 // Process first response.
Kenichi Ishibashif8634ab2021-03-16 23:41:281032 SetResponse("200", string());
Bence Béky6c2c78f2020-08-28 16:49:061033 response_headers_["set-cookie"] = "secret";
1034 size_t spdy_response_header_frame_length;
1035 ProcessPacket(ConstructResponseHeadersPacket(
Bence Békye0d3747d2020-08-28 23:16:401036 incoming_packet_number++, kFin, &spdy_response_header_frame_length));
Bence Béky6c2c78f2020-08-28 16:49:061037 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
Bence Béky6c2c78f2020-08-28 16:49:061038
1039 ASSERT_TRUE(response_.headers.get());
1040 EXPECT_EQ(200, response_.headers->response_code());
1041 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1042 EXPECT_TRUE(response_.headers->HasHeaderValue("set-cookie", "secret"));
1043
Matt Reichhoff0049a0b72021-10-20 20:44:261044 net_log_observer_.SetObserverCaptureMode(
1045 NetLogCaptureMode::kIncludeSensitive);
Bence Béky6c2c78f2020-08-28 16:49:061046
Bence Békye0d3747d2020-08-28 23:16:401047 // Send second request.
1048 quic::QuicStreamId stream_id = GetNthClientInitiatedBidirectionalStreamId(1);
1049 request_.url = GURL("https://www.example.org/foo");
Bence Béky6c2c78f2020-08-28 16:49:061050
Bence Békye0d3747d2020-08-28 23:16:401051 AddWrite(InnerConstructRequestHeadersPacket(
1052 outgoing_packet_number++, stream_id, kIncludeVersion, kFin,
1053 DEFAULT_PRIORITY, &spdy_request_header_frame_length));
Bence Béky6c2c78f2020-08-28 16:49:061054
Bence Békye0d3747d2020-08-28 23:16:401055 auto stream = std::make_unique<QuicHttpStream>(
Dan McArdle68a5f622021-07-09 20:56:531056 session_->CreateHandle(
1057 url::SchemeHostPort(url::kHttpsScheme, "www.example.org/foo", 443)),
Eric Orthac661912022-01-10 21:44:171058 /*dns_aliases=*/std::set<std::string>());
Matt Reichhoff0049a0b72021-10-20 20:44:261059 EXPECT_THAT(
1060 stream->InitializeStream(&request_, true, DEFAULT_PRIORITY,
1061 net_log_with_source_, callback_.callback()),
1062 IsOk());
Bence Békye0d3747d2020-08-28 23:16:401063 EXPECT_THAT(stream->SendRequest(headers_, &response_, callback_.callback()),
1064 IsOk());
1065 ProcessPacket(ConstructServerAckPacket(incoming_packet_number++, 1, 1,
1066 1)); // Ack the request.
Bence Béky6c2c78f2020-08-28 16:49:061067
Bence Békye0d3747d2020-08-28 23:16:401068 // Process second response.
Kenichi Ishibashif8634ab2021-03-16 23:41:281069 SetResponse("200", string());
Bence Békye0d3747d2020-08-28 23:16:401070 response_headers_["set-cookie"] = "secret";
1071 ProcessPacket(InnerConstructResponseHeadersPacket(
1072 incoming_packet_number++, stream_id, kFin,
1073 &spdy_response_header_frame_length));
1074 EXPECT_THAT(stream->ReadResponseHeaders(callback_.callback()), IsOk());
Bence Béky6c2c78f2020-08-28 16:49:061075
Bence Békye0d3747d2020-08-28 23:16:401076 ASSERT_TRUE(response_.headers.get());
1077 EXPECT_EQ(200, response_.headers->response_code());
1078 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1079 EXPECT_TRUE(response_.headers->HasHeaderValue("set-cookie", "secret"));
1080
1081 EXPECT_TRUE(AtEof());
1082
1083 // Check that sensitive header value were stripped
1084 // for the first transaction (logged with NetLogCaptureMode::kDefault)
1085 // but not for the second (logged with NetLogCaptureMode::kIncludeSensitive).
1086 auto entries =
Matt Reichhoff0049a0b72021-10-20 20:44:261087 net_log_observer_.GetEntriesWithType(NetLogEventType::HTTP3_HEADERS_SENT);
Bence Békye0d3747d2020-08-28 23:16:401088 ASSERT_EQ(2u, entries.size());
1089 EXPECT_TRUE(
1090 CheckHeader(entries[0].params, "cookie", "[6 bytes were stripped]"));
1091 EXPECT_TRUE(CheckHeader(entries[1].params, "cookie", "secret"));
1092
Matt Reichhoff0049a0b72021-10-20 20:44:261093 entries = net_log_observer_.GetEntriesWithType(
1094 NetLogEventType::HTTP3_HEADERS_DECODED);
Bence Békye0d3747d2020-08-28 23:16:401095 ASSERT_EQ(2u, entries.size());
1096 EXPECT_TRUE(
1097 CheckHeader(entries[0].params, "set-cookie", "[6 bytes were stripped]"));
1098 EXPECT_TRUE(CheckHeader(entries[1].params, "set-cookie", "secret"));
Bence Béky6c2c78f2020-08-28 16:49:061099}
1100
[email protected]3e7dca62013-09-10 16:14:231101// Regression test for http://crbug.com/288128
[email protected]1e960032013-12-20 19:00:201102TEST_P(QuicHttpStreamTest, GetRequestLargeResponse) {
1103 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451104 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231105 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251106 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231107 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371108 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231109 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1110 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1111 &spdy_request_headers_frame_length));
[email protected]3e7dca62013-09-10 16:14:231112 Initialize();
1113
1114 request_.method = "GET";
rchcd379012017-04-12 21:53:321115 request_.url = GURL("https://www.example.org/");
[email protected]3e7dca62013-09-10 16:14:231116
Matt Reichhoff0049a0b72021-10-20 20:44:261117 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
1118 net_log_with_source_,
1119 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021120 EXPECT_EQ(OK,
1121 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:231122
1123 // Ack the request.
Renjie90e808e2019-01-24 07:24:041124 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]3e7dca62013-09-10 16:14:231125
robpercival214763f2016-07-01 23:27:011126 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1127 IsError(ERR_IO_PENDING));
[email protected]3e7dca62013-09-10 16:14:231128
Kenichi Ishibashif8634ab2021-03-16 23:41:281129 response_headers_[":status"] = "200";
bnc086b39e12016-06-24 13:05:261130 response_headers_[":version"] = "HTTP/1.1";
1131 response_headers_["content-type"] = "text/plain";
1132 response_headers_["big6"] = string(1000, 'x'); // Lots of x's.
[email protected]3e7dca62013-09-10 16:14:231133
sclittlec4dc1a32015-09-24 00:15:451134 size_t spdy_response_headers_frame_length;
1135 ProcessPacket(ConstructResponseHeadersPacket(
1136 2, kFin, &spdy_response_headers_frame_length));
[email protected]3e7dca62013-09-10 16:14:231137
1138 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:011139 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]3e7dca62013-09-10 16:14:231140 ASSERT_TRUE(response_.headers.get());
1141 EXPECT_EQ(200, response_.headers->response_code());
1142 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1143
1144 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:021145 EXPECT_EQ(0,
1146 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1147 callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:231148 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1149 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101150
1151 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451152 // headers and payload.
1153 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1154 stream_->GetTotalSentBytes());
1155 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length),
1156 stream_->GetTotalReceivedBytes());
[email protected]3e7dca62013-09-10 16:14:231157}
1158
rchf9f103cbc2014-08-30 05:28:041159// Regression test for http://crbug.com/409101
1160TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendRequest) {
1161 SetRequest("GET", "/", DEFAULT_PRIORITY);
1162 Initialize();
1163
1164 request_.method = "GET";
rchcd379012017-04-12 21:53:321165 request_.url = GURL("https://www.example.org/");
rchf9f103cbc2014-08-30 05:28:041166
Matt Reichhoff0049a0b72021-10-20 20:44:261167 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
1168 net_log_with_source_,
1169 callback_.callback()));
rchf9f103cbc2014-08-30 05:28:041170
jri78ec06a2016-03-31 18:19:401171 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521172 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rchf9f103cbc2014-08-30 05:28:041173
1174 EXPECT_EQ(ERR_CONNECTION_CLOSED,
rjshaded5ced072015-12-18 19:26:021175 stream_->SendRequest(headers_, &response_, callback_.callback()));
sclittle1edeeb22015-09-02 20:46:101176
1177 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1178 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rchf9f103cbc2014-08-30 05:28:041179}
1180
rch03b7a202016-02-05 00:54:201181// Regression test for http://crbug.com/584441
1182TEST_P(QuicHttpStreamTest, GetSSLInfoAfterSessionClosed) {
1183 SetRequest("GET", "/", DEFAULT_PRIORITY);
1184 Initialize();
1185
1186 request_.method = "GET";
rchcd379012017-04-12 21:53:321187 request_.url = GURL("https://www.example.org/");
rch03b7a202016-02-05 00:54:201188
Matt Reichhoff0049a0b72021-10-20 20:44:261189 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
1190 net_log_with_source_,
1191 callback_.callback()));
rch03b7a202016-02-05 00:54:201192
1193 SSLInfo ssl_info;
rch11565e02016-02-09 20:13:471194 EXPECT_FALSE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:201195 stream_->GetSSLInfo(&ssl_info);
rch11565e02016-02-09 20:13:471196 EXPECT_TRUE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:201197
jri78ec06a2016-03-31 18:19:401198 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521199 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rch03b7a202016-02-05 00:54:201200
rch11565e02016-02-09 20:13:471201 SSLInfo ssl_info2;
1202 stream_->GetSSLInfo(&ssl_info2);
1203 EXPECT_TRUE(ssl_info2.is_valid());
rch03b7a202016-02-05 00:54:201204}
1205
rchcd379012017-04-12 21:53:321206TEST_P(QuicHttpStreamTest, GetAlternativeService) {
1207 SetRequest("GET", "/", DEFAULT_PRIORITY);
1208 Initialize();
1209
1210 request_.method = "GET";
1211 request_.url = GURL("https://www.example.org/");
1212
Matt Reichhoff0049a0b72021-10-20 20:44:261213 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
1214 net_log_with_source_,
1215 callback_.callback()));
rchcd379012017-04-12 21:53:321216
1217 AlternativeService alternative_service;
1218 EXPECT_TRUE(stream_->GetAlternativeService(&alternative_service));
1219 EXPECT_EQ(AlternativeService(kProtoQUIC, "www.example.org", 443),
1220 alternative_service);
1221
1222 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521223 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rchcd379012017-04-12 21:53:321224
1225 AlternativeService alternative_service2;
1226 EXPECT_TRUE(stream_->GetAlternativeService(&alternative_service2));
1227 EXPECT_EQ(AlternativeService(kProtoQUIC, "www.example.org", 443),
1228 alternative_service2);
1229}
1230
zhongyica364fbb2015-12-12 03:39:121231TEST_P(QuicHttpStreamTest, LogGranularQuicConnectionError) {
1232 SetRequest("GET", "/", DEFAULT_PRIORITY);
1233 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231234 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251235 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231236 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371237 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231238 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1239 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1240 &spdy_request_headers_frame_length));
fayang3bcb8b502016-12-07 21:44:371241 AddWrite(ConstructAckAndRstStreamPacket(3));
zhongyica364fbb2015-12-12 03:39:121242 Initialize();
1243
1244 request_.method = "GET";
rchcd379012017-04-12 21:53:321245 request_.url = GURL("https://www.example.org/");
zhongyica364fbb2015-12-12 03:39:121246
Matt Reichhoff0049a0b72021-10-20 20:44:261247 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
1248 net_log_with_source_,
1249 callback_.callback()));
zhongyica364fbb2015-12-12 03:39:121250 EXPECT_EQ(OK,
1251 stream_->SendRequest(headers_, &response_, callback_.callback()));
1252
1253 // Ack the request.
Renjie90e808e2019-01-24 07:24:041254 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011255 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1256 IsError(ERR_IO_PENDING));
zhongyica364fbb2015-12-12 03:39:121257
Ryan Hamilton8d9ee76e2018-05-29 23:52:521258 quic::QuicConnectionCloseFrame frame;
Zhongyi Shica576df2019-04-12 17:43:401259 frame.quic_error_code = quic::QUIC_PEER_GOING_AWAY;
rch1c5b74a2016-06-23 22:10:551260 session_->connection()->OnConnectionCloseFrame(frame);
zhongyica364fbb2015-12-12 03:39:121261
1262 NetErrorDetails details;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521263 EXPECT_EQ(quic::QUIC_NO_ERROR, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121264 stream_->PopulateNetErrorDetails(&details);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521265 EXPECT_EQ(quic::QUIC_PEER_GOING_AWAY, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121266}
1267
Ryan Hamiltone316e482017-08-17 02:48:531268TEST_P(QuicHttpStreamTest, LogGranularQuicErrorIfHandshakeNotConfirmed) {
rch617e0652017-04-26 17:57:511269 // By default the test setup defaults handshake to be confirmed. Manually set
1270 // it to be not confirmed.
rch617e0652017-04-26 17:57:511271 crypto_client_stream_factory_.set_handshake_mode(
Ryan Hamilton9835e662018-08-02 05:36:271272 MockCryptoClientStream::ZERO_RTT);
rch617e0652017-04-26 17:57:511273
zhongyica364fbb2015-12-12 03:39:121274 SetRequest("GET", "/", DEFAULT_PRIORITY);
1275 size_t spdy_request_headers_frame_length;
Michael Warres167db3e2019-03-01 21:38:031276 client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
Nick Harper057264a82019-09-12 23:33:491277 client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
1278 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251279 if (VersionUsesHttp3(version_.transport_version))
Nick Harper057264a82019-09-12 23:33:491280 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371281 AddWrite(InnerConstructRequestHeadersPacket(
Nick Harper057264a82019-09-12 23:33:491282 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1283 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1284 &spdy_request_headers_frame_length));
zhongyica364fbb2015-12-12 03:39:121285 Initialize();
1286
1287 request_.method = "GET";
rchcd379012017-04-12 21:53:321288 request_.url = GURL("https://www.example.org/");
zhongyica364fbb2015-12-12 03:39:121289
Matt Reichhoff0049a0b72021-10-20 20:44:261290 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
1291 net_log_with_source_,
1292 callback_.callback()));
zhongyica364fbb2015-12-12 03:39:121293 EXPECT_EQ(OK,
1294 stream_->SendRequest(headers_, &response_, callback_.callback()));
1295
1296 // Ack the request.
Renjie90e808e2019-01-24 07:24:041297 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011298 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1299 IsError(ERR_IO_PENDING));
zhongyica364fbb2015-12-12 03:39:121300
Ryan Hamilton8d9ee76e2018-05-29 23:52:521301 quic::QuicConnectionCloseFrame frame;
Zhongyi Shica576df2019-04-12 17:43:401302 frame.quic_error_code = quic::QUIC_PEER_GOING_AWAY;
rch1c5b74a2016-06-23 22:10:551303 session_->connection()->OnConnectionCloseFrame(frame);
zhongyica364fbb2015-12-12 03:39:121304
1305 NetErrorDetails details;
zhongyica364fbb2015-12-12 03:39:121306 stream_->PopulateNetErrorDetails(&details);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521307 EXPECT_EQ(quic::QUIC_PEER_GOING_AWAY, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121308}
1309
rch11a114a2014-09-04 23:41:591310// Regression test for http://crbug.com/409871
1311TEST_P(QuicHttpStreamTest, SessionClosedBeforeReadResponseHeaders) {
1312 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451313 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231314 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251315 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231316 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371317 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231318 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1319 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1320 &spdy_request_headers_frame_length));
rch11a114a2014-09-04 23:41:591321 Initialize();
1322
1323 request_.method = "GET";
rchcd379012017-04-12 21:53:321324 request_.url = GURL("https://www.example.org/");
rch11a114a2014-09-04 23:41:591325
Matt Reichhoff0049a0b72021-10-20 20:44:261326 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
1327 net_log_with_source_,
1328 callback_.callback()));
rch11a114a2014-09-04 23:41:591329
rjshaded5ced072015-12-18 19:26:021330 EXPECT_EQ(OK,
1331 stream_->SendRequest(headers_, &response_, callback_.callback()));
rch11a114a2014-09-04 23:41:591332
jri78ec06a2016-03-31 18:19:401333 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521334 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rch11a114a2014-09-04 23:41:591335
1336 EXPECT_NE(OK, stream_->ReadResponseHeaders(callback_.callback()));
sclittle1edeeb22015-09-02 20:46:101337
1338 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451339 // headers and payload.
1340 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1341 stream_->GetTotalSentBytes());
sclittle1edeeb22015-09-02 20:46:101342 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rch11a114a2014-09-04 23:41:591343}
1344
[email protected]1e960032013-12-20 19:00:201345TEST_P(QuicHttpStreamTest, SendPostRequest) {
1346 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451347 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231348 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251349 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231350 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Yixin Wange7ecc472018-03-06 19:00:251351
Victor Vasiliev076657c2019-03-12 02:46:431352 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:321353 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411354 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231355 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1356 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1357 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411358 } else {
1359 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231360 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1361 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1362 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411363 }
Yixin Wange7ecc472018-03-06 19:00:251364
Renjie Tangcd594f32020-07-11 20:18:341365 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]f702d572012-12-04 15:56:201366
1367 Initialize();
1368
danakjad1777e2016-04-16 00:56:421369 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:191370 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
ricea2deef682016-09-09 08:04:071371 kUploadData, strlen(kUploadData)));
rch97827ee2017-05-24 23:49:121372 upload_data_stream_ =
Jeremy Roman0579ed62017-08-29 15:56:191373 std::make_unique<ElementsUploadDataStream>(std::move(element_readers), 0);
[email protected]f702d572012-12-04 15:56:201374 request_.method = "POST";
rchcd379012017-04-12 21:53:321375 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121376 request_.upload_data_stream = upload_data_stream_.get();
Bence Békyd8a21fc32018-06-27 18:29:581377 ASSERT_THAT(request_.upload_data_stream->Init(CompletionOnceCallback(),
tfarina42834112016-09-22 13:38:201378 NetLogWithSource()),
1379 IsOk());
[email protected]f702d572012-12-04 15:56:201380
Matt Reichhoff0049a0b72021-10-20 20:44:261381 EXPECT_EQ(OK, stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1382 net_log_with_source_,
1383 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021384 EXPECT_EQ(OK,
1385 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:201386
1387 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041388 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]f702d572012-12-04 15:56:201389
1390 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281391 SetResponse("200", string());
sclittlec4dc1a32015-09-24 00:15:451392 size_t spdy_response_headers_frame_length;
1393 ProcessPacket(ConstructResponseHeadersPacket(
1394 2, !kFin, &spdy_response_headers_frame_length));
[email protected]f702d572012-12-04 15:56:201395
rchfb47f712017-05-21 03:24:001396 // The headers have already arrived.
1397 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]cadac622013-06-11 16:46:361398 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:201399 EXPECT_EQ(200, response_.headers->response_code());
1400 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1401
1402 // Send the response body.
1403 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431404 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:411405 ProcessPacket(
Ryan Hamilton7505eb92019-06-08 00:22:171406 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
[email protected]f702d572012-12-04 15:56:201407 // Since the body has already arrived, this should return immediately.
1408 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
1409 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1410 callback_.callback()));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291411 EXPECT_EQ(0,
1412 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1413 callback_.callback()));
1414
1415 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1416 EXPECT_TRUE(AtEof());
1417
1418 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
1419 // headers and payload.
1420 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411421 strlen(kUploadData) + header.length()),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291422 stream_->GetTotalSentBytes());
1423 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411424 strlen(kResponseBody) + header2.length()),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291425 stream_->GetTotalReceivedBytes());
1426}
1427
1428TEST_P(QuicHttpStreamTest, SendPostRequestAndReceiveSoloFin) {
1429 SetRequest("POST", "/", DEFAULT_PRIORITY);
1430 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231431 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251432 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231433 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431434 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:321435 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411436 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231437 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1438 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1439 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411440 } else {
1441 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231442 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1443 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1444 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411445 }
1446
Renjie Tangcd594f32020-07-11 20:18:341447 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291448
1449 Initialize();
1450
1451 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:191452 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
Ryan Hamilton2ef0a9c2017-07-25 03:18:291453 kUploadData, strlen(kUploadData)));
1454 upload_data_stream_ =
Jeremy Roman0579ed62017-08-29 15:56:191455 std::make_unique<ElementsUploadDataStream>(std::move(element_readers), 0);
Ryan Hamilton2ef0a9c2017-07-25 03:18:291456 request_.method = "POST";
1457 request_.url = GURL("https://www.example.org/");
1458 request_.upload_data_stream = upload_data_stream_.get();
Bence Békyd8a21fc32018-06-27 18:29:581459 ASSERT_THAT(request_.upload_data_stream->Init(CompletionOnceCallback(),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291460 NetLogWithSource()),
1461 IsOk());
1462
Matt Reichhoff0049a0b72021-10-20 20:44:261463 EXPECT_EQ(OK, stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1464 net_log_with_source_,
1465 callback_.callback()));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291466 EXPECT_EQ(OK,
1467 stream_->SendRequest(headers_, &response_, callback_.callback()));
1468
1469 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041470 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291471
1472 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281473 SetResponse("200", string());
Ryan Hamilton2ef0a9c2017-07-25 03:18:291474 size_t spdy_response_headers_frame_length;
1475 ProcessPacket(ConstructResponseHeadersPacket(
1476 2, !kFin, &spdy_response_headers_frame_length));
1477
1478 // The headers have already arrived.
1479 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
1480 ASSERT_TRUE(response_.headers.get());
1481 EXPECT_EQ(200, response_.headers->response_code());
1482 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1483
1484 // Send the response body.
1485 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431486 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:411487 ProcessPacket(
Ryan Hamilton7505eb92019-06-08 00:22:171488 ConstructServerDataPacket(3, false, !kFin, header2 + kResponseBody));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291489 // Since the body has already arrived, this should return immediately.
1490 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
1491 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1492 callback_.callback()));
Ryan Hamilton7505eb92019-06-08 00:22:171493 ProcessPacket(ConstructServerDataPacket(4, false, kFin, ""));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291494 EXPECT_EQ(0,
1495 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1496 callback_.callback()));
[email protected]f702d572012-12-04 15:56:201497
1498 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1499 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101500
1501 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451502 // headers and payload.
1503 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411504 strlen(kUploadData) + header.length()),
sclittle1edeeb22015-09-02 20:46:101505 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451506 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411507 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101508 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:201509}
1510
[email protected]1e960032013-12-20 19:00:201511TEST_P(QuicHttpStreamTest, SendChunkedPostRequest) {
1512 SetRequest("POST", "/", DEFAULT_PRIORITY);
[email protected]c9e49a02013-02-26 05:56:471513 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:451514 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231515 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251516 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231517 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431518 std::string header = ConstructDataHeader(chunk_size);
Nick Harperc6cb7a612020-02-24 20:03:321519 if (version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411520 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231521 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1522 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1523 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjie Tangd5133972019-12-06 00:20:281524 AddWrite(ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin,
1525 {header + kUploadData}));
Renjief49758b2019-01-11 23:32:411526 } else {
1527 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231528 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1529 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1530 &spdy_request_headers_frame_length, {kUploadData}));
1531 AddWrite(ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin,
1532 kUploadData));
Renjief49758b2019-01-11 23:32:411533 }
1534
Renjie Tangcd594f32020-07-11 20:18:341535 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]c9e49a02013-02-26 05:56:471536 Initialize();
1537
Jeremy Roman0579ed62017-08-29 15:56:191538 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121539 auto* chunked_upload_stream =
1540 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1541 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
[email protected]c9e49a02013-02-26 05:56:471542
1543 request_.method = "POST";
rchcd379012017-04-12 21:53:321544 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121545 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071546 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201547 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]c9e49a02013-02-26 05:56:471548
Matt Reichhoff0049a0b72021-10-20 20:44:261549 ASSERT_EQ(OK, stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1550 net_log_with_source_,
1551 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021552 ASSERT_EQ(ERR_IO_PENDING,
1553 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]c9e49a02013-02-26 05:56:471554
rch97827ee2017-05-24 23:49:121555 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
robpercival214763f2016-07-01 23:27:011556 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]c9e49a02013-02-26 05:56:471557
1558 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041559 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]c9e49a02013-02-26 05:56:471560
1561 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281562 SetResponse("200", string());
sclittlec4dc1a32015-09-24 00:15:451563 size_t spdy_response_headers_frame_length;
1564 ProcessPacket(ConstructResponseHeadersPacket(
1565 2, !kFin, &spdy_response_headers_frame_length));
[email protected]c9e49a02013-02-26 05:56:471566
rchfb47f712017-05-21 03:24:001567 // The headers have already arrived.
1568 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]cadac622013-06-11 16:46:361569 ASSERT_TRUE(response_.headers.get());
[email protected]c9e49a02013-02-26 05:56:471570 EXPECT_EQ(200, response_.headers->response_code());
1571 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1572
1573 // Send the response body.
1574 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431575 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171576 ProcessPacket(
1577 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
[email protected]c9e49a02013-02-26 05:56:471578
1579 // Since the body has already arrived, this should return immediately.
1580 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1581 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1582 callback_.callback()));
1583
1584 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1585 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101586
1587 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451588 // headers and payload.
1589 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411590 strlen(kUploadData) * 2 + header.length() * 2),
sclittle1edeeb22015-09-02 20:46:101591 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451592 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411593 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101594 stream_->GetTotalReceivedBytes());
[email protected]c9e49a02013-02-26 05:56:471595}
1596
[email protected]16ba7742014-08-22 00:57:251597TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithFinalEmptyDataPacket) {
1598 SetRequest("POST", "/", DEFAULT_PRIORITY);
1599 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:451600 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231601 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251602 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231603 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431604 std::string header = ConstructDataHeader(chunk_size);
Renjief49758b2019-01-11 23:32:411605
Nick Harperc6cb7a612020-02-24 20:03:321606 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411607 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231608 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1609 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1610 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411611 } else {
1612 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231613 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1614 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1615 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411616 }
Renjie Tangaadb84b2019-08-31 01:00:231617 AddWrite(
1618 ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin, ""));
Renjie Tangcd594f32020-07-11 20:18:341619 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]16ba7742014-08-22 00:57:251620 Initialize();
1621
Jeremy Roman0579ed62017-08-29 15:56:191622 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121623 auto* chunked_upload_stream =
1624 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1625 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
[email protected]16ba7742014-08-22 00:57:251626
1627 request_.method = "POST";
rchcd379012017-04-12 21:53:321628 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121629 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071630 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201631 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]16ba7742014-08-22 00:57:251632
Matt Reichhoff0049a0b72021-10-20 20:44:261633 ASSERT_EQ(OK, stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1634 net_log_with_source_,
1635 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021636 ASSERT_EQ(ERR_IO_PENDING,
1637 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251638
rch97827ee2017-05-24 23:49:121639 chunked_upload_stream->AppendData(nullptr, 0, true);
robpercival214763f2016-07-01 23:27:011640 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]16ba7742014-08-22 00:57:251641
Renjie90e808e2019-01-24 07:24:041642 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]16ba7742014-08-22 00:57:251643
1644 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281645 SetResponse("200", string());
sclittlec4dc1a32015-09-24 00:15:451646 size_t spdy_response_headers_frame_length;
1647 ProcessPacket(ConstructResponseHeadersPacket(
1648 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251649
rchfb47f712017-05-21 03:24:001650 // The headers have already arrived.
1651 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]16ba7742014-08-22 00:57:251652 ASSERT_TRUE(response_.headers.get());
1653 EXPECT_EQ(200, response_.headers->response_code());
1654 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1655
1656 // Send the response body.
1657 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431658 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171659 ProcessPacket(
1660 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
[email protected]16ba7742014-08-22 00:57:251661
rchb27683c2015-07-29 23:53:501662 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251663 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1664 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1665 callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251666 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1667 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101668
1669 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451670 // headers and payload.
1671 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411672 strlen(kUploadData) + header.length()),
sclittle1edeeb22015-09-02 20:46:101673 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451674 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411675 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101676 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251677}
1678
1679TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithOneEmptyDataPacket) {
1680 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451681 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231682 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251683 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231684 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371685 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231686 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1687 kIncludeVersion, !kFin, DEFAULT_PRIORITY,
1688 &spdy_request_headers_frame_length));
1689 AddWrite(
1690 ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin, ""));
Renjie Tangcd594f32020-07-11 20:18:341691 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]16ba7742014-08-22 00:57:251692 Initialize();
1693
Jeremy Roman0579ed62017-08-29 15:56:191694 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121695 auto* chunked_upload_stream =
1696 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
[email protected]16ba7742014-08-22 00:57:251697
1698 request_.method = "POST";
rchcd379012017-04-12 21:53:321699 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121700 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071701 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201702 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]16ba7742014-08-22 00:57:251703
Matt Reichhoff0049a0b72021-10-20 20:44:261704 ASSERT_EQ(OK, stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1705 net_log_with_source_,
1706 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021707 ASSERT_EQ(ERR_IO_PENDING,
1708 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251709
rch97827ee2017-05-24 23:49:121710 chunked_upload_stream->AppendData(nullptr, 0, true);
robpercival214763f2016-07-01 23:27:011711 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]16ba7742014-08-22 00:57:251712
Renjie90e808e2019-01-24 07:24:041713 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]16ba7742014-08-22 00:57:251714
1715 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281716 SetResponse("200", string());
sclittlec4dc1a32015-09-24 00:15:451717 size_t spdy_response_headers_frame_length;
1718 ProcessPacket(ConstructResponseHeadersPacket(
1719 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251720
rchfb47f712017-05-21 03:24:001721 // The headers have already arrived.
1722 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]16ba7742014-08-22 00:57:251723 ASSERT_TRUE(response_.headers.get());
1724 EXPECT_EQ(200, response_.headers->response_code());
1725 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1726
1727 // Send the response body.
1728 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431729 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171730 ProcessPacket(
1731 ConstructServerDataPacket(3, false, kFin, header + kResponseBody));
[email protected]16ba7742014-08-22 00:57:251732
rchb27683c2015-07-29 23:53:501733 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251734 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1735 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1736 callback_.callback()));
1737
1738 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1739 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101740
1741 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451742 // headers and payload.
1743 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1744 stream_->GetTotalSentBytes());
1745 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411746 strlen(kResponseBody) + header.length()),
sclittle1edeeb22015-09-02 20:46:101747 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251748}
1749
Bence Békye3c6f122020-05-08 01:09:471750TEST_P(QuicHttpStreamTest, SendChunkedPostRequestAbortedByResetStream) {
1751 SetRequest("POST", "/", DEFAULT_PRIORITY);
1752 size_t chunk_size = strlen(kUploadData);
1753 size_t spdy_request_headers_frame_length;
1754 int packet_number = 1;
1755
1756 if (version_.UsesHttp3()) {
1757 AddWrite(ConstructInitialSettingsPacket(packet_number++));
1758 }
1759
1760 std::string header = ConstructDataHeader(chunk_size);
1761 if (version_.HasIetfQuicFrames()) {
1762 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1763 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1764 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1765 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjie Tangcd594f32020-07-11 20:18:341766 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
Fan Yang8d4177792021-07-16 17:48:531767 AddWrite(client_maker_.MakeAckAndRstPacket(
1768 packet_number++, true, stream_id_, quic::QUIC_STREAM_NO_ERROR, 4, 1,
Renjie Tangcd594f32020-07-11 20:18:341769 /* include_stop_sending_if_v99 = */ false));
Bence Békye3c6f122020-05-08 01:09:471770 } else {
1771 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1772 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1773 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1774 &spdy_request_headers_frame_length, {kUploadData}));
Renjie Tangcd594f32020-07-11 20:18:341775 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
Bence Békye3c6f122020-05-08 01:09:471776 AddWrite(client_maker_.MakeAckAndRstPacket(
1777 packet_number++,
1778 /* include_version = */ false, stream_id_,
Renjie Tangcd594f32020-07-11 20:18:341779 quic::QUIC_RST_ACKNOWLEDGEMENT, 4, 1,
Bence Békye3c6f122020-05-08 01:09:471780 /* include_stop_sending_if_v99 = */ false));
1781 }
1782
1783 Initialize();
1784
1785 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
1786 auto* chunked_upload_stream =
1787 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1788 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
1789
1790 request_.method = "POST";
1791 request_.url = GURL("https://www.example.org/");
1792 request_.upload_data_stream = upload_data_stream_.get();
1793 ASSERT_THAT(request_.upload_data_stream->Init(
1794 TestCompletionCallback().callback(), NetLogWithSource()),
1795 IsOk());
Matt Reichhoff0049a0b72021-10-20 20:44:261796 ASSERT_THAT(
1797 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1798 net_log_with_source_, callback_.callback()),
1799 IsOk());
Bence Békye3c6f122020-05-08 01:09:471800 ASSERT_THAT(stream_->SendRequest(headers_, &response_, callback_.callback()),
1801 IsError(ERR_IO_PENDING));
1802
1803 // Ack both packets in the request.
1804 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
1805
1806 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281807 SetResponse("200", string());
Bence Békye3c6f122020-05-08 01:09:471808 size_t spdy_response_headers_frame_length;
1809 ProcessPacket(ConstructResponseHeadersPacket(
1810 2, !kFin, &spdy_response_headers_frame_length));
1811
1812 // Send the response body.
1813 const char kResponseBody[] = "Hello world!";
1814 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
1815 ProcessPacket(
1816 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
1817
Bence Béky050ec6d2021-02-25 22:07:051818 if (version_.HasIetfQuicFrames()) {
1819 // In IETF QUIC, the server uses a STOP_SENDING frame to notify the client
1820 // that it does not need any further data to fully process the request.
1821 ProcessPacket(server_maker_.MakeStopSendingPacket(
1822 4, /* include_version = */ false, stream_id_,
1823 quic::QUIC_STREAM_NO_ERROR));
1824 } else {
1825 // Server resets stream with H3_NO_ERROR before request body is complete.
1826 ProcessPacket(server_maker_.MakeRstPacket(4, /* include_version = */ false,
1827 stream_id_,
1828 quic::QUIC_STREAM_NO_ERROR));
1829 }
Bence Békye3c6f122020-05-08 01:09:471830
1831 // Finish feeding request body to QuicHttpStream. Data will be discarded.
1832 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1833 EXPECT_THAT(callback_.WaitForResult(), IsOk());
1834
1835 // Verify response.
1836 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
1837 ASSERT_TRUE(response_.headers.get());
1838 EXPECT_EQ(200, response_.headers->response_code());
1839 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1840 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1841 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1842 callback_.callback()));
1843 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1844 EXPECT_TRUE(AtEof());
1845
1846 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
1847 // headers and payload.
1848 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
1849 strlen(kUploadData) + header.length()),
1850 stream_->GetTotalSentBytes());
1851 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1852 strlen(kResponseBody) + header2.length()),
1853 stream_->GetTotalReceivedBytes());
1854}
1855
[email protected]1e960032013-12-20 19:00:201856TEST_P(QuicHttpStreamTest, DestroyedEarly) {
1857 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451858 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231859 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251860 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231861 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371862 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231863 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1864 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1865 &spdy_request_headers_frame_length));
1866 AddWrite(ConstructAckAndRstStreamPacket(packet_number++));
[email protected]63534512012-12-23 18:49:001867 Initialize();
1868
1869 request_.method = "GET";
rchcd379012017-04-12 21:53:321870 request_.url = GURL("https://www.example.org/");
[email protected]63534512012-12-23 18:49:001871
Matt Reichhoff0049a0b72021-10-20 20:44:261872 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
1873 net_log_with_source_,
1874 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021875 EXPECT_EQ(OK,
1876 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]63534512012-12-23 18:49:001877
1878 // Ack the request.
Renjie90e808e2019-01-24 07:24:041879 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
rchfb47f712017-05-21 03:24:001880 EXPECT_THAT(stream_->ReadResponseHeaders(
Yannic Bonenberger3c96beb2019-09-03 20:41:371881 base::BindOnce(&QuicHttpStreamTest::CloseStream,
1882 base::Unretained(this), stream_.get())),
robpercival214763f2016-07-01 23:27:011883 IsError(ERR_IO_PENDING));
[email protected]63534512012-12-23 18:49:001884
1885 // Send the response with a body.
Kenichi Ishibashif8634ab2021-03-16 23:41:281886 SetResponse("404", "hello world!");
[email protected]63534512012-12-23 18:49:001887 // In the course of processing this packet, the QuicHttpStream close itself.
rchfb47f712017-05-21 03:24:001888 size_t response_size = 0;
rch1bcfddf22017-06-03 00:26:291889 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin, &response_size));
[email protected]63534512012-12-23 18:49:001890
fdoray92e35a72016-06-10 15:54:551891 base::RunLoop().RunUntilIdle();
rchb27683c2015-07-29 23:53:501892
[email protected]63534512012-12-23 18:49:001893 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101894
1895 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451896 // headers and payload.
1897 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1898 stream_->GetTotalSentBytes());
rchfb47f712017-05-21 03:24:001899 // The stream was closed after receiving the headers.
1900 EXPECT_EQ(static_cast<int64_t>(response_size),
1901 stream_->GetTotalReceivedBytes());
[email protected]63534512012-12-23 18:49:001902}
1903
[email protected]1e960032013-12-20 19:00:201904TEST_P(QuicHttpStreamTest, Priority) {
1905 SetRequest("GET", "/", MEDIUM);
sclittlec4dc1a32015-09-24 00:15:451906 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231907 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251908 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231909 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371910 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231911 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1912 kIncludeVersion, kFin, MEDIUM, &spdy_request_headers_frame_length));
[email protected]24e5bc52013-09-18 15:36:581913 Initialize();
1914
1915 request_.method = "GET";
rchcd379012017-04-12 21:53:321916 request_.url = GURL("https://www.example.org/");
[email protected]24e5bc52013-09-18 15:36:581917
Matt Reichhoff0049a0b72021-10-20 20:44:261918 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, MEDIUM,
1919 net_log_with_source_,
1920 callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581921
rjshaded5ced072015-12-18 19:26:021922 EXPECT_EQ(OK,
1923 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581924
[email protected]24e5bc52013-09-18 15:36:581925 // Ack the request.
Renjie90e808e2019-01-24 07:24:041926 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011927 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1928 IsError(ERR_IO_PENDING));
[email protected]24e5bc52013-09-18 15:36:581929
1930 // Send the response with a body.
Kenichi Ishibashif8634ab2021-03-16 23:41:281931 SetResponse("404", "hello world!");
rchfb47f712017-05-21 03:24:001932 size_t response_size = 0;
1933 ProcessPacket(ConstructResponseHeadersPacket(2, kFin, &response_size));
[email protected]24e5bc52013-09-18 15:36:581934
rchfb47f712017-05-21 03:24:001935 EXPECT_EQ(OK, callback_.WaitForResult());
rchb27683c2015-07-29 23:53:501936
[email protected]24e5bc52013-09-18 15:36:581937 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101938
1939 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451940 // headers and payload.
1941 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1942 stream_->GetTotalSentBytes());
rchfb47f712017-05-21 03:24:001943 EXPECT_EQ(static_cast<int64_t>(response_size),
1944 stream_->GetTotalReceivedBytes());
[email protected]24e5bc52013-09-18 15:36:581945}
1946
xunjieli8dff50b2016-07-22 14:19:061947TEST_P(QuicHttpStreamTest, SessionClosedDuringDoLoop) {
1948 SetRequest("POST", "/", DEFAULT_PRIORITY);
1949 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231950 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251951 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231952 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431953 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:321954 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411955 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231956 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1957 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1958 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411959 } else {
1960 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231961 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1962 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1963 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411964 }
1965
xunjieli8dff50b2016-07-22 14:19:061966 // Second data write will result in a synchronous failure which will close
1967 // the session.
1968 AddWrite(SYNCHRONOUS, ERR_FAILED);
1969 Initialize();
1970
Jeremy Roman0579ed62017-08-29 15:56:191971 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121972 auto* chunked_upload_stream =
1973 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
xunjieli8dff50b2016-07-22 14:19:061974
1975 request_.method = "POST";
rchcd379012017-04-12 21:53:321976 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121977 request_.upload_data_stream = upload_data_stream_.get();
xunjieli8dff50b2016-07-22 14:19:061978 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201979 TestCompletionCallback().callback(), NetLogWithSource()));
xunjieli8dff50b2016-07-22 14:19:061980
1981 size_t chunk_size = strlen(kUploadData);
rch97827ee2017-05-24 23:49:121982 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
Matt Reichhoff0049a0b72021-10-20 20:44:261983 ASSERT_EQ(OK, stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1984 net_log_with_source_,
1985 callback_.callback()));
xunjieli8dff50b2016-07-22 14:19:061986 QuicHttpStream* stream = stream_.get();
1987 DeleteStreamCallback delete_stream_callback(std::move(stream_));
1988 // SendRequest() completes asynchronously after the final chunk is added.
Yixin Wange7ecc472018-03-06 19:00:251989 // Error does not surface yet since packet write is triggered by a packet
1990 // flusher that tries to bundle request body writes.
xunjieli8dff50b2016-07-22 14:19:061991 ASSERT_EQ(ERR_IO_PENDING,
1992 stream->SendRequest(headers_, &response_, callback_.callback()));
rch97827ee2017-05-24 23:49:121993 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
xunjieli8dff50b2016-07-22 14:19:061994 int rv = callback_.WaitForResult();
Yixin Wange7ecc472018-03-06 19:00:251995 EXPECT_EQ(OK, rv);
1996 // Error will be surfaced once an attempt to read the response occurs.
1997 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1998 stream->ReadResponseHeaders(callback_.callback()));
xunjieli8dff50b2016-07-22 14:19:061999}
2000
rtenneti15656ae2016-01-23 03:05:032001TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersComplete) {
2002 SetRequest("POST", "/", DEFAULT_PRIORITY);
Victor Vasiliev7da08172019-10-14 06:04:252003 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232004 AddWrite(ConstructInitialSettingsPacket());
rtenneti15656ae2016-01-23 03:05:032005 AddWrite(SYNCHRONOUS, ERR_FAILED);
2006 Initialize();
2007
Jeremy Roman0579ed62017-08-29 15:56:192008 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
Yixin Wange7ecc472018-03-06 19:00:252009 auto* chunked_upload_stream =
2010 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
rtenneti15656ae2016-01-23 03:05:032011
2012 request_.method = "POST";
rchcd379012017-04-12 21:53:322013 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122014 request_.upload_data_stream = upload_data_stream_.get();
rtenneti15656ae2016-01-23 03:05:032015 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202016 TestCompletionCallback().callback(), NetLogWithSource()));
rtenneti15656ae2016-01-23 03:05:032017
Matt Reichhoff0049a0b72021-10-20 20:44:262018 ASSERT_EQ(OK, stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
2019 net_log_with_source_,
2020 callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252021 ASSERT_EQ(ERR_IO_PENDING,
rtenneti15656ae2016-01-23 03:05:032022 stream_->SendRequest(headers_, &response_, callback_.callback()));
mmenkeffff3642017-06-15 17:37:242023
Yixin Wange7ecc472018-03-06 19:00:252024 // Error will be surfaced once |upload_data_stream| triggers the next write.
2025 size_t chunk_size = strlen(kUploadData);
2026 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2027 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR, callback_.WaitForResult());
2028
2029 EXPECT_LE(0, stream_->GetTotalSentBytes());
2030 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2031}
2032
2033TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersCompleteReadResponse) {
2034 SetRequest("POST", "/", DEFAULT_PRIORITY);
Victor Vasiliev7da08172019-10-14 06:04:252035 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232036 AddWrite(ConstructInitialSettingsPacket());
Yixin Wange7ecc472018-03-06 19:00:252037 AddWrite(SYNCHRONOUS, ERR_FAILED);
2038 Initialize();
2039
2040 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
2041 auto* chunked_upload_stream =
2042 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
2043
2044 request_.method = "POST";
2045 request_.url = GURL("https://www.example.org/");
2046 request_.upload_data_stream = upload_data_stream_.get();
2047
2048 size_t chunk_size = strlen(kUploadData);
2049 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2050
2051 ASSERT_EQ(OK, request_.upload_data_stream->Init(
2052 TestCompletionCallback().callback(), NetLogWithSource()));
2053
Matt Reichhoff0049a0b72021-10-20 20:44:262054 ASSERT_EQ(OK, stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
2055 net_log_with_source_,
2056 callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252057 ASSERT_EQ(OK,
2058 stream_->SendRequest(headers_, &response_, callback_.callback()));
2059
2060 // Error will be surfaced once an attempt to read the response occurs.
2061 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
2062 stream_->ReadResponseHeaders(callback_.callback()));
2063
mmenkeffff3642017-06-15 17:37:242064 EXPECT_LE(0, stream_->GetTotalSentBytes());
2065 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rtenneti15656ae2016-01-23 03:05:032066}
2067
2068TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBodyComplete) {
2069 SetRequest("POST", "/", DEFAULT_PRIORITY);
2070 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232071 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252072 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232073 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:372074 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:232075 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2076 kIncludeVersion, !kFin, DEFAULT_PRIORITY,
2077 &spdy_request_headers_frame_length));
rtenneti15656ae2016-01-23 03:05:032078 AddWrite(SYNCHRONOUS, ERR_FAILED);
2079 Initialize();
2080
Jeremy Roman0579ed62017-08-29 15:56:192081 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:122082 auto* chunked_upload_stream =
2083 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
rtenneti15656ae2016-01-23 03:05:032084
2085 request_.method = "POST";
rchcd379012017-04-12 21:53:322086 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122087 request_.upload_data_stream = upload_data_stream_.get();
rtenneti15656ae2016-01-23 03:05:032088 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202089 TestCompletionCallback().callback(), NetLogWithSource()));
rtenneti15656ae2016-01-23 03:05:032090
Matt Reichhoff0049a0b72021-10-20 20:44:262091 ASSERT_EQ(OK, stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
2092 net_log_with_source_,
2093 callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252094 ASSERT_EQ(ERR_IO_PENDING,
rtenneti15656ae2016-01-23 03:05:032095 stream_->SendRequest(headers_, &response_, callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252096
2097 size_t chunk_size = strlen(kUploadData);
2098 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2099 // Error does not surface yet since packet write is triggered by a packet
2100 // flusher that tries to bundle request body writes.
2101 ASSERT_EQ(OK, callback_.WaitForResult());
2102 // Error will be surfaced once an attempt to read the response occurs.
2103 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
2104 stream_->ReadResponseHeaders(callback_.callback()));
2105
2106 EXPECT_LE(0, stream_->GetTotalSentBytes());
2107 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2108}
2109
2110TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBundledBodyComplete) {
2111 SetRequest("POST", "/", DEFAULT_PRIORITY);
2112 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232113 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252114 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232115 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:432116 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:322117 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:412118 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:232119 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2120 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
2121 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:412122 } else {
2123 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:232124 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2125 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
2126 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:412127 }
2128
Yixin Wange7ecc472018-03-06 19:00:252129 AddWrite(SYNCHRONOUS, ERR_FAILED);
2130 Initialize();
2131
2132 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
2133 auto* chunked_upload_stream =
2134 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
2135
2136 request_.method = "POST";
2137 request_.url = GURL("https://www.example.org/");
2138 request_.upload_data_stream = upload_data_stream_.get();
2139
2140 size_t chunk_size = strlen(kUploadData);
2141 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
2142
2143 ASSERT_EQ(OK, request_.upload_data_stream->Init(
2144 TestCompletionCallback().callback(), NetLogWithSource()));
2145
Matt Reichhoff0049a0b72021-10-20 20:44:262146 ASSERT_EQ(OK, stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
2147 net_log_with_source_,
2148 callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252149 ASSERT_EQ(ERR_IO_PENDING,
2150 stream_->SendRequest(headers_, &response_, callback_.callback()));
2151
2152 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2153
2154 // Error does not surface yet since packet write is triggered by a packet
2155 // flusher that tries to bundle request body writes.
2156 ASSERT_EQ(OK, callback_.WaitForResult());
2157 // Error will be surfaced once an attempt to read the response occurs.
2158 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
2159 stream_->ReadResponseHeaders(callback_.callback()));
2160
2161 EXPECT_LE(0, stream_->GetTotalSentBytes());
2162 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rtenneti15656ae2016-01-23 03:05:032163}
2164
ckrasic3865ee0f2016-02-29 22:04:562165TEST_P(QuicHttpStreamTest, ServerPushGetRequest) {
2166 SetRequest("GET", "/", DEFAULT_PRIORITY);
2167 Initialize();
2168
Bin Wue8408792021-08-24 23:25:162169 // Server push is not supported in HTTP/3.
2170 if (version_.UsesHttp3())
2171 return;
2172
ckrasic3865ee0f2016-02-29 22:04:562173 // Initialize the first stream, for receiving the promise on.
2174 request_.method = "GET";
rchcd379012017-04-12 21:53:322175 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562176
Matt Reichhoff0049a0b72021-10-20 20:44:262177 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
2178 net_log_with_source_,
2179 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232180 ASSERT_EQ(OK,
2181 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562182
2183 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2184 // packet, but does it matter?
2185 ReceivePromise(promise_id_);
2186 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2187
2188 request_.url = GURL(promise_url_);
2189
2190 // Make the second stream that will exercise the first step of the
2191 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272192 EXPECT_EQ(OK, promised_stream_->InitializeStream(
Matt Reichhoff0049a0b72021-10-20 20:44:262193 &request_, true, DEFAULT_PRIORITY, net_log_with_source_,
Steven Valdezb4ff0412018-01-18 22:39:272194 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562195
2196 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252197 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562198 size_t spdy_response_headers_frame_length;
2199 ProcessPacket(InnerConstructResponseHeadersPacket(
2200 1, promise_id_, false, &spdy_response_headers_frame_length));
2201
2202 // Receive the promised response body.
2203 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432204 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172205 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2206 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562207
2208 // Now sending a matching request will have successful rendezvous
2209 // with the promised stream.
Ryan Hamiltona1d1f4a2019-06-26 14:43:042210 ASSERT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
ckrasic3865ee0f2016-02-29 22:04:562211 callback_.callback()));
2212
2213 EXPECT_EQ(
2214 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2215 ->id(),
2216 promise_id_);
2217
2218 // The headers will be immediately available.
robpercival214763f2016-07-01 23:27:012219 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2220 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562221
2222 // As will be the body.
2223 EXPECT_EQ(
2224 static_cast<int>(strlen(kResponseBody)),
2225 promised_stream_->ReadResponseBody(
2226 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2227 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2228 EXPECT_TRUE(AtEof());
2229
ckrasic3865ee0f2016-02-29 22:04:562230 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2231 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412232 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562233 promised_stream_->GetTotalReceivedBytes());
2234}
2235
2236TEST_P(QuicHttpStreamTest, ServerPushGetRequestSlowResponse) {
2237 SetRequest("GET", "/", DEFAULT_PRIORITY);
2238 Initialize();
2239
Bin Wue8408792021-08-24 23:25:162240 // Server push is not supported in HTTP/3.
2241 if (version_.UsesHttp3())
2242 return;
2243
ckrasic3865ee0f2016-02-29 22:04:562244 // Initialize the first stream, for receiving the promise on.
2245 request_.method = "GET";
rchcd379012017-04-12 21:53:322246 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562247
Matt Reichhoff0049a0b72021-10-20 20:44:262248 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
2249 net_log_with_source_,
2250 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232251 ASSERT_EQ(OK,
2252 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562253
2254 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2255 // packet, but does it matter?
2256 ReceivePromise(promise_id_);
2257 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2258
2259 request_.url = GURL(promise_url_);
2260
2261 // Make the second stream that will exercise the first step of the
2262 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272263 EXPECT_EQ(OK, promised_stream_->InitializeStream(
Matt Reichhoff0049a0b72021-10-20 20:44:262264 &request_, true, DEFAULT_PRIORITY, net_log_with_source_,
Steven Valdezb4ff0412018-01-18 22:39:272265 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562266
2267 // Now sending a matching request will rendezvous with the promised
2268 // stream, but pending secondary validation.
2269 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2270 headers_, &response_, callback_.callback()));
2271
2272 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252273 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562274 size_t spdy_response_headers_frame_length;
2275 ProcessPacket(InnerConstructResponseHeadersPacket(
2276 1, promise_id_, false, &spdy_response_headers_frame_length));
2277
2278 // Receive the promised response body.
2279 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432280 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172281 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2282 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562283
fdoray92e35a72016-06-10 15:54:552284 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562285
2286 // Rendezvous should have succeeded now, so the promised stream
2287 // should point at our push stream, and we should be able read
2288 // headers and data from it.
robpercival214763f2016-07-01 23:27:012289 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562290
2291 EXPECT_EQ(
2292 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2293 ->id(),
2294 promise_id_);
2295
robpercival214763f2016-07-01 23:27:012296 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2297 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562298
2299 EXPECT_EQ(
2300 static_cast<int>(strlen(kResponseBody)),
2301 promised_stream_->ReadResponseBody(
2302 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2303
2304 // Callback should return
2305 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2306 EXPECT_TRUE(AtEof());
2307
ckrasic3865ee0f2016-02-29 22:04:562308 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2309 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412310 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562311 promised_stream_->GetTotalReceivedBytes());
2312}
2313
ckrasic2c63f9b2016-08-16 23:54:072314// Verify fix for crbug.com/637349
2315TEST_P(QuicHttpStreamTest, ServerPushCancelHttpStreamBeforeResponse) {
2316 SetRequest("GET", "/", DEFAULT_PRIORITY);
2317 Initialize();
2318
Bin Wue8408792021-08-24 23:25:162319 // Server push is not supported in HTTP/3.
2320 if (version_.UsesHttp3())
2321 return;
2322
ckrasic2c63f9b2016-08-16 23:54:072323 // Initialize the first stream, for receiving the promise on.
2324 request_.method = "GET";
rchcd379012017-04-12 21:53:322325 request_.url = GURL("https://www.example.org/");
ckrasic2c63f9b2016-08-16 23:54:072326
Matt Reichhoff0049a0b72021-10-20 20:44:262327 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
2328 net_log_with_source_,
2329 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232330 ASSERT_EQ(OK,
2331 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic2c63f9b2016-08-16 23:54:072332
2333 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2334 // packet, but does it matter?
2335 ReceivePromise(promise_id_);
2336 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2337
2338 request_.url = GURL(promise_url_);
2339
2340 // Make the second stream that will exercise the first step of the
2341 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272342 EXPECT_EQ(OK, promised_stream_->InitializeStream(
Matt Reichhoff0049a0b72021-10-20 20:44:262343 &request_, true, DEFAULT_PRIORITY, net_log_with_source_,
Steven Valdezb4ff0412018-01-18 22:39:272344 callback_.callback()));
ckrasic2c63f9b2016-08-16 23:54:072345
2346 // Now sending a matching request will rendezvous with the promised
2347 // stream, but pending secondary validation.
2348 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2349 headers_, &response_, callback_.callback()));
2350
2351 base::RunLoop().RunUntilIdle();
2352
2353 // Cause of FinalValidation() crash as per bug.
2354 promised_stream_.reset();
2355
2356 // Receive the promised response headers.
2357 response_headers_ = promised_response_.Clone();
2358 size_t spdy_response_headers_frame_length;
2359 ProcessPacket(InnerConstructResponseHeadersPacket(
2360 1, promise_id_, false, &spdy_response_headers_frame_length));
2361}
2362
ckrasic3865ee0f2016-02-29 22:04:562363TEST_P(QuicHttpStreamTest, ServerPushCrossOriginOK) {
2364 SetRequest("GET", "/", DEFAULT_PRIORITY);
2365 Initialize();
2366
Bin Wue8408792021-08-24 23:25:162367 // Server push is not supported in HTTP/3.
2368 if (version_.UsesHttp3())
2369 return;
2370
ckrasic3865ee0f2016-02-29 22:04:562371 // Initialize the first stream, for receiving the promise on.
2372 request_.method = "GET";
rchcd379012017-04-12 21:53:322373 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562374
Matt Reichhoff0049a0b72021-10-20 20:44:262375 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
2376 net_log_with_source_,
2377 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232378 ASSERT_EQ(OK,
2379 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562380
2381 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2382 // packet, but does it matter?
2383
2384 push_promise_[":authority"] = "mail.example.org";
David Schinazi3f7465c2019-07-12 01:57:052385 promise_url_ =
2386 quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
ckrasic3865ee0f2016-02-29 22:04:562387
2388 ReceivePromise(promise_id_);
2389 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2390
2391 request_.url = GURL(promise_url_);
2392
2393 // Make the second stream that will exercise the first step of the
2394 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272395 EXPECT_EQ(OK, promised_stream_->InitializeStream(
Matt Reichhoff0049a0b72021-10-20 20:44:262396 &request_, true, DEFAULT_PRIORITY, net_log_with_source_,
Steven Valdezb4ff0412018-01-18 22:39:272397 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562398
2399 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252400 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562401 size_t spdy_response_headers_frame_length;
2402 ProcessPacket(InnerConstructResponseHeadersPacket(
2403 1, promise_id_, false, &spdy_response_headers_frame_length));
2404
2405 // Receive the promised response body.
2406 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432407 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172408 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2409 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562410
2411 // Now sending a matching request will have successful rendezvous
2412 // with the promised stream.
2413 EXPECT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
2414 callback_.callback()));
2415
2416 EXPECT_EQ(
2417 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2418 ->id(),
2419 promise_id_);
2420
2421 // The headers will be immediately available.
robpercival214763f2016-07-01 23:27:012422 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2423 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562424
2425 // As will be the body.
2426 EXPECT_EQ(
2427 static_cast<int>(strlen(kResponseBody)),
2428 promised_stream_->ReadResponseBody(
2429 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2430 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2431 EXPECT_TRUE(AtEof());
2432
ckrasic3865ee0f2016-02-29 22:04:562433 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2434 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412435 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562436 promised_stream_->GetTotalReceivedBytes());
2437}
2438
2439TEST_P(QuicHttpStreamTest, ServerPushCrossOriginFail) {
2440 SetRequest("GET", "/", DEFAULT_PRIORITY);
2441 Initialize();
2442
Bin Wue8408792021-08-24 23:25:162443 // Server push is not supported in HTTP/3.
2444 if (version_.UsesHttp3())
2445 return;
2446
ckrasic3865ee0f2016-02-29 22:04:562447 // Initialize the first stream, for receiving the promise on.
2448 request_.method = "GET";
rchcd379012017-04-12 21:53:322449 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562450
Matt Reichhoff0049a0b72021-10-20 20:44:262451 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
2452 net_log_with_source_,
2453 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232454 ASSERT_EQ(OK,
2455 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562456
2457 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2458 // packet, but does it matter?
2459 push_promise_[":authority"] = "www.notexample.org";
David Schinazi3f7465c2019-07-12 01:57:052460 promise_url_ =
2461 quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
ckrasic3865ee0f2016-02-29 22:04:562462
2463 ReceivePromise(promise_id_);
2464 // The promise will have been rejected because the cert doesn't
2465 // match.
2466 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
2467}
2468
2469TEST_P(QuicHttpStreamTest, ServerPushVaryCheckOK) {
2470 SetRequest("GET", "/", DEFAULT_PRIORITY);
2471 Initialize();
2472
Bin Wue8408792021-08-24 23:25:162473 // Server push is not supported in HTTP/3.
2474 if (version_.UsesHttp3())
2475 return;
2476
ckrasic3865ee0f2016-02-29 22:04:562477 // Initialize the first stream, for receiving the promise on.
2478 request_.method = "GET";
rchcd379012017-04-12 21:53:322479 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562480
Matt Reichhoff0049a0b72021-10-20 20:44:262481 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
2482 net_log_with_source_,
2483 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232484 ASSERT_EQ(OK,
2485 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562486
2487 push_promise_["accept-encoding"] = "gzip";
ckrasic3865ee0f2016-02-29 22:04:562488
2489 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2490 // packet, but does it matter?
2491 ReceivePromise(promise_id_);
2492 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2493
2494 request_.url = GURL(promise_url_);
2495
2496 // Make the second stream that will exercise the first step of the
2497 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272498 EXPECT_EQ(OK, promised_stream_->InitializeStream(
Matt Reichhoff0049a0b72021-10-20 20:44:262499 &request_, true, DEFAULT_PRIORITY, net_log_with_source_,
Steven Valdezb4ff0412018-01-18 22:39:272500 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562501
2502 headers_.SetHeader("accept-encoding", "gzip");
2503
2504 // Now sending a matching request will rendezvous with the promised
2505 // stream, but pending secondary validation.
2506 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2507 headers_, &response_, callback_.callback()));
2508
2509 // Receive the promised response headers.
2510 promised_response_["vary"] = "accept-encoding";
bnc94893a72016-06-30 13:45:252511 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562512 size_t spdy_response_headers_frame_length;
2513 ProcessPacket(InnerConstructResponseHeadersPacket(
2514 1, promise_id_, false, &spdy_response_headers_frame_length));
2515
2516 // Receive the promised response body.
2517 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432518 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172519 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2520 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562521
fdoray92e35a72016-06-10 15:54:552522 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562523
2524 // Rendezvous should have succeeded now, so the promised stream
2525 // should point at our push stream, and we should be able read
2526 // headers and data from it.
robpercival214763f2016-07-01 23:27:012527 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562528
2529 EXPECT_EQ(
2530 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2531 ->id(),
2532 promise_id_);
2533
robpercival214763f2016-07-01 23:27:012534 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2535 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562536
2537 EXPECT_EQ(
2538 static_cast<int>(strlen(kResponseBody)),
2539 promised_stream_->ReadResponseBody(
2540 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2541
2542 // Callback should return
2543 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2544 EXPECT_TRUE(AtEof());
2545
ckrasic3865ee0f2016-02-29 22:04:562546 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2547 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412548 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562549 promised_stream_->GetTotalReceivedBytes());
2550}
2551
2552TEST_P(QuicHttpStreamTest, ServerPushVaryCheckFail) {
2553 SetRequest("GET", "/", DEFAULT_PRIORITY);
2554 request_headers_[":scheme"] = "https";
2555 request_headers_[":path"] = "/bar";
2556 request_headers_["accept-encoding"] = "sdch";
2557
ckrasic3865ee0f2016-02-29 22:04:562558 Initialize();
2559
Bin Wue8408792021-08-24 23:25:162560 // Server push is not supported in HTTP/3.
2561 if (version_.UsesHttp3())
2562 return;
2563
ckrasic3865ee0f2016-02-29 22:04:562564 // Initialize the first stream, for receiving the promise on.
2565 request_.method = "GET";
rchcd379012017-04-12 21:53:322566 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562567
Matt Reichhoff0049a0b72021-10-20 20:44:262568 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
2569 net_log_with_source_,
2570 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232571 ASSERT_EQ(OK,
2572 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562573
2574 push_promise_["accept-encoding"] = "gzip";
ckrasic3865ee0f2016-02-29 22:04:562575
2576 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2577 // packet, but does it matter?
2578 ReceivePromise(promise_id_);
2579 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2580
2581 request_.url = GURL(promise_url_);
2582
2583 // Make the second stream that will exercise the first step of the
2584 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272585 EXPECT_EQ(OK, promised_stream_->InitializeStream(
Matt Reichhoff0049a0b72021-10-20 20:44:262586 &request_, true, DEFAULT_PRIORITY, net_log_with_source_,
Steven Valdezb4ff0412018-01-18 22:39:272587 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562588
2589 headers_.SetHeader("accept-encoding", "sdch");
2590
2591 // Now sending a matching request will rendezvous with the promised
2592 // stream, but pending secondary validation.
2593 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2594 headers_, &response_, callback_.callback()));
2595
2596 // Receive the promised response headers.
2597 promised_response_["vary"] = "accept-encoding";
bnc94893a72016-06-30 13:45:252598 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562599 size_t spdy_response_headers_frame_length;
2600 ProcessPacket(InnerConstructResponseHeadersPacket(
2601 1, promise_id_, false, &spdy_response_headers_frame_length));
2602
fdoray92e35a72016-06-10 15:54:552603 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562604
2605 // Rendezvous should have failed due to vary mismatch, so the
2606 // promised stream should have been aborted, and instead we have a
2607 // new, regular client initiated stream.
robpercival214763f2016-07-01 23:27:012608 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562609
2610 // Not a server-initiated stream.
2611 EXPECT_NE(
2612 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2613 ->id(),
2614 promise_id_);
2615
2616 // Instead, a new client-initiated stream.
2617 EXPECT_EQ(
2618 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2619 ->id(),
Nick Harper23290b82019-05-02 00:02:562620 stream_id_ + quic::QuicUtils::StreamIdDelta(version_.transport_version));
ckrasic3865ee0f2016-02-29 22:04:562621
2622 // After rendezvous failure, the push stream has been cancelled.
2623 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
2624
2625 // The rest of the test verifies that the retried as
2626 // client-initiated version of |promised_stream_| works as intended.
2627
2628 // Ack the request.
Renjie90e808e2019-01-24 07:24:042629 ProcessPacket(ConstructServerAckPacket(2, 1, 1, 1));
ckrasic3865ee0f2016-02-29 22:04:562630
Kenichi Ishibashif8634ab2021-03-16 23:41:282631 SetResponse("404", string());
ckrasic3865ee0f2016-02-29 22:04:562632 size_t spdy_response_header_frame_length;
2633 ProcessPacket(InnerConstructResponseHeadersPacket(
Nick Harper23290b82019-05-02 00:02:562634 3,
2635 stream_id_ + quic::QuicUtils::StreamIdDelta(version_.transport_version),
2636 kFin, &spdy_response_header_frame_length));
ckrasic3865ee0f2016-02-29 22:04:562637
fdoray92e35a72016-06-10 15:54:552638 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562639
robpercival214763f2016-07-01 23:27:012640 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2641 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562642 ASSERT_TRUE(response_.headers.get());
2643 EXPECT_EQ(404, response_.headers->response_code());
2644 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
2645 EXPECT_FALSE(response_.response_time.is_null());
2646 EXPECT_FALSE(response_.request_time.is_null());
2647
2648 // There is no body, so this should return immediately.
2649 EXPECT_EQ(
2650 0, promised_stream_->ReadResponseBody(
2651 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2652 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2653
2654 stream_->Close(true);
2655
2656 EXPECT_TRUE(AtEof());
ckrasic3865ee0f2016-02-29 22:04:562657}
2658
maksim.sisov84e20c92016-06-23 08:49:342659TEST_P(QuicHttpStreamTest, DataReadErrorSynchronous) {
2660 SetRequest("POST", "/", DEFAULT_PRIORITY);
2661 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232662 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252663 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232664 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Yixin Wange7ecc472018-03-06 19:00:252665 AddWrite(ConstructRequestAndRstPacket(
Renjie Tangaadb84b2019-08-31 01:00:232666 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2667 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
2668 &spdy_request_headers_frame_length, quic::QUIC_ERROR_PROCESSING_STREAM));
maksim.sisov84e20c92016-06-23 08:49:342669
2670 Initialize();
2671
Jeremy Roman0579ed62017-08-29 15:56:192672 upload_data_stream_ = std::make_unique<ReadErrorUploadDataStream>(
maksim.sisov84e20c92016-06-23 08:49:342673 ReadErrorUploadDataStream::FailureMode::SYNC);
2674 request_.method = "POST";
rchcd379012017-04-12 21:53:322675 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122676 request_.upload_data_stream = upload_data_stream_.get();
maksim.sisov84e20c92016-06-23 08:49:342677 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202678 TestCompletionCallback().callback(), NetLogWithSource()));
maksim.sisov84e20c92016-06-23 08:49:342679
Matt Reichhoff0049a0b72021-10-20 20:44:262680 EXPECT_EQ(OK, stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
2681 net_log_with_source_,
2682 callback_.callback()));
maksim.sisov84e20c92016-06-23 08:49:342683
2684 int result = stream_->SendRequest(headers_, &response_, callback_.callback());
robpercival214763f2016-07-01 23:27:012685 EXPECT_THAT(result, IsError(ERR_FAILED));
maksim.sisov84e20c92016-06-23 08:49:342686
2687 EXPECT_TRUE(AtEof());
2688
2689 // QuicHttpStream::GetTotalSent/ReceivedBytes includes only headers.
2690 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
2691 stream_->GetTotalSentBytes());
2692 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2693}
2694
2695TEST_P(QuicHttpStreamTest, DataReadErrorAsynchronous) {
2696 SetRequest("POST", "/", DEFAULT_PRIORITY);
2697 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232698 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252699 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232700 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:372701 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:232702 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2703 kIncludeVersion, !kFin, DEFAULT_PRIORITY,
2704 &spdy_request_headers_frame_length));
2705 AddWrite(
2706 ConstructClientRstStreamErrorPacket(packet_number++, !kIncludeVersion));
maksim.sisov84e20c92016-06-23 08:49:342707
2708 Initialize();
2709
Jeremy Roman0579ed62017-08-29 15:56:192710 upload_data_stream_ = std::make_unique<ReadErrorUploadDataStream>(
maksim.sisov84e20c92016-06-23 08:49:342711 ReadErrorUploadDataStream::FailureMode::ASYNC);
2712 request_.method = "POST";
rchcd379012017-04-12 21:53:322713 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122714 request_.upload_data_stream = upload_data_stream_.get();
maksim.sisov84e20c92016-06-23 08:49:342715 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202716 TestCompletionCallback().callback(), NetLogWithSource()));
maksim.sisov84e20c92016-06-23 08:49:342717
Matt Reichhoff0049a0b72021-10-20 20:44:262718 EXPECT_EQ(OK, stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
2719 net_log_with_source_,
2720 callback_.callback()));
maksim.sisov84e20c92016-06-23 08:49:342721
2722 int result = stream_->SendRequest(headers_, &response_, callback_.callback());
2723
Renjie90e808e2019-01-24 07:24:042724 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
Kenichi Ishibashif8634ab2021-03-16 23:41:282725 SetResponse("200", string());
maksim.sisov84e20c92016-06-23 08:49:342726
robpercival214763f2016-07-01 23:27:012727 EXPECT_THAT(result, IsError(ERR_IO_PENDING));
2728 EXPECT_THAT(callback_.GetResult(result), IsError(ERR_FAILED));
maksim.sisov84e20c92016-06-23 08:49:342729
2730 EXPECT_TRUE(AtEof());
2731
2732 // QuicHttpStream::GetTotalSent/ReceivedBytes includes only headers.
2733 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
2734 stream_->GetTotalSentBytes());
2735 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2736}
2737
Bence Béky97ec688c2021-03-16 13:48:502738TEST_P(QuicHttpStreamTest, GetAcceptChViaAlps) {
2739 AddWrite(ConstructInitialSettingsPacket());
2740 Initialize();
2741
2742 if (!VersionUsesHttp3(version_.transport_version)) {
2743 // ALPS is only implemented for HTTP/3.
2744 return;
2745 }
2746
2747 base::HistogramTester histogram_tester;
2748
2749 session_->OnAcceptChFrameReceivedViaAlps(
Bence Béky41a34f02021-05-07 00:27:482750 {{{"https://www.example.org", "Sec-CH-UA-Platform"}}});
Bence Béky97ec688c2021-03-16 13:48:502751
2752 request_.method = "GET";
2753 request_.url = GURL("https://www.example.org/foo");
2754
Matt Reichhoff0049a0b72021-10-20 20:44:262755 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
2756 net_log_with_source_,
2757 callback_.callback()));
Bence Béky41a34f02021-05-07 00:27:482758 EXPECT_EQ("Sec-CH-UA-Platform", stream_->GetAcceptChViaAlps());
Bence Béky97ec688c2021-03-16 13:48:502759 EXPECT_TRUE(AtEof());
2760
2761 histogram_tester.ExpectBucketCount(
2762 "Net.QuicSession.AcceptChFrameReceivedViaAlps", 1, 1);
2763 histogram_tester.ExpectTotalCount(
2764 "Net.QuicSession.AcceptChFrameReceivedViaAlps", 1);
2765 histogram_tester.ExpectBucketCount("Net.QuicSession.AcceptChForOrigin", 1, 1);
2766 histogram_tester.ExpectTotalCount("Net.QuicSession.AcceptChForOrigin", 1);
2767}
2768
[email protected]f702d572012-12-04 15:56:202769} // namespace test
[email protected]f702d572012-12-04 15:56:202770} // namespace net