blob: 57e0289e13e418815236a7889a0c1d41f73f3848 [file] [log] [blame]
Avi Drissman64595482022-09-14 20:52:291// Copyright 2012 The Chromium Authors
[email protected]f702d572012-12-04 15:56:202// 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
Avi Drissman41c4a412023-01-11 22:45:3712#include "base/functional/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"
Sean Maher5b9af51f2022-11-21 15:32:4718#include "base/task/single_thread_task_runner.h"
Bence Béky97ec688c2021-03-16 13:48:5019#include "base/test/metrics/histogram_tester.h"
Patrick Meenanf741c6082023-01-03 18:06:4320#include "base/test/scoped_feature_list.h"
Zhongyi Shic16b4102019-02-12 00:37:4021#include "base/time/default_tick_clock.h"
xunjieli84adaab2016-09-20 01:12:2822#include "base/time/time.h"
mmenkecbc2b712014-10-09 20:29:0723#include "net/base/chunked_upload_data_stream.h"
24#include "net/base/elements_upload_data_stream.h"
Patrick Meenanf741c6082023-01-03 18:06:4325#include "net/base/features.h"
David Benjamin0288768a2019-07-22 15:00:2626#include "net/base/load_flags.h"
xunjieli84adaab2016-09-20 01:12:2827#include "net/base/load_timing_info.h"
28#include "net/base/load_timing_info_test_util.h"
[email protected]f702d572012-12-04 15:56:2029#include "net/base/net_errors.h"
30#include "net/base/test_completion_callback.h"
[email protected]b2d26cfd2012-12-11 10:36:0631#include "net/base/upload_bytes_element_reader.h"
Ben Schwartz3ff4dc1e62021-04-27 21:15:2332#include "net/dns/public/secure_dns_policy.h"
[email protected]f702d572012-12-04 15:56:2033#include "net/http/http_response_headers.h"
[email protected]5db452202014-08-19 05:22:1534#include "net/http/transport_security_state.h"
Matt Reichhoff0049a0b72021-10-20 20:44:2635#include "net/log/net_log.h"
mikecirone8b85c432016-09-08 19:11:0036#include "net/log/net_log_event_type.h"
xunjieli5fafe142016-03-23 23:32:5437#include "net/log/test_net_log.h"
38#include "net/log/test_net_log_util.h"
Victor Vasiliev4f6fb892019-05-31 16:58:3139#include "net/quic/address_utils.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0840#include "net/quic/crypto/proof_verifier_chromium.h"
41#include "net/quic/mock_crypto_client_stream_factory.h"
42#include "net/quic/quic_chromium_alarm_factory.h"
43#include "net/quic/quic_chromium_connection_helper.h"
44#include "net/quic/quic_chromium_packet_reader.h"
45#include "net/quic/quic_chromium_packet_writer.h"
Matt Menkefca05b62019-09-20 23:15:5646#include "net/quic/quic_crypto_client_config_handle.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0847#include "net/quic/quic_http_utils.h"
48#include "net/quic/quic_server_info.h"
49#include "net/quic/quic_stream_factory.h"
50#include "net/quic/quic_test_packet_maker.h"
Ryan Hamilton0d65a8c2019-06-07 00:46:0251#include "net/quic/quic_test_packet_printer.h"
Matt Menkefca05b62019-09-20 23:15:5652#include "net/quic/test_quic_crypto_client_config_handle.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0853#include "net/quic/test_task_runner.h"
tbansalca83c002016-04-28 20:56:2854#include "net/socket/socket_performance_watcher.h"
[email protected]f702d572012-12-04 15:56:2055#include "net/socket/socket_test_util.h"
Bence Béky94658bf2018-05-11 19:22:5856#include "net/spdy/spdy_http_utils.h"
rch03b7a202016-02-05 00:54:2057#include "net/test/cert_test_util.h"
robpercival214763f2016-07-01 23:27:0158#include "net/test/gtest_util.h"
rsleevia69c79a2016-06-22 03:28:4359#include "net/test/test_data_directory.h"
Gabriel Charettec7108742019-08-23 03:31:4060#include "net/test/test_with_task_environment.h"
Ryan Hamiltonea4fa192022-04-12 18:30:4961#include "net/third_party/quiche/src/quiche/quic/core/congestion_control/send_algorithm_interface.h"
62#include "net/third_party/quiche/src/quiche/quic/core/crypto/crypto_protocol.h"
63#include "net/third_party/quiche/src/quiche/quic/core/crypto/quic_decrypter.h"
64#include "net/third_party/quiche/src/quiche/quic/core/crypto/quic_encrypter.h"
65#include "net/third_party/quiche/src/quiche/quic/core/http/spdy_server_push_utils.h"
66#include "net/third_party/quiche/src/quiche/quic/core/quic_connection.h"
67#include "net/third_party/quiche/src/quiche/quic/core/quic_utils.h"
68#include "net/third_party/quiche/src/quiche/quic/core/quic_write_blocked_list.h"
69#include "net/third_party/quiche/src/quiche/quic/core/tls_client_handshaker.h"
70#include "net/third_party/quiche/src/quiche/quic/platform/api/quic_flags.h"
71#include "net/third_party/quiche/src/quiche/quic/test_tools/crypto_test_utils.h"
72#include "net/third_party/quiche/src/quiche/quic/test_tools/mock_clock.h"
Nidhi Jaju7135c5e2022-09-03 04:39:5773#include "net/third_party/quiche/src/quiche/quic/test_tools/mock_connection_id_generator.h"
Ryan Hamiltonea4fa192022-04-12 18:30:4974#include "net/third_party/quiche/src/quiche/quic/test_tools/mock_random.h"
75#include "net/third_party/quiche/src/quiche/quic/test_tools/qpack/qpack_test_utils.h"
76#include "net/third_party/quiche/src/quiche/quic/test_tools/quic_connection_peer.h"
77#include "net/third_party/quiche/src/quiche/quic/test_tools/quic_spdy_session_peer.h"
78#include "net/third_party/quiche/src/quiche/quic/test_tools/quic_test_utils.h"
79#include "net/third_party/quiche/src/quiche/spdy/core/spdy_frame_builder.h"
80#include "net/third_party/quiche/src/quiche/spdy/core/spdy_framer.h"
81#include "net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.h"
Ramin Halavati683bcaa92018-02-14 08:42:3982#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
[email protected]f702d572012-12-04 15:56:2083#include "testing/gmock/include/gmock/gmock.h"
84#include "testing/gtest/include/gtest/gtest.h"
Dan McArdle68a5f622021-07-09 20:56:5385#include "url/scheme_host_port.h"
86#include "url/url_constants.h"
[email protected]f702d572012-12-04 15:56:2087
bnc614a92d32016-04-04 13:56:0788using std::string;
[email protected]f702d572012-12-04 15:56:2089using testing::_;
[email protected]06ff5152013-08-29 01:03:0590using testing::AnyNumber;
91using testing::Return;
[email protected]f702d572012-12-04 15:56:2092
Tsuyoshi Horo4f516be2022-06-14 11:53:1393namespace net::test {
[email protected]f702d572012-12-04 15:56:2094namespace {
95
[email protected]16ba7742014-08-22 00:57:2596const char kUploadData[] = "Really nifty data!";
rch9ae5b3b2016-02-11 00:36:2997const char kDefaultServerHostName[] = "www.example.org";
rchcd379012017-04-12 21:53:3298const uint16_t kDefaultServerPort = 443;
[email protected]f702d572012-12-04 15:56:2099
David Schinazi09e9a6012019-10-03 17:37:57100struct TestParams {
101 quic::ParsedQuicVersion version;
102 bool client_headers_include_h2_stream_dependency;
Patrick Meenanf741c6082023-01-03 18:06:43103 bool enable_quic_priority_incremental_support;
David Schinazi09e9a6012019-10-03 17:37:57104};
105
106// Used by ::testing::PrintToStringParamName().
107std::string PrintToString(const TestParams& p) {
Victor Vasiliev62c09dc2020-11-06 18:18:29108 return base::StrCat(
109 {ParsedQuicVersionToString(p.version), "_",
110 (p.client_headers_include_h2_stream_dependency ? "" : "No"),
Patrick Meenanf741c6082023-01-03 18:06:43111 "Dependency", "_",
112 (p.enable_quic_priority_incremental_support ? "" : "No"),
113 "Incremental"});
David Schinazi09e9a6012019-10-03 17:37:57114}
115
116std::vector<TestParams> GetTestParams() {
117 std::vector<TestParams> params;
118 quic::ParsedQuicVersionVector all_supported_versions =
119 quic::AllSupportedVersions();
120 for (const auto& version : all_supported_versions) {
Patrick Meenanf741c6082023-01-03 18:06:43121 params.push_back(TestParams{version, false, false});
122 params.push_back(TestParams{version, false, true});
123 params.push_back(TestParams{version, true, false});
124 params.push_back(TestParams{version, true, true});
David Schinazi09e9a6012019-10-03 17:37:57125 }
126 return params;
127}
128
Bence Békye0d3747d2020-08-28 23:16:40129// Returns true if |params| is a dict, has an entry with key "headers", that
130// entry is a list of strings, which when interpreted as colon-separated
131// key-value pairs has exactly one entry with |key| and that entry has value
132// |expected_value|.
133bool CheckHeader(const base::Value& params,
134 base::StringPiece key,
135 base::StringPiece expected_value) {
136 if (!params.is_dict()) {
137 return false;
138 }
Matt Menke355d7b1e2022-05-27 23:19:53139 const base::Value::List* headers = params.GetDict().FindList("headers");
Bence Békye0d3747d2020-08-28 23:16:40140 if (!headers) {
141 return false;
142 }
143
144 std::string header_prefix = base::StrCat({key, ": "});
145 std::string expected_header = base::StrCat({header_prefix, expected_value});
146
Bence Békye0d3747d2020-08-28 23:16:40147 bool header_found = false;
Matt Menke355d7b1e2022-05-27 23:19:53148 for (const auto& header_value : *headers) {
149 const std::string* header = header_value.GetIfString();
150 if (!header) {
Bence Békye0d3747d2020-08-28 23:16:40151 return false;
152 }
Matt Menke355d7b1e2022-05-27 23:19:53153 if (base::StartsWith(*header, header_prefix)) {
Bence Békye0d3747d2020-08-28 23:16:40154 if (header_found) {
155 return false;
156 }
Matt Menke355d7b1e2022-05-27 23:19:53157 if (*header != expected_header) {
Bence Békye0d3747d2020-08-28 23:16:40158 return false;
159 }
160 header_found = true;
161 }
Bence Békye0d3747d2020-08-28 23:16:40162 }
163 return header_found;
164}
165
Ryan Hamilton8d9ee76e2018-05-29 23:52:52166class TestQuicConnection : public quic::QuicConnection {
[email protected]f702d572012-12-04 15:56:20167 public:
Ryan Hamilton8d9ee76e2018-05-29 23:52:52168 TestQuicConnection(const quic::ParsedQuicVersionVector& versions,
169 quic::QuicConnectionId connection_id,
[email protected]f702d572012-12-04 15:56:20170 IPEndPoint address,
rch12fef552016-01-15 16:26:31171 QuicChromiumConnectionHelper* helper,
rch16c74d1d2016-04-22 06:14:07172 QuicChromiumAlarmFactory* alarm_factory,
Nidhi Jaju7135c5e2022-09-03 04:39:57173 quic::QuicPacketWriter* writer,
174 quic::ConnectionIdGeneratorInterface& generator)
Victor Vasiliev4f6fb892019-05-31 16:58:31175 : quic::QuicConnection(connection_id,
Nick Harperd049f192020-10-02 02:56:10176 quic::QuicSocketAddress(),
Victor Vasiliev4f6fb892019-05-31 16:58:31177 ToQuicSocketAddress(address),
178 helper,
179 alarm_factory,
180 writer,
181 true /* owns_writer */,
182 quic::Perspective::IS_CLIENT,
Nidhi Jaju7135c5e2022-09-03 04:39:57183 versions,
184 generator) {}
[email protected]f702d572012-12-04 15:56:20185
Ryan Hamilton8d9ee76e2018-05-29 23:52:52186 void SetSendAlgorithm(quic::SendAlgorithmInterface* send_algorithm) {
187 quic::test::QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
[email protected]f702d572012-12-04 15:56:20188 }
189};
190
maksim.sisov84e20c92016-06-23 08:49:34191// UploadDataStream that always returns errors on data read.
192class ReadErrorUploadDataStream : public UploadDataStream {
193 public:
194 enum class FailureMode { SYNC, ASYNC };
195
196 explicit ReadErrorUploadDataStream(FailureMode mode)
Jeremy Romand54000b22019-07-08 18:40:16197 : UploadDataStream(true, 0), async_(mode) {}
Peter Boström293b1342021-09-22 17:31:43198
199 ReadErrorUploadDataStream(const ReadErrorUploadDataStream&) = delete;
200 ReadErrorUploadDataStream& operator=(const ReadErrorUploadDataStream&) =
201 delete;
202
Tsuyoshi Horo07c3f0e2022-06-16 07:30:47203 ~ReadErrorUploadDataStream() override = default;
maksim.sisov84e20c92016-06-23 08:49:34204
205 private:
206 void CompleteRead() { UploadDataStream::OnReadCompleted(ERR_FAILED); }
207
208 // UploadDataStream implementation:
tfarina42834112016-09-22 13:38:20209 int InitInternal(const NetLogWithSource& net_log) override { return OK; }
maksim.sisov84e20c92016-06-23 08:49:34210
211 int ReadInternal(IOBuffer* buf, int buf_len) override {
212 if (async_ == FailureMode::ASYNC) {
Sean Maher5b9af51f2022-11-21 15:32:47213 base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
kylecharf4fe5172019-02-15 18:53:49214 FROM_HERE, base::BindOnce(&ReadErrorUploadDataStream::CompleteRead,
215 weak_factory_.GetWeakPtr()));
maksim.sisov84e20c92016-06-23 08:49:34216 return ERR_IO_PENDING;
217 }
218 return ERR_FAILED;
219 }
220
221 void ResetInternal() override {}
222
223 const FailureMode async_;
224
Jeremy Romand54000b22019-07-08 18:40:16225 base::WeakPtrFactory<ReadErrorUploadDataStream> weak_factory_{this};
maksim.sisov84e20c92016-06-23 08:49:34226};
227
Bence Béky8ddc2492018-06-13 01:02:04228// A helper class that will delete |stream| when the callback is invoked.
xunjieli8dff50b2016-07-22 14:19:06229class DeleteStreamCallback : public TestCompletionCallbackBase {
230 public:
Bence Béky8ddc2492018-06-13 01:02:04231 explicit DeleteStreamCallback(std::unique_ptr<QuicHttpStream> stream)
232 : stream_(std::move(stream)) {}
xunjieli8dff50b2016-07-22 14:19:06233
Bence Béky8ddc2492018-06-13 01:02:04234 CompletionOnceCallback callback() {
235 return base::BindOnce(&DeleteStreamCallback::DeleteStream,
236 base::Unretained(this));
237 }
xunjieli8dff50b2016-07-22 14:19:06238
239 private:
240 void DeleteStream(int result) {
241 stream_.reset();
242 SetResult(result);
243 }
244
245 std::unique_ptr<QuicHttpStream> stream_;
xunjieli8dff50b2016-07-22 14:19:06246};
247
[email protected]f702d572012-12-04 15:56:20248} // namespace
249
[email protected]24e5bc52013-09-18 15:36:58250class QuicHttpStreamPeer {
251 public:
rch08e198572017-05-09 16:56:55252 static QuicChromiumClientStream::Handle* GetQuicChromiumClientStream(
[email protected]24e5bc52013-09-18 15:36:58253 QuicHttpStream* stream) {
rch08e198572017-05-09 16:56:55254 return stream->stream_.get();
[email protected]24e5bc52013-09-18 15:36:58255 }
256};
257
David Schinazi09e9a6012019-10-03 17:37:57258class QuicHttpStreamTest : public ::testing::TestWithParam<TestParams>,
Gabriel Charette694c3c332019-08-19 14:53:05259 public WithTaskEnvironment {
rchfb47f712017-05-21 03:24:00260 public:
261 void CloseStream(QuicHttpStream* stream, int /*rv*/) { stream->Close(false); }
262
[email protected]f702d572012-12-04 15:56:20263 protected:
[email protected]1e960032013-12-20 19:00:20264 static const bool kFin = true;
265 static const bool kIncludeVersion = true;
[email protected]1e960032013-12-20 19:00:20266
[email protected]f702d572012-12-04 15:56:20267 // Holds a packet to be written to the wire, and the IO mode that should
268 // be used by the mock socket when performing the write.
269 struct PacketToWrite {
Ryan Hamilton8d9ee76e2018-05-29 23:52:52270 PacketToWrite(IoMode mode, quic::QuicReceivedPacket* packet)
rjshaded5ced072015-12-18 19:26:02271 : mode(mode), packet(packet) {}
rtenneti15656ae2016-01-23 03:05:03272 PacketToWrite(IoMode mode, int rv) : mode(mode), packet(nullptr), rv(rv) {}
[email protected]f702d572012-12-04 15:56:20273 IoMode mode;
Keishi Hattoric1b00232022-11-22 09:04:26274 raw_ptr<quic::QuicReceivedPacket> packet;
rtenneti15656ae2016-01-23 03:05:03275 int rv;
[email protected]f702d572012-12-04 15:56:20276 };
277
278 QuicHttpStreamTest()
David Schinazi09e9a6012019-10-03 17:37:57279 : version_(GetParam().version),
280 client_headers_include_h2_stream_dependency_(
281 GetParam().client_headers_include_h2_stream_dependency),
Nick Harpera598fc5f2019-06-21 08:46:50282 crypto_config_(
283 quic::test::crypto_test_utils::ProofVerifierForTesting()),
Victor Costan9c7302b2018-08-27 16:39:44284 read_buffer_(base::MakeRefCounted<IOBufferWithSize>(4096)),
Fan Yang32c5a112018-12-10 20:06:33285 promise_id_(GetNthServerInitiatedUnidirectionalStreamId(0)),
286 stream_id_(GetNthClientInitiatedBidirectionalStreamId(0)),
David Schinazic8281052019-01-24 06:14:17287 connection_id_(quic::test::TestConnectionId(2)),
Yixin Wang079ad542018-01-11 04:06:05288 client_maker_(version_,
alyssar2adf3ac2016-05-03 17:12:58289 connection_id_,
290 &clock_,
291 kDefaultServerHostName,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52292 quic::Perspective::IS_CLIENT,
Patrick Meenanf741c6082023-01-03 18:06:43293 client_headers_include_h2_stream_dependency_,
294 true),
Yixin Wang079ad542018-01-11 04:06:05295 server_maker_(version_,
zhongyi5dbfdd42017-06-20 05:22:15296 connection_id_,
alyssar2adf3ac2016-05-03 17:12:58297 &clock_,
298 kDefaultServerHostName,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52299 quic::Perspective::IS_SERVER,
Yixin Wang079ad542018-01-11 04:06:05300 false),
Ryan Hamilton0d65a8c2019-06-07 00:46:02301 printer_(version_) {
Patrick Meenanf741c6082023-01-03 18:06:43302 scoped_feature_list_.InitWithFeatureState(
303 features::kPriorityIncremental,
304 GetParam().enable_quic_priority_incremental_support);
Renjie Tang98b4d512020-02-08 01:24:19305 FLAGS_quic_enable_http3_grease_randomness = false;
Zhongyi Shi49f8ad2fd2019-12-13 01:20:31306 quic::QuicEnableVersion(version_);
martijn21968ea2016-02-24 18:46:20307 IPAddress ip(192, 0, 2, 33);
[email protected]f702d572012-12-04 15:56:20308 peer_addr_ = IPEndPoint(ip, 443);
309 self_addr_ = IPEndPoint(ip, 8435);
Ryan Hamilton8d9ee76e2018-05-29 23:52:52310 clock_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(20));
Ramin Halavati683bcaa92018-02-14 08:42:39311 request_.traffic_annotation =
312 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f702d572012-12-04 15:56:20313 }
314
Tsuyoshi Horobfd85672022-06-17 01:37:38315 ~QuicHttpStreamTest() override {
Renjieba55fae2018-09-20 03:05:16316 session_->CloseSessionOnError(ERR_ABORTED, quic::QUIC_INTERNAL_ERROR,
317 quic::ConnectionCloseBehavior::SILENT_CLOSE);
Tsuyoshi Horo17ef47d02022-06-30 10:58:27318 for (auto& write : writes_) {
319 delete write.packet;
[email protected]f702d572012-12-04 15:56:20320 }
321 }
322
323 // Adds a packet to the list of expected writes.
Ryan Hamilton8d9ee76e2018-05-29 23:52:52324 void AddWrite(std::unique_ptr<quic::QuicReceivedPacket> packet) {
Tsuyoshi Horoebc507882022-06-30 11:16:45325 writes_.emplace_back(SYNCHRONOUS, packet.release());
[email protected]f702d572012-12-04 15:56:20326 }
327
Tsuyoshi Horoebc507882022-06-30 11:16:45328 void AddWrite(IoMode mode, int rv) { writes_.emplace_back(mode, rv); }
rtenneti15656ae2016-01-23 03:05:03329
[email protected]f702d572012-12-04 15:56:20330 // Returns the packet to be written at position |pos|.
Ryan Hamilton8d9ee76e2018-05-29 23:52:52331 quic::QuicReceivedPacket* GetWrite(size_t pos) { return writes_[pos].packet; }
[email protected]f702d572012-12-04 15:56:20332
333 bool AtEof() {
rch37de576c2015-05-17 20:28:17334 return socket_data_->AllReadDataConsumed() &&
335 socket_data_->AllWriteDataConsumed();
[email protected]f702d572012-12-04 15:56:20336 }
337
Ryan Hamilton8d9ee76e2018-05-29 23:52:52338 void ProcessPacket(std::unique_ptr<quic::QuicReceivedPacket> packet) {
Victor Vasiliev4f6fb892019-05-31 16:58:31339 connection_->ProcessUdpPacket(ToQuicSocketAddress(self_addr_),
340 ToQuicSocketAddress(peer_addr_), *packet);
[email protected]f702d572012-12-04 15:56:20341 }
342
343 // Configures the test fixture to use the list of expected writes.
344 void Initialize() {
Renjie Tang6ff9a9b2021-02-03 22:11:09345 mock_writes_ = std::make_unique<MockWrite[]>(writes_.size());
[email protected]f702d572012-12-04 15:56:20346 for (size_t i = 0; i < writes_.size(); i++) {
rtenneti15656ae2016-01-23 03:05:03347 if (writes_[i].packet == nullptr) {
348 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].rv, i);
349 } else {
350 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].packet->data(),
351 writes_[i].packet->length());
352 }
bnc614a92d32016-04-04 13:56:07353 }
[email protected]f702d572012-12-04 15:56:20354
Renjie Tang6ff9a9b2021-02-03 22:11:09355 socket_data_ = std::make_unique<StaticSocketDataProvider>(
Ryan Sleevib8d7ea02018-05-07 20:01:01356 base::span<MockRead>(),
Renjie Tang6ff9a9b2021-02-03 22:11:09357 base::make_span(mock_writes_.get(), writes_.size()));
Ryan Hamilton0d65a8c2019-06-07 00:46:02358 socket_data_->set_printer(&printer_);
[email protected]f702d572012-12-04 15:56:20359
Tsuyoshi Horof8861cb2022-07-05 23:50:20360 auto socket = std::make_unique<MockUDPClientSocket>(socket_data_.get(),
361 NetLog::Get());
[email protected]e13201d82012-12-12 05:00:32362 socket->Connect(peer_addr_);
Tsuyoshi Horo2c0a5042022-07-06 05:53:07363 runner_ = base::MakeRefCounted<TestTaskRunner>(&clock_);
Ryan Hamilton8d9ee76e2018-05-29 23:52:52364 send_algorithm_ = new quic::test::MockSendAlgorithm();
rch7dd15702015-07-01 18:57:57365 EXPECT_CALL(*send_algorithm_, InRecovery()).WillRepeatedly(Return(false));
366 EXPECT_CALL(*send_algorithm_, InSlowStart()).WillRepeatedly(Return(false));
Victor Vasiliev7da08172019-10-14 06:04:25367 if (VersionUsesHttp3(version_.transport_version)) {
Renjie Tangaadb84b2019-08-31 01:00:23368 EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
369 .Times(testing::AtLeast(1));
370 }
Ryan Hamiltona1d1f4a2019-06-26 14:43:04371 EXPECT_CALL(*send_algorithm_, OnCongestionEvent(_, _, _, _, _))
372 .Times(AnyNumber());
rtenneti44f4a2e2015-08-07 14:00:07373 EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
Zhongyi Shica576df2019-04-12 17:43:40374 .WillRepeatedly(Return(quic::kMaxOutgoingPacketSize));
jokulik0e0a00c32016-06-13 21:51:58375 EXPECT_CALL(*send_algorithm_, PacingRate(_))
Ryan Hamilton8d9ee76e2018-05-29 23:52:52376 .WillRepeatedly(Return(quic::QuicBandwidth::Zero()));
Michael Warres74ee3ce2017-10-09 15:26:37377 EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true));
rtenneti44f4a2e2015-08-07 14:00:07378 EXPECT_CALL(*send_algorithm_, BandwidthEstimate())
Ryan Hamilton8d9ee76e2018-05-29 23:52:52379 .WillRepeatedly(Return(quic::QuicBandwidth::Zero()));
rch1e543ec2015-03-29 07:04:40380 EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(AnyNumber());
rch08cae032017-03-29 00:59:15381 EXPECT_CALL(*send_algorithm_, OnApplicationLimited(_)).Times(AnyNumber());
rch0d5bcf62017-05-24 22:48:45382 EXPECT_CALL(*send_algorithm_, GetCongestionControlType())
383 .Times(AnyNumber());
Renjie Tang6ff9a9b2021-02-03 22:11:09384 helper_ = std::make_unique<QuicChromiumConnectionHelper>(
385 &clock_, &random_generator_);
386 alarm_factory_ =
387 std::make_unique<QuicChromiumAlarmFactory>(runner_.get(), &clock_);
rch16c74d1d2016-04-22 06:14:07388
Michael Warres74ee3ce2017-10-09 15:26:37389 connection_ = new TestQuicConnection(
Nick Harper23290b82019-05-02 00:02:56390 quic::test::SupportedVersions(version_), connection_id_, peer_addr_,
391 helper_.get(), alarm_factory_.get(),
Sean Maher5b9af51f2022-11-21 15:32:47392 new QuicChromiumPacketWriter(
393 socket.get(),
394 base::SingleThreadTaskRunner::GetCurrentDefault().get()),
Nidhi Jaju7135c5e2022-09-03 04:39:57395 connection_id_generator_);
[email protected]f702d572012-12-04 15:56:20396 connection_->set_visitor(&visitor_);
[email protected]fee17f72013-02-03 07:47:41397 connection_->SetSendAlgorithm(send_algorithm_);
rch03b7a202016-02-05 00:54:20398
399 // Load a certificate that is valid for *.example.org
400 scoped_refptr<X509Certificate> test_cert(
401 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
402 EXPECT_TRUE(test_cert.get());
403
404 verify_details_.cert_verify_result.verified_cert = test_cert;
405 verify_details_.cert_verify_result.is_issued_by_known_root = true;
406 crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details_);
407
xunjieli84adaab2016-09-20 01:12:28408 base::TimeTicks dns_end = base::TimeTicks::Now();
Peter Kastinge5a38ed2021-10-02 03:06:35409 base::TimeTicks dns_start = dns_end - base::Milliseconds(1);
Renjie Tang6ff9a9b2021-02-03 22:11:09410 session_ = std::make_unique<QuicChromiumClientSession>(
xunjielib53b38c2016-03-24 15:54:36411 connection_, std::move(socket),
rtenneti1cd3b162015-09-29 02:58:28412 /*stream_factory=*/nullptr, &crypto_client_stream_factory_, &clock_,
Nick Harper89bc7212018-07-31 19:07:57413 &transport_security_state_, /*ssl_config_service=*/nullptr,
danakjad1777e2016-04-16 00:56:42414 base::WrapUnique(static_cast<QuicServerInfo*>(nullptr)),
Paul Jensen8e3c5d32018-02-19 17:06:33415 QuicSessionKey(kDefaultServerHostName, kDefaultServerPort,
dalyk51ab46b2019-10-15 15:14:34416 PRIVACY_MODE_DISABLED, SocketTag(),
Brianna Goldstein793995c2022-09-27 04:27:37417 NetworkAnonymizationKey(), SecureDnsPolicy::kAllow,
Tsuyoshi Horo7acebce2022-05-12 06:13:23418 /*require_dns_https_alpn=*/false),
Bence Béky1ceba552019-07-19 17:11:05419 /*require_confirmation=*/false,
Bence Béky1ceba552019-07-19 17:11:05420 /*migrate_session_early_v2=*/false,
Zhongyi Shi757fcce2018-06-27 05:41:27421 /*migrate_session_on_network_change_v2=*/false,
Stefano Duo6527ed42022-07-29 09:25:44422 /*default_network=*/handles::kInvalidNetworkHandle,
Zhongyi Shie01f2db2019-02-22 19:53:23423 quic::QuicTime::Delta::FromMilliseconds(
Ryan Sleevi2e8255b2019-07-17 21:02:21424 kDefaultRetransmittableOnWireTimeout.InMilliseconds()),
Zhongyi Shiaf38c4e42019-08-29 22:49:05425 /*migrate_idle_session=*/false, /*allow_port_migration=*/false,
426 kDefaultIdleSessionMigrationPeriod, kMaxTimeOnNonDefaultNetwork,
Zhongyi Shiee760762018-08-01 00:54:29427 kMaxMigrationsToNonDefaultNetworkOnWriteError,
Zhongyi Shi8b1e43f2017-12-13 20:46:30428 kMaxMigrationsToNonDefaultNetworkOnPathDegrading,
Zhongyi Shi5f587cc2017-11-21 23:24:17429 kQuicYieldAfterPacketsRead,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52430 quic::QuicTime::Delta::FromMilliseconds(
431 kQuicYieldAfterDurationMilliseconds),
Yixin Wang079ad542018-01-11 04:06:05432 client_headers_include_h2_stream_dependency_, /*cert_verify_flags=*/0,
Matt Menkefca05b62019-09-20 23:15:56433 quic::test::DefaultQuicConfig(),
434 std::make_unique<TestQuicCryptoClientConfigHandle>(&crypto_config_),
Matt Menked804aaf2020-07-21 21:25:48435 "CONNECTION_UNKNOWN", dns_start, dns_end,
436 std::make_unique<quic::QuicClientPushPromiseIndex>(), nullptr,
Zhongyi Shic16b4102019-02-12 00:37:40437 base::DefaultTickClock::GetInstance(),
Sean Maher5b9af51f2022-11-21 15:32:47438 base::SingleThreadTaskRunner::GetCurrentDefault().get(),
Matt Reichhoff0049a0b72021-10-20 20:44:26439 /*socket_performance_watcher=*/nullptr, NetLog::Get());
rtennetid39bd762015-06-12 01:05:52440 session_->Initialize();
rchf0b18c8a2017-05-05 19:31:57441
Bence Béky6e243aa2019-12-13 19:01:07442 // Blackhole QPACK decoder stream instead of constructing mock writes.
443 if (VersionUsesHttp3(version_.transport_version)) {
444 session_->qpack_decoder()->set_qpack_stream_sender_delegate(
445 &noop_qpack_stream_sender_delegate_);
446 }
447
448 TestCompletionCallback callback;
rch433bf5f2017-02-14 04:10:47449 session_->CryptoConnect(callback.callback());
Ryan Hamilton6c2a2a82017-12-15 02:06:28450 stream_ = std::make_unique<QuicHttpStream>(
Dan McArdle68a5f622021-07-09 20:56:53451 session_->CreateHandle(
452 url::SchemeHostPort(url::kHttpsScheme, "www.example.org", 443)),
Eric Orthac661912022-01-10 21:44:17453 /*dns_aliases=*/std::set<std::string>());
Ryan Hamilton6c2a2a82017-12-15 02:06:28454 promised_stream_ = std::make_unique<QuicHttpStream>(
Dan McArdle68a5f622021-07-09 20:56:53455 session_->CreateHandle(
456 url::SchemeHostPort(url::kHttpsScheme, "www.example.org", 443)),
Eric Orthac661912022-01-10 21:44:17457 /*dns_aliases=*/std::set<std::string>());
ckrasic3865ee0f2016-02-29 22:04:56458 push_promise_[":path"] = "/bar";
459 push_promise_[":authority"] = "www.example.org";
460 push_promise_[":version"] = "HTTP/1.1";
461 push_promise_[":method"] = "GET";
462 push_promise_[":scheme"] = "https";
463
Kenichi Ishibashif8634ab2021-03-16 23:41:28464 promised_response_[":status"] = "200";
ckrasic3865ee0f2016-02-29 22:04:56465 promised_response_[":version"] = "HTTP/1.1";
466 promised_response_["content-type"] = "text/plain";
467
David Schinazi3f7465c2019-07-12 01:57:05468 promise_url_ =
469 quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
[email protected]6cca996b2013-01-25 07:43:36470 }
471
bnc614a92d32016-04-04 13:56:07472 void SetRequest(const string& method,
473 const string& path,
[email protected]1e960032013-12-20 19:00:20474 RequestPriority priority) {
rchcd379012017-04-12 21:53:32475 request_headers_ = client_maker_.GetRequestHeaders(method, "https", path);
[email protected]6cca996b2013-01-25 07:43:36476 }
477
bnc614a92d32016-04-04 13:56:07478 void SetResponse(const string& status, const string& body) {
alyssar2adf3ac2016-05-03 17:12:58479 response_headers_ = server_maker_.GetResponseHeaders(status);
[email protected]92bf17c2014-03-03 21:14:03480 response_data_ = body;
[email protected]6cca996b2013-01-25 07:43:36481 }
[email protected]f702d572012-12-04 15:56:20482
Ryan Hamilton8d9ee76e2018-05-29 23:52:52483 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientDataPacket(
Fan Yangac867502019-01-28 21:10:23484 uint64_t packet_number,
[email protected]e8ff26842013-03-22 21:02:05485 bool should_include_version,
[email protected]f702d572012-12-04 15:56:20486 bool fin,
Victor Vasiliev47ecb6a2020-10-14 17:22:10487 absl::string_view data) {
Ryan Hamilton7505eb92019-06-08 00:22:17488 return client_maker_.MakeDataPacket(packet_number, stream_id_,
489 should_include_version, fin, data);
alyssar2adf3ac2016-05-03 17:12:58490 }
491
Ryan Hamilton8d9ee76e2018-05-29 23:52:52492 std::unique_ptr<quic::QuicReceivedPacket> ConstructServerDataPacket(
Fan Yangac867502019-01-28 21:10:23493 uint64_t packet_number,
alyssar2adf3ac2016-05-03 17:12:58494 bool should_include_version,
495 bool fin,
Victor Vasiliev47ecb6a2020-10-14 17:22:10496 absl::string_view data) {
Ryan Hamilton7505eb92019-06-08 00:22:17497 return server_maker_.MakeDataPacket(packet_number, stream_id_,
498 should_include_version, fin, data);
ckrasic3865ee0f2016-02-29 22:04:56499 }
500
Ryan Hamilton8d9ee76e2018-05-29 23:52:52501 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23502 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52503 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56504 bool should_include_version,
505 bool fin,
506 RequestPriority request_priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02507 size_t* spdy_headers_frame_length) {
Yixin Wang7a3f1b8d2018-01-17 21:40:48508 return InnerConstructRequestHeadersPacket(
509 packet_number, stream_id, should_include_version, fin, request_priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02510 0, spdy_headers_frame_length);
Yixin Wang7a3f1b8d2018-01-17 21:40:48511 }
512
Ryan Hamilton8d9ee76e2018-05-29 23:52:52513 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23514 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52515 quic::QuicStreamId stream_id,
Yixin Wang7a3f1b8d2018-01-17 21:40:48516 bool should_include_version,
517 bool fin,
518 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52519 quic::QuicStreamId parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02520 size_t* spdy_headers_frame_length) {
Ryan Hamilton0239aac2018-05-19 00:03:13521 spdy::SpdyPriority priority =
ckrasic3865ee0f2016-02-29 22:04:56522 ConvertRequestPriorityToQuicPriority(request_priority);
alyssar2adf3ac2016-05-03 17:12:58523 return client_maker_.MakeRequestHeadersPacket(
ckrasic3865ee0f2016-02-29 22:04:56524 packet_number, stream_id, should_include_version, fin, priority,
Yixin Wang7a3f1b8d2018-01-17 21:40:48525 std::move(request_headers_), parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02526 spdy_headers_frame_length);
[email protected]f702d572012-12-04 15:56:20527 }
528
Ryan Hamilton8d9ee76e2018-05-29 23:52:52529 std::unique_ptr<quic::QuicReceivedPacket>
Yixin Wange7ecc472018-03-06 19:00:25530 ConstructRequestHeadersAndDataFramesPacket(
Fan Yangac867502019-01-28 21:10:23531 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52532 quic::QuicStreamId stream_id,
Yixin Wange7ecc472018-03-06 19:00:25533 bool should_include_version,
534 bool fin,
535 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52536 quic::QuicStreamId parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25537 size_t* spdy_headers_frame_length,
538 const std::vector<std::string>& data_writes) {
Ryan Hamilton0239aac2018-05-19 00:03:13539 spdy::SpdyPriority priority =
Yixin Wange7ecc472018-03-06 19:00:25540 ConvertRequestPriorityToQuicPriority(request_priority);
541 return client_maker_.MakeRequestHeadersAndMultipleDataFramesPacket(
542 packet_number, stream_id, should_include_version, fin, priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02543 std::move(request_headers_), parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25544 spdy_headers_frame_length, data_writes);
545 }
546
Ryan Hamilton8d9ee76e2018-05-29 23:52:52547 std::unique_ptr<quic::QuicReceivedPacket> ConstructRequestAndRstPacket(
Fan Yangac867502019-01-28 21:10:23548 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52549 quic::QuicStreamId stream_id,
Yixin Wange7ecc472018-03-06 19:00:25550 bool should_include_version,
551 bool fin,
552 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52553 quic::QuicStreamId parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25554 size_t* spdy_headers_frame_length,
Ryan Hamiltonb5d4c5a2019-06-21 22:08:41555 quic::QuicRstStreamErrorCode error_code) {
Ryan Hamilton0239aac2018-05-19 00:03:13556 spdy::SpdyPriority priority =
Yixin Wange7ecc472018-03-06 19:00:25557 ConvertRequestPriorityToQuicPriority(request_priority);
558 return client_maker_.MakeRequestHeadersAndRstPacket(
559 packet_number, stream_id, should_include_version, fin, priority,
560 std::move(request_headers_), parent_stream_id,
Ryan Hamiltonb5d4c5a2019-06-21 22:08:41561 spdy_headers_frame_length, error_code);
Yixin Wange7ecc472018-03-06 19:00:25562 }
563
Ryan Hamilton8d9ee76e2018-05-29 23:52:52564 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructResponseHeadersPacket(
Fan Yangac867502019-01-28 21:10:23565 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52566 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56567 bool fin,
568 size_t* spdy_headers_frame_length) {
alyssar2adf3ac2016-05-03 17:12:58569 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26570 packet_number, stream_id, !kIncludeVersion, fin,
Ryan Hamilton0d65a8c2019-06-07 00:46:02571 std::move(response_headers_), 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> ConstructResponseHeadersPacket(
Fan Yangac867502019-01-28 21:10:23575 uint64_t packet_number,
sclittlec4dc1a32015-09-24 00:15:45576 bool fin,
577 size_t* spdy_headers_frame_length) {
ckrasic3865ee0f2016-02-29 22:04:56578 return InnerConstructResponseHeadersPacket(packet_number, stream_id_, fin,
579 spdy_headers_frame_length);
[email protected]1e960032013-12-20 19:00:20580 }
581
Ryan Hamilton8d9ee76e2018-05-29 23:52:52582 std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseTrailersPacket(
Fan Yangac867502019-01-28 21:10:23583 uint64_t packet_number,
xunjieli34291fe12016-03-02 13:58:38584 bool fin,
Bence Béky4c325e52020-10-22 20:48:01585 spdy::Http2HeaderBlock trailers,
Ryan Hamilton0d65a8c2019-06-07 00:46:02586 size_t* spdy_headers_frame_length) {
alyssar2adf3ac2016-05-03 17:12:58587 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26588 packet_number, stream_id_, !kIncludeVersion, fin, std::move(trailers),
Ryan Hamilton0d65a8c2019-06-07 00:46:02589 spdy_headers_frame_length);
xunjieli34291fe12016-03-02 13:58:38590 }
591
Ryan Hamilton8d9ee76e2018-05-29 23:52:52592 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientRstStreamErrorPacket(
Fan Yangac867502019-01-28 21:10:23593 uint64_t packet_number,
maksim.sisov84e20c92016-06-23 08:49:34594 bool include_version) {
595 return client_maker_.MakeRstPacket(packet_number, include_version,
596 stream_id_,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52597 quic::QUIC_ERROR_PROCESSING_STREAM);
maksim.sisov84e20c92016-06-23 08:49:34598 }
599
Ryan Hamilton8d9ee76e2018-05-29 23:52:52600 std::unique_ptr<quic::QuicReceivedPacket> ConstructAckAndRstStreamPacket(
Fan Yangac867502019-01-28 21:10:23601 uint64_t packet_number) {
Renjie Tangcd594f32020-07-11 20:18:34602 return client_maker_.MakeAckAndRstPacket(packet_number, !kIncludeVersion,
603 stream_id_,
604 quic::QUIC_STREAM_CANCELLED, 2, 1);
[email protected]c5e1aca2014-01-30 04:03:04605 }
606
Ryan Hamilton8d9ee76e2018-05-29 23:52:52607 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientAckPacket(
Fan Yangac867502019-01-28 21:10:23608 uint64_t packet_number,
609 uint64_t largest_received,
Renjie Tangcd594f32020-07-11 20:18:34610 uint64_t smallest_received) {
alyssar2adf3ac2016-05-03 17:12:58611 return client_maker_.MakeAckPacket(packet_number, largest_received,
Renjie Tangcd594f32020-07-11 20:18:34612 smallest_received);
alyssar2adf3ac2016-05-03 17:12:58613 }
614
Ryan Hamilton8d9ee76e2018-05-29 23:52:52615 std::unique_ptr<quic::QuicReceivedPacket> ConstructServerAckPacket(
Fan Yangac867502019-01-28 21:10:23616 uint64_t packet_number,
617 uint64_t largest_received,
618 uint64_t smallest_received,
619 uint64_t least_unacked) {
alyssar2adf3ac2016-05-03 17:12:58620 return server_maker_.MakeAckPacket(packet_number, largest_received,
Bence Béky7a45d4d2020-05-08 01:59:23621 smallest_received, least_unacked);
[email protected]63534512012-12-23 18:49:00622 }
623
Ryan Hamilton0d65a8c2019-06-07 00:46:02624 std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket() {
625 return client_maker_.MakeInitialSettingsPacket(1);
fayang3bcb8b502016-12-07 21:44:37626 }
627
Renjie Tangaadb84b2019-08-31 01:00:23628 std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket(
629 int packet_number) {
630 return client_maker_.MakeInitialSettingsPacket(packet_number);
631 }
632
Victor Vasiliev076657c2019-03-12 02:46:43633 std::string ConstructDataHeader(size_t body_len) {
Nick Harperc6cb7a612020-02-24 20:03:32634 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:41635 return "";
636 }
Victor Vasilievc617d452022-03-07 15:54:25637 quiche::QuicheBuffer buffer = quic::HttpEncoder::SerializeDataFrameHeader(
638 body_len, quiche::SimpleBufferAllocator::Get());
Ian Swett17d4d1c02021-06-08 19:52:41639 return std::string(buffer.data(), buffer.size());
Renjief49758b2019-01-11 23:32:41640 }
641
Ryan Hamilton8d9ee76e2018-05-29 23:52:52642 void ReceivePromise(quic::QuicStreamId id) {
643 auto headers = quic::test::AsHeaderList(push_promise_);
rch08e198572017-05-09 16:56:55644 QuicChromiumClientStream::Handle* stream =
ckrasic3865ee0f2016-02-29 22:04:56645 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
ckrasic32b17dcd2016-10-31 06:15:35646 stream->OnPromiseHeaderList(id, headers.uncompressed_header_bytes(),
647 headers);
ckrasic3865ee0f2016-02-29 22:04:56648 }
649
xunjieli84adaab2016-09-20 01:12:28650 void ExpectLoadTimingValid(const LoadTimingInfo& load_timing_info,
xunjieli100937eb52016-09-15 20:09:37651 bool session_reused) {
652 EXPECT_EQ(session_reused, load_timing_info.socket_reused);
xunjieli84adaab2016-09-20 01:12:28653 if (session_reused) {
654 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
655 } else {
656 ExpectConnectTimingHasTimes(
657 load_timing_info.connect_timing,
658 CONNECT_TIMING_HAS_SSL_TIMES | CONNECT_TIMING_HAS_DNS_TIMES);
659 }
660 ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info);
xunjieli100937eb52016-09-15 20:09:37661 }
662
Fan Yang32c5a112018-12-10 20:06:33663 quic::QuicStreamId GetNthClientInitiatedBidirectionalStreamId(int n) {
Nick Harper23290b82019-05-02 00:02:56664 return quic::test::GetNthClientInitiatedBidirectionalStreamId(
665 version_.transport_version, n);
ckrasicbf2f59c2017-05-04 23:54:36666 }
667
Fan Yang32c5a112018-12-10 20:06:33668 quic::QuicStreamId GetNthServerInitiatedUnidirectionalStreamId(int n) {
Nick Harper23290b82019-05-02 00:02:56669 return quic::test::GetNthServerInitiatedUnidirectionalStreamId(
670 version_.transport_version, n);
ckrasicbf2f59c2017-05-04 23:54:36671 }
672
Patrick Meenan0041f332022-05-19 23:48:35673 quic::test::QuicFlagSaver saver_;
Ryan Hamiltona1d1f4a2019-06-26 14:43:04674
Nick Harper23290b82019-05-02 00:02:56675 const quic::ParsedQuicVersion version_;
Yixin Wang079ad542018-01-11 04:06:05676 const bool client_headers_include_h2_stream_dependency_;
Patrick Meenanf741c6082023-01-03 18:06:43677 base::test::ScopedFeatureList scoped_feature_list_;
Yixin Wang079ad542018-01-11 04:06:05678
Matt Reichhoff0049a0b72021-10-20 20:44:26679 NetLogWithSource net_log_with_source_{
680 NetLogWithSource::Make(NetLog::Get(), NetLogSourceType::NONE)};
681 RecordingNetLogObserver net_log_observer_;
Keishi Hattori0e45c022021-11-27 09:25:52682 raw_ptr<quic::test::MockSendAlgorithm> send_algorithm_;
[email protected]f702d572012-12-04 15:56:20683 scoped_refptr<TestTaskRunner> runner_;
danakjad1777e2016-04-16 00:56:42684 std::unique_ptr<MockWrite[]> mock_writes_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52685 quic::MockClock clock_;
Keishi Hattori0e45c022021-11-27 09:25:52686 raw_ptr<TestQuicConnection> connection_;
danakjad1777e2016-04-16 00:56:42687 std::unique_ptr<QuicChromiumConnectionHelper> helper_;
rch16c74d1d2016-04-22 06:14:07688 std::unique_ptr<QuicChromiumAlarmFactory> alarm_factory_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52689 testing::StrictMock<quic::test::MockQuicConnectionVisitor> visitor_;
rch97827ee2017-05-24 23:49:12690 std::unique_ptr<UploadDataStream> upload_data_stream_;
danakjad1777e2016-04-16 00:56:42691 std::unique_ptr<QuicHttpStream> stream_;
[email protected]5db452202014-08-19 05:22:15692 TransportSecurityState transport_security_state_;
danakjad1777e2016-04-16 00:56:42693 std::unique_ptr<QuicChromiumClientSession> session_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52694 quic::QuicCryptoClientConfig crypto_config_;
[email protected]f702d572012-12-04 15:56:20695 TestCompletionCallback callback_;
696 HttpRequestInfo request_;
697 HttpRequestHeaders headers_;
698 HttpResponseInfo response_;
699 scoped_refptr<IOBufferWithSize> read_buffer_;
Bence Béky4c325e52020-10-22 20:48:01700 spdy::Http2HeaderBlock request_headers_;
701 spdy::Http2HeaderBlock response_headers_;
bnc614a92d32016-04-04 13:56:07702 string request_data_;
703 string response_data_;
[email protected]f702d572012-12-04 15:56:20704
ckrasic3865ee0f2016-02-29 22:04:56705 // For server push testing
danakjad1777e2016-04-16 00:56:42706 std::unique_ptr<QuicHttpStream> promised_stream_;
Bence Béky4c325e52020-10-22 20:48:01707 spdy::Http2HeaderBlock push_promise_;
708 spdy::Http2HeaderBlock promised_response_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52709 const quic::QuicStreamId promise_id_;
ckrasic3865ee0f2016-02-29 22:04:56710 string promise_url_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52711 const quic::QuicStreamId stream_id_;
ckrasic3865ee0f2016-02-29 22:04:56712
Ryan Hamilton8d9ee76e2018-05-29 23:52:52713 const quic::QuicConnectionId connection_id_;
alyssar2adf3ac2016-05-03 17:12:58714 QuicTestPacketMaker client_maker_;
715 QuicTestPacketMaker server_maker_;
[email protected]f702d572012-12-04 15:56:20716 IPEndPoint self_addr_;
717 IPEndPoint peer_addr_;
Tsuyoshi Horo432981d52022-06-09 09:50:13718 quic::test::MockRandom random_generator_{0};
rch03b7a202016-02-05 00:54:20719 ProofVerifyDetailsChromium verify_details_;
[email protected]e8ff26842013-03-22 21:02:05720 MockCryptoClientStreamFactory crypto_client_stream_factory_;
danakjad1777e2016-04-16 00:56:42721 std::unique_ptr<StaticSocketDataProvider> socket_data_;
Ryan Hamilton0d65a8c2019-06-07 00:46:02722 QuicPacketPrinter printer_;
[email protected]f702d572012-12-04 15:56:20723 std::vector<PacketToWrite> writes_;
Nidhi Jaju7135c5e2022-09-03 04:39:57724 quic::test::MockConnectionIdGenerator connection_id_generator_;
Bence Béky6e243aa2019-12-13 19:01:07725 quic::test::NoopQpackStreamSenderDelegate noop_qpack_stream_sender_delegate_;
[email protected]f702d572012-12-04 15:56:20726};
727
David Schinazi09e9a6012019-10-03 17:37:57728INSTANTIATE_TEST_SUITE_P(VersionIncludeStreamDependencySequence,
729 QuicHttpStreamTest,
730 ::testing::ValuesIn(GetTestParams()),
731 ::testing::PrintToStringParamName());
[email protected]1e960032013-12-20 19:00:20732
733TEST_P(QuicHttpStreamTest, RenewStreamForAuth) {
[email protected]ed3fc15d2013-03-08 18:37:44734 Initialize();
rtennetibe635732014-10-02 22:51:42735 EXPECT_EQ(nullptr, stream_->RenewStreamForAuth());
[email protected]f702d572012-12-04 15:56:20736}
737
mmenkebd84c392015-09-02 14:12:34738TEST_P(QuicHttpStreamTest, CanReuseConnection) {
[email protected]ed3fc15d2013-03-08 18:37:44739 Initialize();
mmenkebd84c392015-09-02 14:12:34740 EXPECT_FALSE(stream_->CanReuseConnection());
[email protected]f702d572012-12-04 15:56:20741}
742
jri231c2972016-03-08 19:50:11743TEST_P(QuicHttpStreamTest, DisableConnectionMigrationForStream) {
Zhongyi Shibb28b1f2018-07-18 02:41:26744 request_.load_flags |= LOAD_DISABLE_CONNECTION_MIGRATION_TO_CELLULAR;
jri231c2972016-03-08 19:50:11745 Initialize();
Ali Beyada0b1a1c2022-04-08 20:08:14746 stream_->RegisterRequest(&request_);
747 EXPECT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:26748 net_log_with_source_,
749 callback_.callback()));
rch08e198572017-05-09 16:56:55750 QuicChromiumClientStream::Handle* client_stream =
jri231c2972016-03-08 19:50:11751 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
Zhongyi Shibb28b1f2018-07-18 02:41:26752 EXPECT_FALSE(client_stream->can_migrate_to_cellular_network());
jri231c2972016-03-08 19:50:11753}
754
[email protected]1e960032013-12-20 19:00:20755TEST_P(QuicHttpStreamTest, GetRequest) {
756 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:45757 size_t spdy_request_header_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:23758 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:25759 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:23760 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:37761 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23762 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
763 kIncludeVersion, kFin, DEFAULT_PRIORITY,
764 &spdy_request_header_frame_length));
fayang3bcb8b502016-12-07 21:44:37765
[email protected]f702d572012-12-04 15:56:20766 Initialize();
767
768 request_.method = "GET";
rchcd379012017-04-12 21:53:32769 request_.url = GURL("https://www.example.org/");
[email protected]f702d572012-12-04 15:56:20770
xunjieli100937eb52016-09-15 20:09:37771 // Make sure getting load timing from the stream early does not crash.
772 LoadTimingInfo load_timing_info;
773 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
Ali Beyada0b1a1c2022-04-08 20:08:14774 stream_->RegisterRequest(&request_);
775 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:26776 net_log_with_source_,
777 callback_.callback()));
rjshaded5ced072015-12-18 19:26:02778 EXPECT_EQ(OK,
779 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20780
781 // Ack the request.
Renjie90e808e2019-01-24 07:24:04782 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]f702d572012-12-04 15:56:20783
robpercival214763f2016-07-01 23:27:01784 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
785 IsError(ERR_IO_PENDING));
[email protected]f702d572012-12-04 15:56:20786
Kenichi Ishibashif8634ab2021-03-16 23:41:28787 SetResponse("404", string());
sclittlec4dc1a32015-09-24 00:15:45788 size_t spdy_response_header_frame_length;
789 ProcessPacket(ConstructResponseHeadersPacket(
790 2, kFin, &spdy_response_header_frame_length));
[email protected]f702d572012-12-04 15:56:20791
792 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:01793 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]cadac622013-06-11 16:46:36794 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:20795 EXPECT_EQ(404, response_.headers->response_code());
796 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
[email protected]6ed67432014-06-24 01:53:53797 EXPECT_FALSE(response_.response_time.is_null());
798 EXPECT_FALSE(response_.request_time.is_null());
[email protected]f702d572012-12-04 15:56:20799
800 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:02801 EXPECT_EQ(0,
802 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
803 callback_.callback()));
[email protected]f702d572012-12-04 15:56:20804 EXPECT_TRUE(stream_->IsResponseBodyComplete());
805 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:10806
xunjieli100937eb52016-09-15 20:09:37807 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
xunjieli84adaab2016-09-20 01:12:28808 ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
xunjieli100937eb52016-09-15 20:09:37809
sclittle1edeeb22015-09-02 20:46:10810 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:45811 // headers and payload.
812 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
813 stream_->GetTotalSentBytes());
814 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length),
815 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:20816}
817
xunjieli100937eb52016-09-15 20:09:37818TEST_P(QuicHttpStreamTest, LoadTimingTwoRequests) {
819 SetRequest("GET", "/", DEFAULT_PRIORITY);
820 size_t spdy_request_header_frame_length;
821
Renjie Tangaadb84b2019-08-31 01:00:23822 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:25823 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:23824 AddWrite(ConstructInitialSettingsPacket(packet_number++));
xunjieli100937eb52016-09-15 20:09:37825 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23826 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
827 kIncludeVersion, kFin, DEFAULT_PRIORITY,
828 &spdy_request_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37829
830 // SetRequest() again for second request as |request_headers_| was moved.
831 SetRequest("GET", "/", DEFAULT_PRIORITY);
832 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23833 packet_number++, GetNthClientInitiatedBidirectionalStreamId(1),
834 kIncludeVersion, kFin, DEFAULT_PRIORITY,
835 GetNthClientInitiatedBidirectionalStreamId(0),
Ryan Hamilton0d65a8c2019-06-07 00:46:02836 &spdy_request_header_frame_length));
Renjie Tangcd594f32020-07-11 20:18:34837 AddWrite(
838 ConstructClientAckPacket(packet_number++, 3, 1)); // Ack the responses.
xunjieli100937eb52016-09-15 20:09:37839
840 Initialize();
841
842 request_.method = "GET";
rchcd379012017-04-12 21:53:32843 request_.url = GURL("https://www.example.org/");
xunjieli100937eb52016-09-15 20:09:37844 // Start first request.
Ali Beyada0b1a1c2022-04-08 20:08:14845 stream_->RegisterRequest(&request_);
846 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:26847 net_log_with_source_,
848 callback_.callback()));
xunjieli100937eb52016-09-15 20:09:37849 EXPECT_EQ(OK,
850 stream_->SendRequest(headers_, &response_, callback_.callback()));
851
852 // Start a second request.
Dan McArdle68a5f622021-07-09 20:56:53853 QuicHttpStream stream2(session_->CreateHandle(url::SchemeHostPort(
854 url::kHttpsScheme, "www.example.org", 443)),
855 {} /* dns_aliases */);
xunjieli100937eb52016-09-15 20:09:37856 TestCompletionCallback callback2;
Ali Beyada0b1a1c2022-04-08 20:08:14857 stream2.RegisterRequest(&request_);
Matt Reichhoff0049a0b72021-10-20 20:44:26858 EXPECT_EQ(
Ali Beyada0b1a1c2022-04-08 20:08:14859 OK, stream2.InitializeStream(true, DEFAULT_PRIORITY, net_log_with_source_,
860 callback2.callback()));
xunjieli100937eb52016-09-15 20:09:37861 EXPECT_EQ(OK,
862 stream2.SendRequest(headers_, &response_, callback2.callback()));
863
864 // Ack both requests.
Renjie90e808e2019-01-24 07:24:04865 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
xunjieli100937eb52016-09-15 20:09:37866
867 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
868 IsError(ERR_IO_PENDING));
869 size_t spdy_response_header_frame_length;
Kenichi Ishibashif8634ab2021-03-16 23:41:28870 SetResponse("200", string());
xunjieli100937eb52016-09-15 20:09:37871 ProcessPacket(InnerConstructResponseHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33872 2, GetNthClientInitiatedBidirectionalStreamId(0), kFin,
ckrasicbf2f59c2017-05-04 23:54:36873 &spdy_response_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37874
875 // Now that the headers have been processed, the callback will return.
876 EXPECT_THAT(callback_.WaitForResult(), IsOk());
877 EXPECT_EQ(200, response_.headers->response_code());
878
879 // There is no body, so this should return immediately.
880 EXPECT_EQ(0,
881 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
882 callback_.callback()));
883 EXPECT_TRUE(stream_->IsResponseBodyComplete());
884
885 LoadTimingInfo load_timing_info;
886 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
xunjieli84adaab2016-09-20 01:12:28887 ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
xunjieli100937eb52016-09-15 20:09:37888
889 // SetResponse() again for second request as |response_headers_| was moved.
Kenichi Ishibashif8634ab2021-03-16 23:41:28890 SetResponse("200", string());
xunjieli100937eb52016-09-15 20:09:37891 EXPECT_THAT(stream2.ReadResponseHeaders(callback2.callback()),
892 IsError(ERR_IO_PENDING));
893
894 ProcessPacket(InnerConstructResponseHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33895 3, GetNthClientInitiatedBidirectionalStreamId(1), kFin,
ckrasicbf2f59c2017-05-04 23:54:36896 &spdy_response_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37897
898 EXPECT_THAT(callback2.WaitForResult(), IsOk());
899
900 // There is no body, so this should return immediately.
901 EXPECT_EQ(0,
902 stream2.ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
903 callback2.callback()));
904 EXPECT_TRUE(stream2.IsResponseBodyComplete());
905
906 LoadTimingInfo load_timing_info2;
907 EXPECT_TRUE(stream2.GetLoadTimingInfo(&load_timing_info2));
xunjieli84adaab2016-09-20 01:12:28908 ExpectLoadTimingValid(load_timing_info2, /*session_reused=*/true);
xunjieli100937eb52016-09-15 20:09:37909}
910
xunjieli34291fe12016-03-02 13:58:38911// QuicHttpStream does not currently support trailers. It should ignore
912// trailers upon receiving them.
913TEST_P(QuicHttpStreamTest, GetRequestWithTrailers) {
914 SetRequest("GET", "/", DEFAULT_PRIORITY);
915 size_t spdy_request_header_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:23916 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:25917 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:23918 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:37919 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23920 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
921 kIncludeVersion, kFin, DEFAULT_PRIORITY,
922 &spdy_request_header_frame_length));
Renjie Tangcd594f32020-07-11 20:18:34923 AddWrite(
924 ConstructClientAckPacket(packet_number++, 3, 1)); // Ack the data packet.
xunjieli34291fe12016-03-02 13:58:38925
926 Initialize();
927
928 request_.method = "GET";
rchcd379012017-04-12 21:53:32929 request_.url = GURL("https://www.example.org/");
Ali Beyada0b1a1c2022-04-08 20:08:14930 stream_->RegisterRequest(&request_);
931 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:26932 net_log_with_source_,
933 callback_.callback()));
xunjieli5fafe142016-03-23 23:32:54934
xunjieli34291fe12016-03-02 13:58:38935 EXPECT_EQ(OK,
936 stream_->SendRequest(headers_, &response_, callback_.callback()));
xunjieli34291fe12016-03-02 13:58:38937 // Ack the request.
Renjie90e808e2019-01-24 07:24:04938 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
xunjieli34291fe12016-03-02 13:58:38939
robpercival214763f2016-07-01 23:27:01940 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
941 IsError(ERR_IO_PENDING));
xunjieli34291fe12016-03-02 13:58:38942
Kenichi Ishibashif8634ab2021-03-16 23:41:28943 SetResponse("200", string());
xunjieli34291fe12016-03-02 13:58:38944
945 // Send the response headers.
946 size_t spdy_response_header_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:02947 ProcessPacket(ConstructResponseHeadersPacket(
948 2, !kFin, &spdy_response_header_frame_length));
xunjieli34291fe12016-03-02 13:58:38949 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:01950 EXPECT_THAT(callback_.WaitForResult(), IsOk());
xunjieli34291fe12016-03-02 13:58:38951 ASSERT_TRUE(response_.headers.get());
952 EXPECT_EQ(200, response_.headers->response_code());
953 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
954 EXPECT_FALSE(response_.response_time.is_null());
955 EXPECT_FALSE(response_.request_time.is_null());
956
957 // Send the response body.
958 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:43959 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:17960 ProcessPacket(
961 ConstructServerDataPacket(3, false, !kFin, header + kResponseBody));
Bence Béky4c325e52020-10-22 20:48:01962 spdy::Http2HeaderBlock trailers;
xunjieli34291fe12016-03-02 13:58:38963 size_t spdy_trailers_frame_length;
964 trailers["foo"] = "bar";
Victor Vasiliev7da08172019-10-14 06:04:25965 if (!quic::VersionUsesHttp3(version_.transport_version)) {
Ryan Hamiltona1d1f4a2019-06-26 14:43:04966 trailers[quic::kFinalOffsetHeaderKey] =
967 base::NumberToString(strlen(kResponseBody) + header.length());
968 }
Ryan Hamilton0d65a8c2019-06-07 00:46:02969 ProcessPacket(ConstructResponseTrailersPacket(4, kFin, std::move(trailers),
970 &spdy_trailers_frame_length));
xunjieli34291fe12016-03-02 13:58:38971
972 // Make sure trailers are processed.
fdoray92e35a72016-06-10 15:54:55973 base::RunLoop().RunUntilIdle();
xunjieli34291fe12016-03-02 13:58:38974
975 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
976 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
977 callback_.callback()));
978 EXPECT_TRUE(stream_->IsResponseBodyComplete());
979
980 EXPECT_EQ(OK,
981 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
982 callback_.callback()));
983
984 EXPECT_TRUE(stream_->IsResponseBodyComplete());
985 EXPECT_TRUE(AtEof());
986
987 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
988 // headers and payload.
989 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
990 stream_->GetTotalSentBytes());
Renjief49758b2019-01-11 23:32:41991 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length +
992 strlen(kResponseBody) + header.length() +
993 +spdy_trailers_frame_length),
994 stream_->GetTotalReceivedBytes());
xunjieli5fafe142016-03-23 23:32:54995 // Check that NetLog was filled as expected.
Matt Reichhoff0049a0b72021-10-20 20:44:26996 auto entries = net_log_observer_.GetEntries();
xunjieli5fafe142016-03-23 23:32:54997 size_t pos = ExpectLogContainsSomewhere(
998 entries, /*min_offset=*/0,
mikecirone8b85c432016-09-08 19:11:00999 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
1000 NetLogEventPhase::NONE);
xunjieli5fafe142016-03-23 23:32:541001 pos = ExpectLogContainsSomewhere(
1002 entries, /*min_offset=*/pos,
mikecirone8b85c432016-09-08 19:11:001003 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
1004 NetLogEventPhase::NONE);
xunjieli5fafe142016-03-23 23:32:541005 ExpectLogContainsSomewhere(
1006 entries, /*min_offset=*/pos,
mikecirone8b85c432016-09-08 19:11:001007 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
1008 NetLogEventPhase::NONE);
xunjieli34291fe12016-03-02 13:58:381009}
1010
Bence Béky6c2c78f2020-08-28 16:49:061011TEST_P(QuicHttpStreamTest, ElideHeadersInNetLog) {
1012 Initialize();
1013
1014 // QuicHttp3Logger is only used with HTTP/3.
1015 if (!VersionUsesHttp3(version_.transport_version)) {
1016 return;
1017 }
1018
Matt Reichhoff0049a0b72021-10-20 20:44:261019 net_log_observer_.SetObserverCaptureMode(NetLogCaptureMode::kDefault);
Bence Béky6c2c78f2020-08-28 16:49:061020
Bence Békye0d3747d2020-08-28 23:16:401021 // Send first request.
Bence Béky6c2c78f2020-08-28 16:49:061022 SetRequest("GET", "/", DEFAULT_PRIORITY);
1023 request_.method = "GET";
1024 request_.url = GURL("https://www.example.org/");
1025 headers_.SetHeader(HttpRequestHeaders::kCookie, "secret");
1026
1027 size_t spdy_request_header_frame_length;
Bence Békye0d3747d2020-08-28 23:16:401028 int outgoing_packet_number = 1;
1029 AddWrite(ConstructInitialSettingsPacket(outgoing_packet_number++));
Bence Béky6c2c78f2020-08-28 16:49:061030 AddWrite(InnerConstructRequestHeadersPacket(
Bence Békye0d3747d2020-08-28 23:16:401031 outgoing_packet_number++, stream_id_, kIncludeVersion, kFin,
1032 DEFAULT_PRIORITY, &spdy_request_header_frame_length));
Bence Béky6c2c78f2020-08-28 16:49:061033
Ali Beyada0b1a1c2022-04-08 20:08:141034 stream_->RegisterRequest(&request_);
Matt Reichhoff0049a0b72021-10-20 20:44:261035 EXPECT_THAT(
Ali Beyada0b1a1c2022-04-08 20:08:141036 stream_->InitializeStream(true, DEFAULT_PRIORITY, net_log_with_source_,
1037 callback_.callback()),
Matt Reichhoff0049a0b72021-10-20 20:44:261038 IsOk());
Bence Béky6c2c78f2020-08-28 16:49:061039 EXPECT_THAT(stream_->SendRequest(headers_, &response_, callback_.callback()),
1040 IsOk());
Bence Békye0d3747d2020-08-28 23:16:401041 int incoming_packet_number = 1;
1042 ProcessPacket(ConstructServerAckPacket(incoming_packet_number++, 1, 1,
1043 1)); // Ack the request.
Bence Béky6c2c78f2020-08-28 16:49:061044
Bence Békye0d3747d2020-08-28 23:16:401045 // Process first response.
Kenichi Ishibashif8634ab2021-03-16 23:41:281046 SetResponse("200", string());
Bence Béky6c2c78f2020-08-28 16:49:061047 response_headers_["set-cookie"] = "secret";
1048 size_t spdy_response_header_frame_length;
1049 ProcessPacket(ConstructResponseHeadersPacket(
Bence Békye0d3747d2020-08-28 23:16:401050 incoming_packet_number++, kFin, &spdy_response_header_frame_length));
Bence Béky6c2c78f2020-08-28 16:49:061051 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
Bence Béky6c2c78f2020-08-28 16:49:061052
1053 ASSERT_TRUE(response_.headers.get());
1054 EXPECT_EQ(200, response_.headers->response_code());
1055 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1056 EXPECT_TRUE(response_.headers->HasHeaderValue("set-cookie", "secret"));
1057
Matt Reichhoff0049a0b72021-10-20 20:44:261058 net_log_observer_.SetObserverCaptureMode(
1059 NetLogCaptureMode::kIncludeSensitive);
Bence Béky6c2c78f2020-08-28 16:49:061060
Bence Békye0d3747d2020-08-28 23:16:401061 // Send second request.
1062 quic::QuicStreamId stream_id = GetNthClientInitiatedBidirectionalStreamId(1);
1063 request_.url = GURL("https://www.example.org/foo");
Bence Béky6c2c78f2020-08-28 16:49:061064
Bence Békye0d3747d2020-08-28 23:16:401065 AddWrite(InnerConstructRequestHeadersPacket(
1066 outgoing_packet_number++, stream_id, kIncludeVersion, kFin,
1067 DEFAULT_PRIORITY, &spdy_request_header_frame_length));
Bence Béky6c2c78f2020-08-28 16:49:061068
Bence Békye0d3747d2020-08-28 23:16:401069 auto stream = std::make_unique<QuicHttpStream>(
Dan McArdle68a5f622021-07-09 20:56:531070 session_->CreateHandle(
1071 url::SchemeHostPort(url::kHttpsScheme, "www.example.org/foo", 443)),
Eric Orthac661912022-01-10 21:44:171072 /*dns_aliases=*/std::set<std::string>());
Ali Beyada0b1a1c2022-04-08 20:08:141073 stream->RegisterRequest(&request_);
Matt Reichhoff0049a0b72021-10-20 20:44:261074 EXPECT_THAT(
Ali Beyada0b1a1c2022-04-08 20:08:141075 stream->InitializeStream(true, DEFAULT_PRIORITY, net_log_with_source_,
1076 callback_.callback()),
Matt Reichhoff0049a0b72021-10-20 20:44:261077 IsOk());
Bence Békye0d3747d2020-08-28 23:16:401078 EXPECT_THAT(stream->SendRequest(headers_, &response_, callback_.callback()),
1079 IsOk());
1080 ProcessPacket(ConstructServerAckPacket(incoming_packet_number++, 1, 1,
1081 1)); // Ack the request.
Bence Béky6c2c78f2020-08-28 16:49:061082
Bence Békye0d3747d2020-08-28 23:16:401083 // Process second response.
Kenichi Ishibashif8634ab2021-03-16 23:41:281084 SetResponse("200", string());
Bence Békye0d3747d2020-08-28 23:16:401085 response_headers_["set-cookie"] = "secret";
1086 ProcessPacket(InnerConstructResponseHeadersPacket(
1087 incoming_packet_number++, stream_id, kFin,
1088 &spdy_response_header_frame_length));
1089 EXPECT_THAT(stream->ReadResponseHeaders(callback_.callback()), IsOk());
Bence Béky6c2c78f2020-08-28 16:49:061090
Bence Békye0d3747d2020-08-28 23:16:401091 ASSERT_TRUE(response_.headers.get());
1092 EXPECT_EQ(200, response_.headers->response_code());
1093 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1094 EXPECT_TRUE(response_.headers->HasHeaderValue("set-cookie", "secret"));
1095
1096 EXPECT_TRUE(AtEof());
1097
1098 // Check that sensitive header value were stripped
1099 // for the first transaction (logged with NetLogCaptureMode::kDefault)
1100 // but not for the second (logged with NetLogCaptureMode::kIncludeSensitive).
1101 auto entries =
Matt Reichhoff0049a0b72021-10-20 20:44:261102 net_log_observer_.GetEntriesWithType(NetLogEventType::HTTP3_HEADERS_SENT);
Bence Békye0d3747d2020-08-28 23:16:401103 ASSERT_EQ(2u, entries.size());
1104 EXPECT_TRUE(
1105 CheckHeader(entries[0].params, "cookie", "[6 bytes were stripped]"));
1106 EXPECT_TRUE(CheckHeader(entries[1].params, "cookie", "secret"));
1107
Matt Reichhoff0049a0b72021-10-20 20:44:261108 entries = net_log_observer_.GetEntriesWithType(
1109 NetLogEventType::HTTP3_HEADERS_DECODED);
Bence Békye0d3747d2020-08-28 23:16:401110 ASSERT_EQ(2u, entries.size());
1111 EXPECT_TRUE(
1112 CheckHeader(entries[0].params, "set-cookie", "[6 bytes were stripped]"));
1113 EXPECT_TRUE(CheckHeader(entries[1].params, "set-cookie", "secret"));
Bence Béky6c2c78f2020-08-28 16:49:061114}
1115
[email protected]3e7dca62013-09-10 16:14:231116// Regression test for http://crbug.com/288128
[email protected]1e960032013-12-20 19:00:201117TEST_P(QuicHttpStreamTest, GetRequestLargeResponse) {
1118 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451119 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231120 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251121 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231122 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371123 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231124 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1125 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1126 &spdy_request_headers_frame_length));
[email protected]3e7dca62013-09-10 16:14:231127 Initialize();
1128
1129 request_.method = "GET";
rchcd379012017-04-12 21:53:321130 request_.url = GURL("https://www.example.org/");
[email protected]3e7dca62013-09-10 16:14:231131
Ali Beyada0b1a1c2022-04-08 20:08:141132 stream_->RegisterRequest(&request_);
1133 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261134 net_log_with_source_,
1135 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021136 EXPECT_EQ(OK,
1137 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:231138
1139 // Ack the request.
Renjie90e808e2019-01-24 07:24:041140 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]3e7dca62013-09-10 16:14:231141
robpercival214763f2016-07-01 23:27:011142 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1143 IsError(ERR_IO_PENDING));
[email protected]3e7dca62013-09-10 16:14:231144
Kenichi Ishibashif8634ab2021-03-16 23:41:281145 response_headers_[":status"] = "200";
bnc086b39e12016-06-24 13:05:261146 response_headers_[":version"] = "HTTP/1.1";
1147 response_headers_["content-type"] = "text/plain";
1148 response_headers_["big6"] = string(1000, 'x'); // Lots of x's.
[email protected]3e7dca62013-09-10 16:14:231149
sclittlec4dc1a32015-09-24 00:15:451150 size_t spdy_response_headers_frame_length;
1151 ProcessPacket(ConstructResponseHeadersPacket(
1152 2, kFin, &spdy_response_headers_frame_length));
[email protected]3e7dca62013-09-10 16:14:231153
1154 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:011155 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]3e7dca62013-09-10 16:14:231156 ASSERT_TRUE(response_.headers.get());
1157 EXPECT_EQ(200, response_.headers->response_code());
1158 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1159
1160 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:021161 EXPECT_EQ(0,
1162 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1163 callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:231164 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1165 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101166
1167 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451168 // headers and payload.
1169 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1170 stream_->GetTotalSentBytes());
1171 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length),
1172 stream_->GetTotalReceivedBytes());
[email protected]3e7dca62013-09-10 16:14:231173}
1174
rchf9f103cbc2014-08-30 05:28:041175// Regression test for http://crbug.com/409101
1176TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendRequest) {
1177 SetRequest("GET", "/", DEFAULT_PRIORITY);
1178 Initialize();
1179
1180 request_.method = "GET";
rchcd379012017-04-12 21:53:321181 request_.url = GURL("https://www.example.org/");
rchf9f103cbc2014-08-30 05:28:041182
Ali Beyada0b1a1c2022-04-08 20:08:141183 stream_->RegisterRequest(&request_);
1184 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261185 net_log_with_source_,
1186 callback_.callback()));
rchf9f103cbc2014-08-30 05:28:041187
jri78ec06a2016-03-31 18:19:401188 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521189 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rchf9f103cbc2014-08-30 05:28:041190
1191 EXPECT_EQ(ERR_CONNECTION_CLOSED,
rjshaded5ced072015-12-18 19:26:021192 stream_->SendRequest(headers_, &response_, callback_.callback()));
sclittle1edeeb22015-09-02 20:46:101193
1194 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1195 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rchf9f103cbc2014-08-30 05:28:041196}
1197
rch03b7a202016-02-05 00:54:201198// Regression test for http://crbug.com/584441
1199TEST_P(QuicHttpStreamTest, GetSSLInfoAfterSessionClosed) {
1200 SetRequest("GET", "/", DEFAULT_PRIORITY);
1201 Initialize();
1202
1203 request_.method = "GET";
rchcd379012017-04-12 21:53:321204 request_.url = GURL("https://www.example.org/");
rch03b7a202016-02-05 00:54:201205
Ali Beyada0b1a1c2022-04-08 20:08:141206 stream_->RegisterRequest(&request_);
1207 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261208 net_log_with_source_,
1209 callback_.callback()));
rch03b7a202016-02-05 00:54:201210
1211 SSLInfo ssl_info;
rch11565e02016-02-09 20:13:471212 EXPECT_FALSE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:201213 stream_->GetSSLInfo(&ssl_info);
rch11565e02016-02-09 20:13:471214 EXPECT_TRUE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:201215
jri78ec06a2016-03-31 18:19:401216 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521217 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rch03b7a202016-02-05 00:54:201218
rch11565e02016-02-09 20:13:471219 SSLInfo ssl_info2;
1220 stream_->GetSSLInfo(&ssl_info2);
1221 EXPECT_TRUE(ssl_info2.is_valid());
rch03b7a202016-02-05 00:54:201222}
1223
rchcd379012017-04-12 21:53:321224TEST_P(QuicHttpStreamTest, GetAlternativeService) {
1225 SetRequest("GET", "/", DEFAULT_PRIORITY);
1226 Initialize();
1227
1228 request_.method = "GET";
1229 request_.url = GURL("https://www.example.org/");
1230
Ali Beyada0b1a1c2022-04-08 20:08:141231 stream_->RegisterRequest(&request_);
1232 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261233 net_log_with_source_,
1234 callback_.callback()));
rchcd379012017-04-12 21:53:321235
1236 AlternativeService alternative_service;
1237 EXPECT_TRUE(stream_->GetAlternativeService(&alternative_service));
1238 EXPECT_EQ(AlternativeService(kProtoQUIC, "www.example.org", 443),
1239 alternative_service);
1240
1241 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521242 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rchcd379012017-04-12 21:53:321243
1244 AlternativeService alternative_service2;
1245 EXPECT_TRUE(stream_->GetAlternativeService(&alternative_service2));
1246 EXPECT_EQ(AlternativeService(kProtoQUIC, "www.example.org", 443),
1247 alternative_service2);
1248}
1249
zhongyica364fbb2015-12-12 03:39:121250TEST_P(QuicHttpStreamTest, LogGranularQuicConnectionError) {
1251 SetRequest("GET", "/", DEFAULT_PRIORITY);
1252 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231253 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251254 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231255 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371256 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231257 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1258 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1259 &spdy_request_headers_frame_length));
fayang3bcb8b502016-12-07 21:44:371260 AddWrite(ConstructAckAndRstStreamPacket(3));
zhongyica364fbb2015-12-12 03:39:121261 Initialize();
1262
1263 request_.method = "GET";
rchcd379012017-04-12 21:53:321264 request_.url = GURL("https://www.example.org/");
zhongyica364fbb2015-12-12 03:39:121265
Ali Beyada0b1a1c2022-04-08 20:08:141266 stream_->RegisterRequest(&request_);
1267 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261268 net_log_with_source_,
1269 callback_.callback()));
zhongyica364fbb2015-12-12 03:39:121270 EXPECT_EQ(OK,
1271 stream_->SendRequest(headers_, &response_, callback_.callback()));
1272
1273 // Ack the request.
Renjie90e808e2019-01-24 07:24:041274 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011275 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1276 IsError(ERR_IO_PENDING));
zhongyica364fbb2015-12-12 03:39:121277
Ryan Hamilton8d9ee76e2018-05-29 23:52:521278 quic::QuicConnectionCloseFrame frame;
Zhongyi Shica576df2019-04-12 17:43:401279 frame.quic_error_code = quic::QUIC_PEER_GOING_AWAY;
rch1c5b74a2016-06-23 22:10:551280 session_->connection()->OnConnectionCloseFrame(frame);
zhongyica364fbb2015-12-12 03:39:121281
1282 NetErrorDetails details;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521283 EXPECT_EQ(quic::QUIC_NO_ERROR, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121284 stream_->PopulateNetErrorDetails(&details);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521285 EXPECT_EQ(quic::QUIC_PEER_GOING_AWAY, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121286}
1287
Ryan Hamiltone316e482017-08-17 02:48:531288TEST_P(QuicHttpStreamTest, LogGranularQuicErrorIfHandshakeNotConfirmed) {
rch617e0652017-04-26 17:57:511289 // By default the test setup defaults handshake to be confirmed. Manually set
1290 // it to be not confirmed.
rch617e0652017-04-26 17:57:511291 crypto_client_stream_factory_.set_handshake_mode(
Ryan Hamilton9835e662018-08-02 05:36:271292 MockCryptoClientStream::ZERO_RTT);
rch617e0652017-04-26 17:57:511293
zhongyica364fbb2015-12-12 03:39:121294 SetRequest("GET", "/", DEFAULT_PRIORITY);
1295 size_t spdy_request_headers_frame_length;
Michael Warres167db3e2019-03-01 21:38:031296 client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
Nick Harper057264a82019-09-12 23:33:491297 client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
1298 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251299 if (VersionUsesHttp3(version_.transport_version))
Nick Harper057264a82019-09-12 23:33:491300 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371301 AddWrite(InnerConstructRequestHeadersPacket(
Nick Harper057264a82019-09-12 23:33:491302 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1303 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1304 &spdy_request_headers_frame_length));
zhongyica364fbb2015-12-12 03:39:121305 Initialize();
1306
1307 request_.method = "GET";
rchcd379012017-04-12 21:53:321308 request_.url = GURL("https://www.example.org/");
zhongyica364fbb2015-12-12 03:39:121309
Ali Beyada0b1a1c2022-04-08 20:08:141310 stream_->RegisterRequest(&request_);
1311 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261312 net_log_with_source_,
1313 callback_.callback()));
zhongyica364fbb2015-12-12 03:39:121314 EXPECT_EQ(OK,
1315 stream_->SendRequest(headers_, &response_, callback_.callback()));
1316
1317 // Ack the request.
Renjie90e808e2019-01-24 07:24:041318 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011319 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1320 IsError(ERR_IO_PENDING));
zhongyica364fbb2015-12-12 03:39:121321
Ryan Hamilton8d9ee76e2018-05-29 23:52:521322 quic::QuicConnectionCloseFrame frame;
Zhongyi Shica576df2019-04-12 17:43:401323 frame.quic_error_code = quic::QUIC_PEER_GOING_AWAY;
rch1c5b74a2016-06-23 22:10:551324 session_->connection()->OnConnectionCloseFrame(frame);
zhongyica364fbb2015-12-12 03:39:121325
1326 NetErrorDetails details;
zhongyica364fbb2015-12-12 03:39:121327 stream_->PopulateNetErrorDetails(&details);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521328 EXPECT_EQ(quic::QUIC_PEER_GOING_AWAY, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121329}
1330
rch11a114a2014-09-04 23:41:591331// Regression test for http://crbug.com/409871
1332TEST_P(QuicHttpStreamTest, SessionClosedBeforeReadResponseHeaders) {
1333 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451334 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231335 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251336 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231337 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371338 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231339 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1340 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1341 &spdy_request_headers_frame_length));
rch11a114a2014-09-04 23:41:591342 Initialize();
1343
1344 request_.method = "GET";
rchcd379012017-04-12 21:53:321345 request_.url = GURL("https://www.example.org/");
rch11a114a2014-09-04 23:41:591346
Ali Beyada0b1a1c2022-04-08 20:08:141347 stream_->RegisterRequest(&request_);
1348 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261349 net_log_with_source_,
1350 callback_.callback()));
rch11a114a2014-09-04 23:41:591351
rjshaded5ced072015-12-18 19:26:021352 EXPECT_EQ(OK,
1353 stream_->SendRequest(headers_, &response_, callback_.callback()));
rch11a114a2014-09-04 23:41:591354
jri78ec06a2016-03-31 18:19:401355 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521356 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rch11a114a2014-09-04 23:41:591357
1358 EXPECT_NE(OK, stream_->ReadResponseHeaders(callback_.callback()));
sclittle1edeeb22015-09-02 20:46:101359
1360 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451361 // headers and payload.
1362 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1363 stream_->GetTotalSentBytes());
sclittle1edeeb22015-09-02 20:46:101364 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rch11a114a2014-09-04 23:41:591365}
1366
[email protected]1e960032013-12-20 19:00:201367TEST_P(QuicHttpStreamTest, SendPostRequest) {
1368 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451369 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231370 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251371 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231372 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Yixin Wange7ecc472018-03-06 19:00:251373
Victor Vasiliev076657c2019-03-12 02:46:431374 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:321375 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411376 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231377 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1378 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1379 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411380 } else {
1381 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231382 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1383 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1384 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411385 }
Yixin Wange7ecc472018-03-06 19:00:251386
Renjie Tangcd594f32020-07-11 20:18:341387 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]f702d572012-12-04 15:56:201388
1389 Initialize();
1390
danakjad1777e2016-04-16 00:56:421391 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:191392 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
ricea2deef682016-09-09 08:04:071393 kUploadData, strlen(kUploadData)));
rch97827ee2017-05-24 23:49:121394 upload_data_stream_ =
Jeremy Roman0579ed62017-08-29 15:56:191395 std::make_unique<ElementsUploadDataStream>(std::move(element_readers), 0);
[email protected]f702d572012-12-04 15:56:201396 request_.method = "POST";
rchcd379012017-04-12 21:53:321397 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121398 request_.upload_data_stream = upload_data_stream_.get();
Bence Békyd8a21fc32018-06-27 18:29:581399 ASSERT_THAT(request_.upload_data_stream->Init(CompletionOnceCallback(),
tfarina42834112016-09-22 13:38:201400 NetLogWithSource()),
1401 IsOk());
[email protected]f702d572012-12-04 15:56:201402
Ali Beyada0b1a1c2022-04-08 20:08:141403 stream_->RegisterRequest(&request_);
1404 EXPECT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261405 net_log_with_source_,
1406 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021407 EXPECT_EQ(OK,
1408 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:201409
1410 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041411 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]f702d572012-12-04 15:56:201412
1413 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281414 SetResponse("200", string());
sclittlec4dc1a32015-09-24 00:15:451415 size_t spdy_response_headers_frame_length;
1416 ProcessPacket(ConstructResponseHeadersPacket(
1417 2, !kFin, &spdy_response_headers_frame_length));
[email protected]f702d572012-12-04 15:56:201418
rchfb47f712017-05-21 03:24:001419 // The headers have already arrived.
1420 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]cadac622013-06-11 16:46:361421 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:201422 EXPECT_EQ(200, response_.headers->response_code());
1423 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1424
1425 // Send the response body.
1426 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431427 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:411428 ProcessPacket(
Ryan Hamilton7505eb92019-06-08 00:22:171429 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
[email protected]f702d572012-12-04 15:56:201430 // Since the body has already arrived, this should return immediately.
1431 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
1432 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1433 callback_.callback()));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291434 EXPECT_EQ(0,
1435 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1436 callback_.callback()));
1437
1438 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1439 EXPECT_TRUE(AtEof());
1440
1441 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
1442 // headers and payload.
1443 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411444 strlen(kUploadData) + header.length()),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291445 stream_->GetTotalSentBytes());
1446 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411447 strlen(kResponseBody) + header2.length()),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291448 stream_->GetTotalReceivedBytes());
1449}
1450
1451TEST_P(QuicHttpStreamTest, SendPostRequestAndReceiveSoloFin) {
1452 SetRequest("POST", "/", DEFAULT_PRIORITY);
1453 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231454 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251455 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231456 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431457 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:321458 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411459 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231460 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1461 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1462 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411463 } else {
1464 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231465 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1466 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1467 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411468 }
1469
Renjie Tangcd594f32020-07-11 20:18:341470 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291471
1472 Initialize();
1473
1474 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:191475 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
Ryan Hamilton2ef0a9c2017-07-25 03:18:291476 kUploadData, strlen(kUploadData)));
1477 upload_data_stream_ =
Jeremy Roman0579ed62017-08-29 15:56:191478 std::make_unique<ElementsUploadDataStream>(std::move(element_readers), 0);
Ryan Hamilton2ef0a9c2017-07-25 03:18:291479 request_.method = "POST";
1480 request_.url = GURL("https://www.example.org/");
1481 request_.upload_data_stream = upload_data_stream_.get();
Bence Békyd8a21fc32018-06-27 18:29:581482 ASSERT_THAT(request_.upload_data_stream->Init(CompletionOnceCallback(),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291483 NetLogWithSource()),
1484 IsOk());
1485
Ali Beyada0b1a1c2022-04-08 20:08:141486 stream_->RegisterRequest(&request_);
1487 EXPECT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261488 net_log_with_source_,
1489 callback_.callback()));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291490 EXPECT_EQ(OK,
1491 stream_->SendRequest(headers_, &response_, callback_.callback()));
1492
1493 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041494 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291495
1496 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281497 SetResponse("200", string());
Ryan Hamilton2ef0a9c2017-07-25 03:18:291498 size_t spdy_response_headers_frame_length;
1499 ProcessPacket(ConstructResponseHeadersPacket(
1500 2, !kFin, &spdy_response_headers_frame_length));
1501
1502 // The headers have already arrived.
1503 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
1504 ASSERT_TRUE(response_.headers.get());
1505 EXPECT_EQ(200, response_.headers->response_code());
1506 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1507
1508 // Send the response body.
1509 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431510 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:411511 ProcessPacket(
Ryan Hamilton7505eb92019-06-08 00:22:171512 ConstructServerDataPacket(3, false, !kFin, header2 + kResponseBody));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291513 // Since the body has already arrived, this should return immediately.
1514 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
1515 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1516 callback_.callback()));
Ryan Hamilton7505eb92019-06-08 00:22:171517 ProcessPacket(ConstructServerDataPacket(4, false, kFin, ""));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291518 EXPECT_EQ(0,
1519 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1520 callback_.callback()));
[email protected]f702d572012-12-04 15:56:201521
1522 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1523 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101524
1525 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451526 // headers and payload.
1527 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411528 strlen(kUploadData) + header.length()),
sclittle1edeeb22015-09-02 20:46:101529 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451530 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411531 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101532 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:201533}
1534
[email protected]1e960032013-12-20 19:00:201535TEST_P(QuicHttpStreamTest, SendChunkedPostRequest) {
1536 SetRequest("POST", "/", DEFAULT_PRIORITY);
[email protected]c9e49a02013-02-26 05:56:471537 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:451538 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231539 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251540 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231541 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431542 std::string header = ConstructDataHeader(chunk_size);
Nick Harperc6cb7a612020-02-24 20:03:321543 if (version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411544 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231545 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1546 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1547 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjie Tangd5133972019-12-06 00:20:281548 AddWrite(ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin,
1549 {header + kUploadData}));
Renjief49758b2019-01-11 23:32:411550 } else {
1551 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231552 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1553 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1554 &spdy_request_headers_frame_length, {kUploadData}));
1555 AddWrite(ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin,
1556 kUploadData));
Renjief49758b2019-01-11 23:32:411557 }
1558
Renjie Tangcd594f32020-07-11 20:18:341559 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]c9e49a02013-02-26 05:56:471560 Initialize();
1561
Jeremy Roman0579ed62017-08-29 15:56:191562 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121563 auto* chunked_upload_stream =
1564 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1565 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
[email protected]c9e49a02013-02-26 05:56:471566
1567 request_.method = "POST";
rchcd379012017-04-12 21:53:321568 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121569 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071570 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201571 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]c9e49a02013-02-26 05:56:471572
Ali Beyada0b1a1c2022-04-08 20:08:141573 stream_->RegisterRequest(&request_);
1574 ASSERT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261575 net_log_with_source_,
1576 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021577 ASSERT_EQ(ERR_IO_PENDING,
1578 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]c9e49a02013-02-26 05:56:471579
rch97827ee2017-05-24 23:49:121580 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
robpercival214763f2016-07-01 23:27:011581 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]c9e49a02013-02-26 05:56:471582
1583 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041584 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]c9e49a02013-02-26 05:56:471585
1586 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281587 SetResponse("200", string());
sclittlec4dc1a32015-09-24 00:15:451588 size_t spdy_response_headers_frame_length;
1589 ProcessPacket(ConstructResponseHeadersPacket(
1590 2, !kFin, &spdy_response_headers_frame_length));
[email protected]c9e49a02013-02-26 05:56:471591
rchfb47f712017-05-21 03:24:001592 // The headers have already arrived.
1593 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]cadac622013-06-11 16:46:361594 ASSERT_TRUE(response_.headers.get());
[email protected]c9e49a02013-02-26 05:56:471595 EXPECT_EQ(200, response_.headers->response_code());
1596 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1597
1598 // Send the response body.
1599 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431600 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171601 ProcessPacket(
1602 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
[email protected]c9e49a02013-02-26 05:56:471603
1604 // Since the body has already arrived, this should return immediately.
1605 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1606 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1607 callback_.callback()));
1608
1609 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1610 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101611
1612 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451613 // headers and payload.
1614 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411615 strlen(kUploadData) * 2 + header.length() * 2),
sclittle1edeeb22015-09-02 20:46:101616 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451617 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411618 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101619 stream_->GetTotalReceivedBytes());
[email protected]c9e49a02013-02-26 05:56:471620}
1621
[email protected]16ba7742014-08-22 00:57:251622TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithFinalEmptyDataPacket) {
1623 SetRequest("POST", "/", DEFAULT_PRIORITY);
1624 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:451625 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231626 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251627 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231628 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431629 std::string header = ConstructDataHeader(chunk_size);
Renjief49758b2019-01-11 23:32:411630
Nick Harperc6cb7a612020-02-24 20:03:321631 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411632 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231633 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1634 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1635 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411636 } else {
1637 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231638 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1639 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1640 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411641 }
Renjie Tangaadb84b2019-08-31 01:00:231642 AddWrite(
1643 ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin, ""));
Renjie Tangcd594f32020-07-11 20:18:341644 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]16ba7742014-08-22 00:57:251645 Initialize();
1646
Jeremy Roman0579ed62017-08-29 15:56:191647 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121648 auto* chunked_upload_stream =
1649 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1650 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
[email protected]16ba7742014-08-22 00:57:251651
1652 request_.method = "POST";
rchcd379012017-04-12 21:53:321653 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121654 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071655 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201656 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]16ba7742014-08-22 00:57:251657
Ali Beyada0b1a1c2022-04-08 20:08:141658 stream_->RegisterRequest(&request_);
1659 ASSERT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261660 net_log_with_source_,
1661 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021662 ASSERT_EQ(ERR_IO_PENDING,
1663 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251664
rch97827ee2017-05-24 23:49:121665 chunked_upload_stream->AppendData(nullptr, 0, true);
robpercival214763f2016-07-01 23:27:011666 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]16ba7742014-08-22 00:57:251667
Renjie90e808e2019-01-24 07:24:041668 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]16ba7742014-08-22 00:57:251669
1670 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281671 SetResponse("200", string());
sclittlec4dc1a32015-09-24 00:15:451672 size_t spdy_response_headers_frame_length;
1673 ProcessPacket(ConstructResponseHeadersPacket(
1674 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251675
rchfb47f712017-05-21 03:24:001676 // The headers have already arrived.
1677 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]16ba7742014-08-22 00:57:251678 ASSERT_TRUE(response_.headers.get());
1679 EXPECT_EQ(200, response_.headers->response_code());
1680 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1681
1682 // Send the response body.
1683 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431684 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171685 ProcessPacket(
1686 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
[email protected]16ba7742014-08-22 00:57:251687
rchb27683c2015-07-29 23:53:501688 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251689 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1690 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1691 callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251692 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1693 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101694
1695 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451696 // headers and payload.
1697 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411698 strlen(kUploadData) + header.length()),
sclittle1edeeb22015-09-02 20:46:101699 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451700 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411701 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101702 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251703}
1704
1705TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithOneEmptyDataPacket) {
1706 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451707 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231708 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251709 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231710 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371711 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231712 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1713 kIncludeVersion, !kFin, DEFAULT_PRIORITY,
1714 &spdy_request_headers_frame_length));
1715 AddWrite(
1716 ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin, ""));
Renjie Tangcd594f32020-07-11 20:18:341717 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]16ba7742014-08-22 00:57:251718 Initialize();
1719
Jeremy Roman0579ed62017-08-29 15:56:191720 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121721 auto* chunked_upload_stream =
1722 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
[email protected]16ba7742014-08-22 00:57:251723
1724 request_.method = "POST";
rchcd379012017-04-12 21:53:321725 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121726 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071727 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201728 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]16ba7742014-08-22 00:57:251729
Ali Beyada0b1a1c2022-04-08 20:08:141730 stream_->RegisterRequest(&request_);
1731 ASSERT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261732 net_log_with_source_,
1733 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021734 ASSERT_EQ(ERR_IO_PENDING,
1735 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251736
rch97827ee2017-05-24 23:49:121737 chunked_upload_stream->AppendData(nullptr, 0, true);
robpercival214763f2016-07-01 23:27:011738 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]16ba7742014-08-22 00:57:251739
Renjie90e808e2019-01-24 07:24:041740 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]16ba7742014-08-22 00:57:251741
1742 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281743 SetResponse("200", string());
sclittlec4dc1a32015-09-24 00:15:451744 size_t spdy_response_headers_frame_length;
1745 ProcessPacket(ConstructResponseHeadersPacket(
1746 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251747
rchfb47f712017-05-21 03:24:001748 // The headers have already arrived.
1749 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]16ba7742014-08-22 00:57:251750 ASSERT_TRUE(response_.headers.get());
1751 EXPECT_EQ(200, response_.headers->response_code());
1752 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1753
1754 // Send the response body.
1755 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431756 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171757 ProcessPacket(
1758 ConstructServerDataPacket(3, false, kFin, header + kResponseBody));
[email protected]16ba7742014-08-22 00:57:251759
rchb27683c2015-07-29 23:53:501760 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251761 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1762 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1763 callback_.callback()));
1764
1765 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1766 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101767
1768 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451769 // headers and payload.
1770 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1771 stream_->GetTotalSentBytes());
1772 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411773 strlen(kResponseBody) + header.length()),
sclittle1edeeb22015-09-02 20:46:101774 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251775}
1776
Bence Békye3c6f122020-05-08 01:09:471777TEST_P(QuicHttpStreamTest, SendChunkedPostRequestAbortedByResetStream) {
1778 SetRequest("POST", "/", DEFAULT_PRIORITY);
1779 size_t chunk_size = strlen(kUploadData);
1780 size_t spdy_request_headers_frame_length;
1781 int packet_number = 1;
1782
1783 if (version_.UsesHttp3()) {
1784 AddWrite(ConstructInitialSettingsPacket(packet_number++));
1785 }
1786
1787 std::string header = ConstructDataHeader(chunk_size);
1788 if (version_.HasIetfQuicFrames()) {
1789 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1790 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1791 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1792 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjie Tangcd594f32020-07-11 20:18:341793 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
Fan Yang8d4177792021-07-16 17:48:531794 AddWrite(client_maker_.MakeAckAndRstPacket(
1795 packet_number++, true, stream_id_, quic::QUIC_STREAM_NO_ERROR, 4, 1,
Renjie Tangcd594f32020-07-11 20:18:341796 /* include_stop_sending_if_v99 = */ false));
Bence Békye3c6f122020-05-08 01:09:471797 } else {
1798 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1799 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1800 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1801 &spdy_request_headers_frame_length, {kUploadData}));
Renjie Tangcd594f32020-07-11 20:18:341802 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
Bence Békye3c6f122020-05-08 01:09:471803 AddWrite(client_maker_.MakeAckAndRstPacket(
1804 packet_number++,
1805 /* include_version = */ false, stream_id_,
Renjie Tangcd594f32020-07-11 20:18:341806 quic::QUIC_RST_ACKNOWLEDGEMENT, 4, 1,
Bence Békye3c6f122020-05-08 01:09:471807 /* include_stop_sending_if_v99 = */ false));
1808 }
1809
1810 Initialize();
1811
1812 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
1813 auto* chunked_upload_stream =
1814 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1815 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
1816
1817 request_.method = "POST";
1818 request_.url = GURL("https://www.example.org/");
1819 request_.upload_data_stream = upload_data_stream_.get();
1820 ASSERT_THAT(request_.upload_data_stream->Init(
1821 TestCompletionCallback().callback(), NetLogWithSource()),
1822 IsOk());
Ali Beyada0b1a1c2022-04-08 20:08:141823 stream_->RegisterRequest(&request_);
Matt Reichhoff0049a0b72021-10-20 20:44:261824 ASSERT_THAT(
Ali Beyada0b1a1c2022-04-08 20:08:141825 stream_->InitializeStream(false, DEFAULT_PRIORITY, net_log_with_source_,
1826 callback_.callback()),
Matt Reichhoff0049a0b72021-10-20 20:44:261827 IsOk());
Bence Békye3c6f122020-05-08 01:09:471828 ASSERT_THAT(stream_->SendRequest(headers_, &response_, callback_.callback()),
1829 IsError(ERR_IO_PENDING));
1830
1831 // Ack both packets in the request.
1832 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
1833
1834 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281835 SetResponse("200", string());
Bence Békye3c6f122020-05-08 01:09:471836 size_t spdy_response_headers_frame_length;
1837 ProcessPacket(ConstructResponseHeadersPacket(
1838 2, !kFin, &spdy_response_headers_frame_length));
1839
1840 // Send the response body.
1841 const char kResponseBody[] = "Hello world!";
1842 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
1843 ProcessPacket(
1844 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
1845
Bence Béky050ec6d2021-02-25 22:07:051846 if (version_.HasIetfQuicFrames()) {
1847 // In IETF QUIC, the server uses a STOP_SENDING frame to notify the client
1848 // that it does not need any further data to fully process the request.
1849 ProcessPacket(server_maker_.MakeStopSendingPacket(
1850 4, /* include_version = */ false, stream_id_,
1851 quic::QUIC_STREAM_NO_ERROR));
1852 } else {
1853 // Server resets stream with H3_NO_ERROR before request body is complete.
1854 ProcessPacket(server_maker_.MakeRstPacket(4, /* include_version = */ false,
1855 stream_id_,
1856 quic::QUIC_STREAM_NO_ERROR));
1857 }
Bence Békye3c6f122020-05-08 01:09:471858
1859 // Finish feeding request body to QuicHttpStream. Data will be discarded.
1860 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1861 EXPECT_THAT(callback_.WaitForResult(), IsOk());
1862
1863 // Verify response.
1864 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
1865 ASSERT_TRUE(response_.headers.get());
1866 EXPECT_EQ(200, response_.headers->response_code());
1867 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1868 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1869 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1870 callback_.callback()));
1871 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1872 EXPECT_TRUE(AtEof());
1873
1874 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
1875 // headers and payload.
1876 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
1877 strlen(kUploadData) + header.length()),
1878 stream_->GetTotalSentBytes());
1879 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1880 strlen(kResponseBody) + header2.length()),
1881 stream_->GetTotalReceivedBytes());
1882}
1883
[email protected]1e960032013-12-20 19:00:201884TEST_P(QuicHttpStreamTest, DestroyedEarly) {
1885 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451886 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231887 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251888 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231889 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371890 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231891 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1892 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1893 &spdy_request_headers_frame_length));
1894 AddWrite(ConstructAckAndRstStreamPacket(packet_number++));
[email protected]63534512012-12-23 18:49:001895 Initialize();
1896
1897 request_.method = "GET";
rchcd379012017-04-12 21:53:321898 request_.url = GURL("https://www.example.org/");
[email protected]63534512012-12-23 18:49:001899
Ali Beyada0b1a1c2022-04-08 20:08:141900 stream_->RegisterRequest(&request_);
1901 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:261902 net_log_with_source_,
1903 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021904 EXPECT_EQ(OK,
1905 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]63534512012-12-23 18:49:001906
1907 // Ack the request.
Renjie90e808e2019-01-24 07:24:041908 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
rchfb47f712017-05-21 03:24:001909 EXPECT_THAT(stream_->ReadResponseHeaders(
Yannic Bonenberger3c96beb2019-09-03 20:41:371910 base::BindOnce(&QuicHttpStreamTest::CloseStream,
1911 base::Unretained(this), stream_.get())),
robpercival214763f2016-07-01 23:27:011912 IsError(ERR_IO_PENDING));
[email protected]63534512012-12-23 18:49:001913
1914 // Send the response with a body.
Kenichi Ishibashif8634ab2021-03-16 23:41:281915 SetResponse("404", "hello world!");
[email protected]63534512012-12-23 18:49:001916 // In the course of processing this packet, the QuicHttpStream close itself.
rchfb47f712017-05-21 03:24:001917 size_t response_size = 0;
rch1bcfddf22017-06-03 00:26:291918 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin, &response_size));
[email protected]63534512012-12-23 18:49:001919
fdoray92e35a72016-06-10 15:54:551920 base::RunLoop().RunUntilIdle();
rchb27683c2015-07-29 23:53:501921
[email protected]63534512012-12-23 18:49:001922 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101923
1924 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451925 // headers and payload.
1926 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1927 stream_->GetTotalSentBytes());
rchfb47f712017-05-21 03:24:001928 // The stream was closed after receiving the headers.
1929 EXPECT_EQ(static_cast<int64_t>(response_size),
1930 stream_->GetTotalReceivedBytes());
[email protected]63534512012-12-23 18:49:001931}
1932
[email protected]1e960032013-12-20 19:00:201933TEST_P(QuicHttpStreamTest, Priority) {
1934 SetRequest("GET", "/", MEDIUM);
sclittlec4dc1a32015-09-24 00:15:451935 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231936 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251937 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231938 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371939 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231940 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1941 kIncludeVersion, kFin, MEDIUM, &spdy_request_headers_frame_length));
[email protected]24e5bc52013-09-18 15:36:581942 Initialize();
1943
1944 request_.method = "GET";
rchcd379012017-04-12 21:53:321945 request_.url = GURL("https://www.example.org/");
[email protected]24e5bc52013-09-18 15:36:581946
Ali Beyada0b1a1c2022-04-08 20:08:141947 stream_->RegisterRequest(&request_);
1948 EXPECT_EQ(OK, stream_->InitializeStream(true, MEDIUM, net_log_with_source_,
Matt Reichhoff0049a0b72021-10-20 20:44:261949 callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581950
rjshaded5ced072015-12-18 19:26:021951 EXPECT_EQ(OK,
1952 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581953
[email protected]24e5bc52013-09-18 15:36:581954 // Ack the request.
Renjie90e808e2019-01-24 07:24:041955 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011956 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1957 IsError(ERR_IO_PENDING));
[email protected]24e5bc52013-09-18 15:36:581958
1959 // Send the response with a body.
Kenichi Ishibashif8634ab2021-03-16 23:41:281960 SetResponse("404", "hello world!");
rchfb47f712017-05-21 03:24:001961 size_t response_size = 0;
1962 ProcessPacket(ConstructResponseHeadersPacket(2, kFin, &response_size));
[email protected]24e5bc52013-09-18 15:36:581963
rchfb47f712017-05-21 03:24:001964 EXPECT_EQ(OK, callback_.WaitForResult());
rchb27683c2015-07-29 23:53:501965
[email protected]24e5bc52013-09-18 15:36:581966 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101967
1968 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451969 // headers and payload.
1970 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1971 stream_->GetTotalSentBytes());
rchfb47f712017-05-21 03:24:001972 EXPECT_EQ(static_cast<int64_t>(response_size),
1973 stream_->GetTotalReceivedBytes());
[email protected]24e5bc52013-09-18 15:36:581974}
1975
xunjieli8dff50b2016-07-22 14:19:061976TEST_P(QuicHttpStreamTest, SessionClosedDuringDoLoop) {
1977 SetRequest("POST", "/", DEFAULT_PRIORITY);
1978 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231979 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251980 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231981 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431982 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:321983 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411984 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231985 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1986 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1987 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411988 } else {
1989 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231990 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1991 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1992 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411993 }
1994
xunjieli8dff50b2016-07-22 14:19:061995 // Second data write will result in a synchronous failure which will close
1996 // the session.
1997 AddWrite(SYNCHRONOUS, ERR_FAILED);
1998 Initialize();
1999
Jeremy Roman0579ed62017-08-29 15:56:192000 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:122001 auto* chunked_upload_stream =
2002 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
xunjieli8dff50b2016-07-22 14:19:062003
2004 request_.method = "POST";
rchcd379012017-04-12 21:53:322005 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122006 request_.upload_data_stream = upload_data_stream_.get();
xunjieli8dff50b2016-07-22 14:19:062007 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202008 TestCompletionCallback().callback(), NetLogWithSource()));
xunjieli8dff50b2016-07-22 14:19:062009
2010 size_t chunk_size = strlen(kUploadData);
rch97827ee2017-05-24 23:49:122011 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
Ali Beyada0b1a1c2022-04-08 20:08:142012 stream_->RegisterRequest(&request_);
2013 ASSERT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262014 net_log_with_source_,
2015 callback_.callback()));
xunjieli8dff50b2016-07-22 14:19:062016 QuicHttpStream* stream = stream_.get();
2017 DeleteStreamCallback delete_stream_callback(std::move(stream_));
2018 // SendRequest() completes asynchronously after the final chunk is added.
Yixin Wange7ecc472018-03-06 19:00:252019 // Error does not surface yet since packet write is triggered by a packet
2020 // flusher that tries to bundle request body writes.
xunjieli8dff50b2016-07-22 14:19:062021 ASSERT_EQ(ERR_IO_PENDING,
2022 stream->SendRequest(headers_, &response_, callback_.callback()));
rch97827ee2017-05-24 23:49:122023 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
xunjieli8dff50b2016-07-22 14:19:062024 int rv = callback_.WaitForResult();
Yixin Wange7ecc472018-03-06 19:00:252025 EXPECT_EQ(OK, rv);
2026 // Error will be surfaced once an attempt to read the response occurs.
2027 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
2028 stream->ReadResponseHeaders(callback_.callback()));
xunjieli8dff50b2016-07-22 14:19:062029}
2030
rtenneti15656ae2016-01-23 03:05:032031TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersComplete) {
2032 SetRequest("POST", "/", DEFAULT_PRIORITY);
Victor Vasiliev7da08172019-10-14 06:04:252033 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232034 AddWrite(ConstructInitialSettingsPacket());
rtenneti15656ae2016-01-23 03:05:032035 AddWrite(SYNCHRONOUS, ERR_FAILED);
2036 Initialize();
2037
Jeremy Roman0579ed62017-08-29 15:56:192038 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
Yixin Wange7ecc472018-03-06 19:00:252039 auto* chunked_upload_stream =
2040 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
rtenneti15656ae2016-01-23 03:05:032041
2042 request_.method = "POST";
rchcd379012017-04-12 21:53:322043 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122044 request_.upload_data_stream = upload_data_stream_.get();
rtenneti15656ae2016-01-23 03:05:032045 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202046 TestCompletionCallback().callback(), NetLogWithSource()));
rtenneti15656ae2016-01-23 03:05:032047
Ali Beyada0b1a1c2022-04-08 20:08:142048 stream_->RegisterRequest(&request_);
2049 ASSERT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262050 net_log_with_source_,
2051 callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252052 ASSERT_EQ(ERR_IO_PENDING,
rtenneti15656ae2016-01-23 03:05:032053 stream_->SendRequest(headers_, &response_, callback_.callback()));
mmenkeffff3642017-06-15 17:37:242054
Yixin Wange7ecc472018-03-06 19:00:252055 // Error will be surfaced once |upload_data_stream| triggers the next write.
2056 size_t chunk_size = strlen(kUploadData);
2057 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2058 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR, callback_.WaitForResult());
2059
2060 EXPECT_LE(0, stream_->GetTotalSentBytes());
2061 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2062}
2063
2064TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersCompleteReadResponse) {
2065 SetRequest("POST", "/", DEFAULT_PRIORITY);
Victor Vasiliev7da08172019-10-14 06:04:252066 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232067 AddWrite(ConstructInitialSettingsPacket());
Yixin Wange7ecc472018-03-06 19:00:252068 AddWrite(SYNCHRONOUS, ERR_FAILED);
2069 Initialize();
2070
2071 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
2072 auto* chunked_upload_stream =
2073 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
2074
2075 request_.method = "POST";
2076 request_.url = GURL("https://www.example.org/");
2077 request_.upload_data_stream = upload_data_stream_.get();
2078
2079 size_t chunk_size = strlen(kUploadData);
2080 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2081
2082 ASSERT_EQ(OK, request_.upload_data_stream->Init(
2083 TestCompletionCallback().callback(), NetLogWithSource()));
2084
Ali Beyada0b1a1c2022-04-08 20:08:142085 stream_->RegisterRequest(&request_);
2086 ASSERT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262087 net_log_with_source_,
2088 callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252089 ASSERT_EQ(OK,
2090 stream_->SendRequest(headers_, &response_, callback_.callback()));
2091
2092 // Error will be surfaced once an attempt to read the response occurs.
2093 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
2094 stream_->ReadResponseHeaders(callback_.callback()));
2095
mmenkeffff3642017-06-15 17:37:242096 EXPECT_LE(0, stream_->GetTotalSentBytes());
2097 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rtenneti15656ae2016-01-23 03:05:032098}
2099
2100TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBodyComplete) {
2101 SetRequest("POST", "/", DEFAULT_PRIORITY);
2102 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232103 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252104 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232105 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:372106 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:232107 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2108 kIncludeVersion, !kFin, DEFAULT_PRIORITY,
2109 &spdy_request_headers_frame_length));
rtenneti15656ae2016-01-23 03:05:032110 AddWrite(SYNCHRONOUS, ERR_FAILED);
2111 Initialize();
2112
Jeremy Roman0579ed62017-08-29 15:56:192113 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:122114 auto* chunked_upload_stream =
2115 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
rtenneti15656ae2016-01-23 03:05:032116
2117 request_.method = "POST";
rchcd379012017-04-12 21:53:322118 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122119 request_.upload_data_stream = upload_data_stream_.get();
rtenneti15656ae2016-01-23 03:05:032120 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202121 TestCompletionCallback().callback(), NetLogWithSource()));
rtenneti15656ae2016-01-23 03:05:032122
Ali Beyada0b1a1c2022-04-08 20:08:142123 stream_->RegisterRequest(&request_);
2124 ASSERT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262125 net_log_with_source_,
2126 callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252127 ASSERT_EQ(ERR_IO_PENDING,
rtenneti15656ae2016-01-23 03:05:032128 stream_->SendRequest(headers_, &response_, callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252129
2130 size_t chunk_size = strlen(kUploadData);
2131 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2132 // Error does not surface yet since packet write is triggered by a packet
2133 // flusher that tries to bundle request body writes.
2134 ASSERT_EQ(OK, callback_.WaitForResult());
2135 // Error will be surfaced once an attempt to read the response occurs.
2136 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
2137 stream_->ReadResponseHeaders(callback_.callback()));
2138
2139 EXPECT_LE(0, stream_->GetTotalSentBytes());
2140 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2141}
2142
2143TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBundledBodyComplete) {
2144 SetRequest("POST", "/", DEFAULT_PRIORITY);
2145 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232146 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252147 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232148 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:432149 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:322150 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:412151 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:232152 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2153 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
2154 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:412155 } else {
2156 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:232157 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2158 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
2159 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:412160 }
2161
Yixin Wange7ecc472018-03-06 19:00:252162 AddWrite(SYNCHRONOUS, ERR_FAILED);
2163 Initialize();
2164
2165 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
2166 auto* chunked_upload_stream =
2167 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
2168
2169 request_.method = "POST";
2170 request_.url = GURL("https://www.example.org/");
2171 request_.upload_data_stream = upload_data_stream_.get();
2172
2173 size_t chunk_size = strlen(kUploadData);
2174 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
2175
2176 ASSERT_EQ(OK, request_.upload_data_stream->Init(
2177 TestCompletionCallback().callback(), NetLogWithSource()));
2178
Ali Beyada0b1a1c2022-04-08 20:08:142179 stream_->RegisterRequest(&request_);
2180 ASSERT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262181 net_log_with_source_,
2182 callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252183 ASSERT_EQ(ERR_IO_PENDING,
2184 stream_->SendRequest(headers_, &response_, callback_.callback()));
2185
2186 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2187
2188 // Error does not surface yet since packet write is triggered by a packet
2189 // flusher that tries to bundle request body writes.
2190 ASSERT_EQ(OK, callback_.WaitForResult());
2191 // Error will be surfaced once an attempt to read the response occurs.
2192 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
2193 stream_->ReadResponseHeaders(callback_.callback()));
2194
2195 EXPECT_LE(0, stream_->GetTotalSentBytes());
2196 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rtenneti15656ae2016-01-23 03:05:032197}
2198
ckrasic3865ee0f2016-02-29 22:04:562199TEST_P(QuicHttpStreamTest, ServerPushGetRequest) {
2200 SetRequest("GET", "/", DEFAULT_PRIORITY);
2201 Initialize();
2202
Bin Wue8408792021-08-24 23:25:162203 // Server push is not supported in HTTP/3.
2204 if (version_.UsesHttp3())
2205 return;
2206
ckrasic3865ee0f2016-02-29 22:04:562207 // Initialize the first stream, for receiving the promise on.
2208 request_.method = "GET";
rchcd379012017-04-12 21:53:322209 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562210
Ali Beyada0b1a1c2022-04-08 20:08:142211 stream_->RegisterRequest(&request_);
2212 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262213 net_log_with_source_,
2214 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232215 ASSERT_EQ(OK,
2216 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562217
2218 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2219 // packet, but does it matter?
2220 ReceivePromise(promise_id_);
2221 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2222
2223 request_.url = GURL(promise_url_);
2224
2225 // Make the second stream that will exercise the first step of the
2226 // server push rendezvous mechanism.
Ali Beyada0b1a1c2022-04-08 20:08:142227 promised_stream_->RegisterRequest(&request_);
2228 EXPECT_EQ(OK, promised_stream_->InitializeStream(true, DEFAULT_PRIORITY,
2229 net_log_with_source_,
2230 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562231
2232 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252233 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562234 size_t spdy_response_headers_frame_length;
2235 ProcessPacket(InnerConstructResponseHeadersPacket(
2236 1, promise_id_, false, &spdy_response_headers_frame_length));
2237
2238 // Receive the promised response body.
2239 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432240 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172241 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2242 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562243
2244 // Now sending a matching request will have successful rendezvous
2245 // with the promised stream.
Ryan Hamiltona1d1f4a2019-06-26 14:43:042246 ASSERT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
ckrasic3865ee0f2016-02-29 22:04:562247 callback_.callback()));
2248
2249 EXPECT_EQ(
2250 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2251 ->id(),
2252 promise_id_);
2253
2254 // The headers will be immediately available.
robpercival214763f2016-07-01 23:27:012255 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2256 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562257
2258 // As will be the body.
2259 EXPECT_EQ(
2260 static_cast<int>(strlen(kResponseBody)),
2261 promised_stream_->ReadResponseBody(
2262 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2263 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2264 EXPECT_TRUE(AtEof());
2265
ckrasic3865ee0f2016-02-29 22:04:562266 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2267 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412268 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562269 promised_stream_->GetTotalReceivedBytes());
2270}
2271
2272TEST_P(QuicHttpStreamTest, ServerPushGetRequestSlowResponse) {
2273 SetRequest("GET", "/", DEFAULT_PRIORITY);
2274 Initialize();
2275
Bin Wue8408792021-08-24 23:25:162276 // Server push is not supported in HTTP/3.
2277 if (version_.UsesHttp3())
2278 return;
2279
ckrasic3865ee0f2016-02-29 22:04:562280 // Initialize the first stream, for receiving the promise on.
2281 request_.method = "GET";
rchcd379012017-04-12 21:53:322282 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562283
Ali Beyada0b1a1c2022-04-08 20:08:142284 stream_->RegisterRequest(&request_);
2285 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262286 net_log_with_source_,
2287 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232288 ASSERT_EQ(OK,
2289 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562290
2291 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2292 // packet, but does it matter?
2293 ReceivePromise(promise_id_);
2294 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2295
2296 request_.url = GURL(promise_url_);
2297
2298 // Make the second stream that will exercise the first step of the
2299 // server push rendezvous mechanism.
Ali Beyada0b1a1c2022-04-08 20:08:142300 promised_stream_->RegisterRequest(&request_);
2301 EXPECT_EQ(OK, promised_stream_->InitializeStream(true, DEFAULT_PRIORITY,
2302 net_log_with_source_,
2303 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562304
2305 // Now sending a matching request will rendezvous with the promised
2306 // stream, but pending secondary validation.
2307 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2308 headers_, &response_, callback_.callback()));
2309
2310 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252311 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562312 size_t spdy_response_headers_frame_length;
2313 ProcessPacket(InnerConstructResponseHeadersPacket(
2314 1, promise_id_, false, &spdy_response_headers_frame_length));
2315
2316 // Receive the promised response body.
2317 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432318 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172319 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2320 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562321
fdoray92e35a72016-06-10 15:54:552322 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562323
2324 // Rendezvous should have succeeded now, so the promised stream
2325 // should point at our push stream, and we should be able read
2326 // headers and data from it.
robpercival214763f2016-07-01 23:27:012327 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562328
2329 EXPECT_EQ(
2330 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2331 ->id(),
2332 promise_id_);
2333
robpercival214763f2016-07-01 23:27:012334 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2335 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562336
2337 EXPECT_EQ(
2338 static_cast<int>(strlen(kResponseBody)),
2339 promised_stream_->ReadResponseBody(
2340 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2341
2342 // Callback should return
2343 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2344 EXPECT_TRUE(AtEof());
2345
ckrasic3865ee0f2016-02-29 22:04:562346 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2347 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412348 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562349 promised_stream_->GetTotalReceivedBytes());
2350}
2351
ckrasic2c63f9b2016-08-16 23:54:072352// Verify fix for crbug.com/637349
2353TEST_P(QuicHttpStreamTest, ServerPushCancelHttpStreamBeforeResponse) {
2354 SetRequest("GET", "/", DEFAULT_PRIORITY);
2355 Initialize();
2356
Bin Wue8408792021-08-24 23:25:162357 // Server push is not supported in HTTP/3.
2358 if (version_.UsesHttp3())
2359 return;
2360
ckrasic2c63f9b2016-08-16 23:54:072361 // Initialize the first stream, for receiving the promise on.
2362 request_.method = "GET";
rchcd379012017-04-12 21:53:322363 request_.url = GURL("https://www.example.org/");
ckrasic2c63f9b2016-08-16 23:54:072364
Ali Beyada0b1a1c2022-04-08 20:08:142365 stream_->RegisterRequest(&request_);
2366 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262367 net_log_with_source_,
2368 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232369 ASSERT_EQ(OK,
2370 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic2c63f9b2016-08-16 23:54:072371
2372 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2373 // packet, but does it matter?
2374 ReceivePromise(promise_id_);
2375 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2376
2377 request_.url = GURL(promise_url_);
2378
2379 // Make the second stream that will exercise the first step of the
2380 // server push rendezvous mechanism.
Ali Beyada0b1a1c2022-04-08 20:08:142381 promised_stream_->RegisterRequest(&request_);
2382 EXPECT_EQ(OK, promised_stream_->InitializeStream(true, DEFAULT_PRIORITY,
2383 net_log_with_source_,
2384 callback_.callback()));
ckrasic2c63f9b2016-08-16 23:54:072385
2386 // Now sending a matching request will rendezvous with the promised
2387 // stream, but pending secondary validation.
2388 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2389 headers_, &response_, callback_.callback()));
2390
2391 base::RunLoop().RunUntilIdle();
2392
2393 // Cause of FinalValidation() crash as per bug.
2394 promised_stream_.reset();
2395
2396 // Receive the promised response headers.
2397 response_headers_ = promised_response_.Clone();
2398 size_t spdy_response_headers_frame_length;
2399 ProcessPacket(InnerConstructResponseHeadersPacket(
2400 1, promise_id_, false, &spdy_response_headers_frame_length));
2401}
2402
ckrasic3865ee0f2016-02-29 22:04:562403TEST_P(QuicHttpStreamTest, ServerPushCrossOriginOK) {
2404 SetRequest("GET", "/", DEFAULT_PRIORITY);
2405 Initialize();
2406
Bin Wue8408792021-08-24 23:25:162407 // Server push is not supported in HTTP/3.
2408 if (version_.UsesHttp3())
2409 return;
2410
ckrasic3865ee0f2016-02-29 22:04:562411 // Initialize the first stream, for receiving the promise on.
2412 request_.method = "GET";
rchcd379012017-04-12 21:53:322413 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562414
Ali Beyada0b1a1c2022-04-08 20:08:142415 stream_->RegisterRequest(&request_);
2416 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262417 net_log_with_source_,
2418 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232419 ASSERT_EQ(OK,
2420 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562421
2422 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2423 // packet, but does it matter?
2424
2425 push_promise_[":authority"] = "mail.example.org";
David Schinazi3f7465c2019-07-12 01:57:052426 promise_url_ =
2427 quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
ckrasic3865ee0f2016-02-29 22:04:562428
2429 ReceivePromise(promise_id_);
2430 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2431
2432 request_.url = GURL(promise_url_);
2433
2434 // Make the second stream that will exercise the first step of the
2435 // server push rendezvous mechanism.
Ali Beyada0b1a1c2022-04-08 20:08:142436 promised_stream_->RegisterRequest(&request_);
2437 EXPECT_EQ(OK, promised_stream_->InitializeStream(true, DEFAULT_PRIORITY,
2438 net_log_with_source_,
2439 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562440
2441 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252442 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562443 size_t spdy_response_headers_frame_length;
2444 ProcessPacket(InnerConstructResponseHeadersPacket(
2445 1, promise_id_, false, &spdy_response_headers_frame_length));
2446
2447 // Receive the promised response body.
2448 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432449 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172450 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2451 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562452
2453 // Now sending a matching request will have successful rendezvous
2454 // with the promised stream.
2455 EXPECT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
2456 callback_.callback()));
2457
2458 EXPECT_EQ(
2459 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2460 ->id(),
2461 promise_id_);
2462
2463 // The headers will be immediately available.
robpercival214763f2016-07-01 23:27:012464 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2465 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562466
2467 // As will be the body.
2468 EXPECT_EQ(
2469 static_cast<int>(strlen(kResponseBody)),
2470 promised_stream_->ReadResponseBody(
2471 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2472 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2473 EXPECT_TRUE(AtEof());
2474
ckrasic3865ee0f2016-02-29 22:04:562475 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2476 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412477 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562478 promised_stream_->GetTotalReceivedBytes());
2479}
2480
2481TEST_P(QuicHttpStreamTest, ServerPushCrossOriginFail) {
2482 SetRequest("GET", "/", DEFAULT_PRIORITY);
2483 Initialize();
2484
Bin Wue8408792021-08-24 23:25:162485 // Server push is not supported in HTTP/3.
2486 if (version_.UsesHttp3())
2487 return;
2488
ckrasic3865ee0f2016-02-29 22:04:562489 // Initialize the first stream, for receiving the promise on.
2490 request_.method = "GET";
rchcd379012017-04-12 21:53:322491 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562492
Ali Beyada0b1a1c2022-04-08 20:08:142493 stream_->RegisterRequest(&request_);
2494 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262495 net_log_with_source_,
2496 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232497 ASSERT_EQ(OK,
2498 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562499
2500 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2501 // packet, but does it matter?
2502 push_promise_[":authority"] = "www.notexample.org";
David Schinazi3f7465c2019-07-12 01:57:052503 promise_url_ =
2504 quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
ckrasic3865ee0f2016-02-29 22:04:562505
2506 ReceivePromise(promise_id_);
2507 // The promise will have been rejected because the cert doesn't
2508 // match.
2509 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
2510}
2511
2512TEST_P(QuicHttpStreamTest, ServerPushVaryCheckOK) {
2513 SetRequest("GET", "/", DEFAULT_PRIORITY);
2514 Initialize();
2515
Bin Wue8408792021-08-24 23:25:162516 // Server push is not supported in HTTP/3.
2517 if (version_.UsesHttp3())
2518 return;
2519
ckrasic3865ee0f2016-02-29 22:04:562520 // Initialize the first stream, for receiving the promise on.
2521 request_.method = "GET";
rchcd379012017-04-12 21:53:322522 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562523
Ali Beyada0b1a1c2022-04-08 20:08:142524 stream_->RegisterRequest(&request_);
2525 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262526 net_log_with_source_,
2527 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232528 ASSERT_EQ(OK,
2529 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562530
2531 push_promise_["accept-encoding"] = "gzip";
ckrasic3865ee0f2016-02-29 22:04:562532
2533 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2534 // packet, but does it matter?
2535 ReceivePromise(promise_id_);
2536 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2537
2538 request_.url = GURL(promise_url_);
2539
2540 // Make the second stream that will exercise the first step of the
2541 // server push rendezvous mechanism.
Ali Beyada0b1a1c2022-04-08 20:08:142542 promised_stream_->RegisterRequest(&request_);
2543 EXPECT_EQ(OK, promised_stream_->InitializeStream(true, DEFAULT_PRIORITY,
2544 net_log_with_source_,
2545 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562546
2547 headers_.SetHeader("accept-encoding", "gzip");
2548
2549 // Now sending a matching request will rendezvous with the promised
2550 // stream, but pending secondary validation.
2551 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2552 headers_, &response_, callback_.callback()));
2553
2554 // Receive the promised response headers.
2555 promised_response_["vary"] = "accept-encoding";
bnc94893a72016-06-30 13:45:252556 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562557 size_t spdy_response_headers_frame_length;
2558 ProcessPacket(InnerConstructResponseHeadersPacket(
2559 1, promise_id_, false, &spdy_response_headers_frame_length));
2560
2561 // Receive the promised response body.
2562 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432563 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172564 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2565 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562566
fdoray92e35a72016-06-10 15:54:552567 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562568
2569 // Rendezvous should have succeeded now, so the promised stream
2570 // should point at our push stream, and we should be able read
2571 // headers and data from it.
robpercival214763f2016-07-01 23:27:012572 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562573
2574 EXPECT_EQ(
2575 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2576 ->id(),
2577 promise_id_);
2578
robpercival214763f2016-07-01 23:27:012579 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2580 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562581
2582 EXPECT_EQ(
2583 static_cast<int>(strlen(kResponseBody)),
2584 promised_stream_->ReadResponseBody(
2585 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2586
2587 // Callback should return
2588 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2589 EXPECT_TRUE(AtEof());
2590
ckrasic3865ee0f2016-02-29 22:04:562591 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2592 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412593 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562594 promised_stream_->GetTotalReceivedBytes());
2595}
2596
2597TEST_P(QuicHttpStreamTest, ServerPushVaryCheckFail) {
2598 SetRequest("GET", "/", DEFAULT_PRIORITY);
2599 request_headers_[":scheme"] = "https";
2600 request_headers_[":path"] = "/bar";
2601 request_headers_["accept-encoding"] = "sdch";
2602
ckrasic3865ee0f2016-02-29 22:04:562603 Initialize();
2604
Bin Wue8408792021-08-24 23:25:162605 // Server push is not supported in HTTP/3.
2606 if (version_.UsesHttp3())
2607 return;
2608
ckrasic3865ee0f2016-02-29 22:04:562609 // Initialize the first stream, for receiving the promise on.
2610 request_.method = "GET";
rchcd379012017-04-12 21:53:322611 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562612
Ali Beyada0b1a1c2022-04-08 20:08:142613 stream_->RegisterRequest(&request_);
2614 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262615 net_log_with_source_,
2616 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232617 ASSERT_EQ(OK,
2618 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562619
2620 push_promise_["accept-encoding"] = "gzip";
ckrasic3865ee0f2016-02-29 22:04:562621
2622 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2623 // packet, but does it matter?
2624 ReceivePromise(promise_id_);
2625 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2626
2627 request_.url = GURL(promise_url_);
2628
2629 // Make the second stream that will exercise the first step of the
2630 // server push rendezvous mechanism.
Ali Beyada0b1a1c2022-04-08 20:08:142631 promised_stream_->RegisterRequest(&request_);
2632 EXPECT_EQ(OK, promised_stream_->InitializeStream(true, DEFAULT_PRIORITY,
2633 net_log_with_source_,
2634 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562635
2636 headers_.SetHeader("accept-encoding", "sdch");
2637
2638 // Now sending a matching request will rendezvous with the promised
2639 // stream, but pending secondary validation.
2640 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2641 headers_, &response_, callback_.callback()));
2642
2643 // Receive the promised response headers.
2644 promised_response_["vary"] = "accept-encoding";
bnc94893a72016-06-30 13:45:252645 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562646 size_t spdy_response_headers_frame_length;
2647 ProcessPacket(InnerConstructResponseHeadersPacket(
2648 1, promise_id_, false, &spdy_response_headers_frame_length));
2649
fdoray92e35a72016-06-10 15:54:552650 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562651
2652 // Rendezvous should have failed due to vary mismatch, so the
2653 // promised stream should have been aborted, and instead we have a
2654 // new, regular client initiated stream.
robpercival214763f2016-07-01 23:27:012655 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562656
2657 // Not a server-initiated stream.
2658 EXPECT_NE(
2659 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2660 ->id(),
2661 promise_id_);
2662
2663 // Instead, a new client-initiated stream.
2664 EXPECT_EQ(
2665 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2666 ->id(),
Nick Harper23290b82019-05-02 00:02:562667 stream_id_ + quic::QuicUtils::StreamIdDelta(version_.transport_version));
ckrasic3865ee0f2016-02-29 22:04:562668
2669 // After rendezvous failure, the push stream has been cancelled.
2670 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
2671
2672 // The rest of the test verifies that the retried as
2673 // client-initiated version of |promised_stream_| works as intended.
2674
2675 // Ack the request.
Renjie90e808e2019-01-24 07:24:042676 ProcessPacket(ConstructServerAckPacket(2, 1, 1, 1));
ckrasic3865ee0f2016-02-29 22:04:562677
Kenichi Ishibashif8634ab2021-03-16 23:41:282678 SetResponse("404", string());
ckrasic3865ee0f2016-02-29 22:04:562679 size_t spdy_response_header_frame_length;
2680 ProcessPacket(InnerConstructResponseHeadersPacket(
Nick Harper23290b82019-05-02 00:02:562681 3,
2682 stream_id_ + quic::QuicUtils::StreamIdDelta(version_.transport_version),
2683 kFin, &spdy_response_header_frame_length));
ckrasic3865ee0f2016-02-29 22:04:562684
fdoray92e35a72016-06-10 15:54:552685 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562686
robpercival214763f2016-07-01 23:27:012687 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2688 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562689 ASSERT_TRUE(response_.headers.get());
2690 EXPECT_EQ(404, response_.headers->response_code());
2691 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
2692 EXPECT_FALSE(response_.response_time.is_null());
2693 EXPECT_FALSE(response_.request_time.is_null());
2694
2695 // There is no body, so this should return immediately.
2696 EXPECT_EQ(
2697 0, promised_stream_->ReadResponseBody(
2698 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2699 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2700
2701 stream_->Close(true);
2702
2703 EXPECT_TRUE(AtEof());
ckrasic3865ee0f2016-02-29 22:04:562704}
2705
maksim.sisov84e20c92016-06-23 08:49:342706TEST_P(QuicHttpStreamTest, DataReadErrorSynchronous) {
2707 SetRequest("POST", "/", DEFAULT_PRIORITY);
2708 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232709 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252710 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232711 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Yixin Wange7ecc472018-03-06 19:00:252712 AddWrite(ConstructRequestAndRstPacket(
Renjie Tangaadb84b2019-08-31 01:00:232713 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2714 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
2715 &spdy_request_headers_frame_length, quic::QUIC_ERROR_PROCESSING_STREAM));
maksim.sisov84e20c92016-06-23 08:49:342716
2717 Initialize();
2718
Jeremy Roman0579ed62017-08-29 15:56:192719 upload_data_stream_ = std::make_unique<ReadErrorUploadDataStream>(
maksim.sisov84e20c92016-06-23 08:49:342720 ReadErrorUploadDataStream::FailureMode::SYNC);
2721 request_.method = "POST";
rchcd379012017-04-12 21:53:322722 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122723 request_.upload_data_stream = upload_data_stream_.get();
maksim.sisov84e20c92016-06-23 08:49:342724 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202725 TestCompletionCallback().callback(), NetLogWithSource()));
maksim.sisov84e20c92016-06-23 08:49:342726
Ali Beyada0b1a1c2022-04-08 20:08:142727 stream_->RegisterRequest(&request_);
2728 EXPECT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262729 net_log_with_source_,
2730 callback_.callback()));
maksim.sisov84e20c92016-06-23 08:49:342731
2732 int result = stream_->SendRequest(headers_, &response_, callback_.callback());
robpercival214763f2016-07-01 23:27:012733 EXPECT_THAT(result, IsError(ERR_FAILED));
maksim.sisov84e20c92016-06-23 08:49:342734
2735 EXPECT_TRUE(AtEof());
2736
2737 // QuicHttpStream::GetTotalSent/ReceivedBytes includes only headers.
2738 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
2739 stream_->GetTotalSentBytes());
2740 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2741}
2742
2743TEST_P(QuicHttpStreamTest, DataReadErrorAsynchronous) {
2744 SetRequest("POST", "/", DEFAULT_PRIORITY);
2745 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232746 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252747 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232748 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:372749 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:232750 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2751 kIncludeVersion, !kFin, DEFAULT_PRIORITY,
2752 &spdy_request_headers_frame_length));
2753 AddWrite(
2754 ConstructClientRstStreamErrorPacket(packet_number++, !kIncludeVersion));
maksim.sisov84e20c92016-06-23 08:49:342755
2756 Initialize();
2757
Jeremy Roman0579ed62017-08-29 15:56:192758 upload_data_stream_ = std::make_unique<ReadErrorUploadDataStream>(
maksim.sisov84e20c92016-06-23 08:49:342759 ReadErrorUploadDataStream::FailureMode::ASYNC);
2760 request_.method = "POST";
rchcd379012017-04-12 21:53:322761 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122762 request_.upload_data_stream = upload_data_stream_.get();
maksim.sisov84e20c92016-06-23 08:49:342763 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202764 TestCompletionCallback().callback(), NetLogWithSource()));
maksim.sisov84e20c92016-06-23 08:49:342765
Ali Beyada0b1a1c2022-04-08 20:08:142766 stream_->RegisterRequest(&request_);
2767 EXPECT_EQ(OK, stream_->InitializeStream(false, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262768 net_log_with_source_,
2769 callback_.callback()));
maksim.sisov84e20c92016-06-23 08:49:342770
2771 int result = stream_->SendRequest(headers_, &response_, callback_.callback());
2772
Renjie90e808e2019-01-24 07:24:042773 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
Kenichi Ishibashif8634ab2021-03-16 23:41:282774 SetResponse("200", string());
maksim.sisov84e20c92016-06-23 08:49:342775
robpercival214763f2016-07-01 23:27:012776 EXPECT_THAT(result, IsError(ERR_IO_PENDING));
2777 EXPECT_THAT(callback_.GetResult(result), IsError(ERR_FAILED));
maksim.sisov84e20c92016-06-23 08:49:342778
2779 EXPECT_TRUE(AtEof());
2780
2781 // QuicHttpStream::GetTotalSent/ReceivedBytes includes only headers.
2782 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
2783 stream_->GetTotalSentBytes());
2784 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2785}
2786
Bence Béky97ec688c2021-03-16 13:48:502787TEST_P(QuicHttpStreamTest, GetAcceptChViaAlps) {
2788 AddWrite(ConstructInitialSettingsPacket());
2789 Initialize();
2790
2791 if (!VersionUsesHttp3(version_.transport_version)) {
2792 // ALPS is only implemented for HTTP/3.
2793 return;
2794 }
2795
2796 base::HistogramTester histogram_tester;
2797
2798 session_->OnAcceptChFrameReceivedViaAlps(
Bence Béky41a34f02021-05-07 00:27:482799 {{{"https://www.example.org", "Sec-CH-UA-Platform"}}});
Bence Béky97ec688c2021-03-16 13:48:502800
2801 request_.method = "GET";
2802 request_.url = GURL("https://www.example.org/foo");
2803
Ali Beyada0b1a1c2022-04-08 20:08:142804 stream_->RegisterRequest(&request_);
2805 EXPECT_EQ(OK, stream_->InitializeStream(true, DEFAULT_PRIORITY,
Matt Reichhoff0049a0b72021-10-20 20:44:262806 net_log_with_source_,
2807 callback_.callback()));
Bence Béky41a34f02021-05-07 00:27:482808 EXPECT_EQ("Sec-CH-UA-Platform", stream_->GetAcceptChViaAlps());
Bence Béky97ec688c2021-03-16 13:48:502809 EXPECT_TRUE(AtEof());
2810
2811 histogram_tester.ExpectBucketCount(
2812 "Net.QuicSession.AcceptChFrameReceivedViaAlps", 1, 1);
2813 histogram_tester.ExpectTotalCount(
2814 "Net.QuicSession.AcceptChFrameReceivedViaAlps", 1);
2815 histogram_tester.ExpectBucketCount("Net.QuicSession.AcceptChForOrigin", 1, 1);
2816 histogram_tester.ExpectTotalCount("Net.QuicSession.AcceptChForOrigin", 1);
2817}
2818
Tsuyoshi Horo4f516be2022-06-14 11:53:132819} // namespace net::test