blob: e49e4ace847cb8f3919bde94d754b50431267f79 [file] [log] [blame]
[email protected]f702d572012-12-04 15:56:201// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Ryan Hamiltona3ee93a72018-08-01 22:03:085#include "net/quic/quic_http_stream.h"
[email protected]f702d572012-12-04 15:56:206
sclittle1edeeb22015-09-02 20:46:107#include <stdint.h>
8
danakjad1777e2016-04-16 00:56:429#include <memory>
bnc086b39e12016-06-24 13:05:2610#include <utility>
[email protected]f702d572012-12-04 15:56:2011
Sebastien Marchand6d0558fd2019-01-25 16:49:3712#include "base/bind.h"
danakjad1777e2016-04-16 00:56:4213#include "base/memory/ptr_util.h"
fdoray92e35a72016-06-10 15:54:5514#include "base/run_loop.h"
Bence Békye0d3747d2020-08-28 23:16:4015#include "base/strings/strcat.h"
xunjieli188bd402016-03-12 00:17:2516#include "base/strings/string_number_conversions.h"
Bence Béky97ec688c2021-03-16 13:48:5017#include "base/test/metrics/histogram_tester.h"
gabf767595f2016-05-11 18:50:3518#include "base/threading/thread_task_runner_handle.h"
Zhongyi Shic16b4102019-02-12 00:37:4019#include "base/time/default_tick_clock.h"
xunjieli84adaab2016-09-20 01:12:2820#include "base/time/time.h"
mmenkecbc2b712014-10-09 20:29:0721#include "net/base/chunked_upload_data_stream.h"
22#include "net/base/elements_upload_data_stream.h"
David Benjamin0288768a2019-07-22 15:00:2623#include "net/base/load_flags.h"
xunjieli84adaab2016-09-20 01:12:2824#include "net/base/load_timing_info.h"
25#include "net/base/load_timing_info_test_util.h"
[email protected]f702d572012-12-04 15:56:2026#include "net/base/net_errors.h"
27#include "net/base/test_completion_callback.h"
[email protected]b2d26cfd2012-12-11 10:36:0628#include "net/base/upload_bytes_element_reader.h"
Ben Schwartz3ff4dc1e62021-04-27 21:15:2329#include "net/dns/public/secure_dns_policy.h"
[email protected]f702d572012-12-04 15:56:2030#include "net/http/http_response_headers.h"
[email protected]5db452202014-08-19 05:22:1531#include "net/http/transport_security_state.h"
Matt Reichhoff0049a0b72021-10-20 20:44:2632#include "net/log/net_log.h"
mikecirone8b85c432016-09-08 19:11:0033#include "net/log/net_log_event_type.h"
xunjieli5fafe142016-03-23 23:32:5434#include "net/log/test_net_log.h"
35#include "net/log/test_net_log_util.h"
Victor Vasiliev4f6fb892019-05-31 16:58:3136#include "net/quic/address_utils.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0837#include "net/quic/crypto/proof_verifier_chromium.h"
38#include "net/quic/mock_crypto_client_stream_factory.h"
Ryan Hamiltona1d1f4a2019-06-26 14:43:0439#include "net/quic/platform/impl/quic_test_impl.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0840#include "net/quic/quic_chromium_alarm_factory.h"
41#include "net/quic/quic_chromium_connection_helper.h"
42#include "net/quic/quic_chromium_packet_reader.h"
43#include "net/quic/quic_chromium_packet_writer.h"
Matt Menkefca05b62019-09-20 23:15:5644#include "net/quic/quic_crypto_client_config_handle.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0845#include "net/quic/quic_http_utils.h"
46#include "net/quic/quic_server_info.h"
47#include "net/quic/quic_stream_factory.h"
48#include "net/quic/quic_test_packet_maker.h"
Ryan Hamilton0d65a8c2019-06-07 00:46:0249#include "net/quic/quic_test_packet_printer.h"
Matt Menkefca05b62019-09-20 23:15:5650#include "net/quic/test_quic_crypto_client_config_handle.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0851#include "net/quic/test_task_runner.h"
tbansalca83c002016-04-28 20:56:2852#include "net/socket/socket_performance_watcher.h"
[email protected]f702d572012-12-04 15:56:2053#include "net/socket/socket_test_util.h"
Bence Béky94658bf2018-05-11 19:22:5854#include "net/spdy/spdy_http_utils.h"
rch03b7a202016-02-05 00:54:2055#include "net/test/cert_test_util.h"
robpercival214763f2016-07-01 23:27:0156#include "net/test/gtest_util.h"
rsleevia69c79a2016-06-22 03:28:4357#include "net/test/test_data_directory.h"
Gabriel Charettec7108742019-08-23 03:31:4058#include "net/test/test_with_task_environment.h"
Victor Vasiliev6bb59d22019-03-08 21:34:5159#include "net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.h"
60#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
61#include "net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h"
62#include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
David Schinazi3f7465c2019-07-12 01:57:0563#include "net/third_party/quiche/src/quic/core/http/spdy_server_push_utils.h"
Victor Vasiliev6bb59d22019-03-08 21:34:5164#include "net/third_party/quiche/src/quic/core/quic_connection.h"
65#include "net/third_party/quiche/src/quic/core/quic_utils.h"
66#include "net/third_party/quiche/src/quic/core/quic_write_blocked_list.h"
Ryan Hamiltona1d1f4a2019-06-26 14:43:0467#include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h"
68#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
Victor Vasiliev6bb59d22019-03-08 21:34:5169#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
70#include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
71#include "net/third_party/quiche/src/quic/test_tools/mock_random.h"
Bence Béky6e243aa2019-12-13 19:01:0772#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h"
Victor Vasiliev6bb59d22019-03-08 21:34:5173#include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
74#include "net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h"
75#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
Victor Vasiliev27cc7712019-01-24 11:50:1476#include "net/third_party/quiche/src/spdy/core/spdy_frame_builder.h"
77#include "net/third_party/quiche/src/spdy/core/spdy_framer.h"
78#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
Ramin Halavati683bcaa92018-02-14 08:42:3979#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
[email protected]f702d572012-12-04 15:56:2080#include "testing/gmock/include/gmock/gmock.h"
81#include "testing/gtest/include/gtest/gtest.h"
Dan McArdle68a5f622021-07-09 20:56:5382#include "url/scheme_host_port.h"
83#include "url/url_constants.h"
[email protected]f702d572012-12-04 15:56:2084
bnc614a92d32016-04-04 13:56:0785using std::string;
[email protected]f702d572012-12-04 15:56:2086using testing::_;
[email protected]06ff5152013-08-29 01:03:0587using testing::AnyNumber;
88using testing::Return;
[email protected]f702d572012-12-04 15:56:2089
90namespace net {
[email protected]f702d572012-12-04 15:56:2091namespace test {
[email protected]f702d572012-12-04 15:56:2092namespace {
93
[email protected]16ba7742014-08-22 00:57:2594const char kUploadData[] = "Really nifty data!";
rch9ae5b3b2016-02-11 00:36:2995const char kDefaultServerHostName[] = "www.example.org";
rchcd379012017-04-12 21:53:3296const uint16_t kDefaultServerPort = 443;
[email protected]f702d572012-12-04 15:56:2097
David Schinazi09e9a6012019-10-03 17:37:5798struct TestParams {
99 quic::ParsedQuicVersion version;
100 bool client_headers_include_h2_stream_dependency;
101};
102
103// Used by ::testing::PrintToStringParamName().
104std::string PrintToString(const TestParams& p) {
Victor Vasiliev62c09dc2020-11-06 18:18:29105 return base::StrCat(
106 {ParsedQuicVersionToString(p.version), "_",
107 (p.client_headers_include_h2_stream_dependency ? "" : "No"),
108 "Dependency"});
David Schinazi09e9a6012019-10-03 17:37:57109}
110
111std::vector<TestParams> GetTestParams() {
112 std::vector<TestParams> params;
113 quic::ParsedQuicVersionVector all_supported_versions =
114 quic::AllSupportedVersions();
115 for (const auto& version : all_supported_versions) {
116 params.push_back(TestParams{version, false});
117 params.push_back(TestParams{version, true});
118 }
119 return params;
120}
121
Bence Békye0d3747d2020-08-28 23:16:40122// Returns true if |params| is a dict, has an entry with key "headers", that
123// entry is a list of strings, which when interpreted as colon-separated
124// key-value pairs has exactly one entry with |key| and that entry has value
125// |expected_value|.
126bool CheckHeader(const base::Value& params,
127 base::StringPiece key,
128 base::StringPiece expected_value) {
129 if (!params.is_dict()) {
130 return false;
131 }
132 const base::Value* headers = params.FindListKey("headers");
133 if (!headers) {
134 return false;
135 }
136
137 std::string header_prefix = base::StrCat({key, ": "});
138 std::string expected_header = base::StrCat({header_prefix, expected_value});
139
140 auto header_list = headers->GetList();
141 auto header_it = header_list.begin();
142 bool header_found = false;
143 while (header_it != header_list.end()) {
144 if (!header_it->is_string()) {
145 return false;
146 }
147 const std::string& header = header_it->GetString();
148 if (base::StartsWith(header, header_prefix)) {
149 if (header_found) {
150 return false;
151 }
152 if (header != expected_header) {
153 return false;
154 }
155 header_found = true;
156 }
157 ++header_it;
158 }
159 return header_found;
160}
161
Ryan Hamilton8d9ee76e2018-05-29 23:52:52162class TestQuicConnection : public quic::QuicConnection {
[email protected]f702d572012-12-04 15:56:20163 public:
Ryan Hamilton8d9ee76e2018-05-29 23:52:52164 TestQuicConnection(const quic::ParsedQuicVersionVector& versions,
165 quic::QuicConnectionId connection_id,
[email protected]f702d572012-12-04 15:56:20166 IPEndPoint address,
rch12fef552016-01-15 16:26:31167 QuicChromiumConnectionHelper* helper,
rch16c74d1d2016-04-22 06:14:07168 QuicChromiumAlarmFactory* alarm_factory,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52169 quic::QuicPacketWriter* writer)
Victor Vasiliev4f6fb892019-05-31 16:58:31170 : quic::QuicConnection(connection_id,
Nick Harperd049f192020-10-02 02:56:10171 quic::QuicSocketAddress(),
Victor Vasiliev4f6fb892019-05-31 16:58:31172 ToQuicSocketAddress(address),
173 helper,
174 alarm_factory,
175 writer,
176 true /* owns_writer */,
177 quic::Perspective::IS_CLIENT,
178 versions) {}
[email protected]f702d572012-12-04 15:56:20179
Ryan Hamilton8d9ee76e2018-05-29 23:52:52180 void SetSendAlgorithm(quic::SendAlgorithmInterface* send_algorithm) {
181 quic::test::QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
[email protected]f702d572012-12-04 15:56:20182 }
183};
184
maksim.sisov84e20c92016-06-23 08:49:34185// UploadDataStream that always returns errors on data read.
186class ReadErrorUploadDataStream : public UploadDataStream {
187 public:
188 enum class FailureMode { SYNC, ASYNC };
189
190 explicit ReadErrorUploadDataStream(FailureMode mode)
Jeremy Romand54000b22019-07-08 18:40:16191 : UploadDataStream(true, 0), async_(mode) {}
Peter Boström293b1342021-09-22 17:31:43192
193 ReadErrorUploadDataStream(const ReadErrorUploadDataStream&) = delete;
194 ReadErrorUploadDataStream& operator=(const ReadErrorUploadDataStream&) =
195 delete;
196
maksim.sisov84e20c92016-06-23 08:49:34197 ~ReadErrorUploadDataStream() override {}
198
199 private:
200 void CompleteRead() { UploadDataStream::OnReadCompleted(ERR_FAILED); }
201
202 // UploadDataStream implementation:
tfarina42834112016-09-22 13:38:20203 int InitInternal(const NetLogWithSource& net_log) override { return OK; }
maksim.sisov84e20c92016-06-23 08:49:34204
205 int ReadInternal(IOBuffer* buf, int buf_len) override {
206 if (async_ == FailureMode::ASYNC) {
207 base::ThreadTaskRunnerHandle::Get()->PostTask(
kylecharf4fe5172019-02-15 18:53:49208 FROM_HERE, base::BindOnce(&ReadErrorUploadDataStream::CompleteRead,
209 weak_factory_.GetWeakPtr()));
maksim.sisov84e20c92016-06-23 08:49:34210 return ERR_IO_PENDING;
211 }
212 return ERR_FAILED;
213 }
214
215 void ResetInternal() override {}
216
217 const FailureMode async_;
218
Jeremy Romand54000b22019-07-08 18:40:16219 base::WeakPtrFactory<ReadErrorUploadDataStream> weak_factory_{this};
maksim.sisov84e20c92016-06-23 08:49:34220};
221
Bence Béky8ddc2492018-06-13 01:02:04222// A helper class that will delete |stream| when the callback is invoked.
xunjieli8dff50b2016-07-22 14:19:06223class DeleteStreamCallback : public TestCompletionCallbackBase {
224 public:
Bence Béky8ddc2492018-06-13 01:02:04225 explicit DeleteStreamCallback(std::unique_ptr<QuicHttpStream> stream)
226 : stream_(std::move(stream)) {}
xunjieli8dff50b2016-07-22 14:19:06227
Bence Béky8ddc2492018-06-13 01:02:04228 CompletionOnceCallback callback() {
229 return base::BindOnce(&DeleteStreamCallback::DeleteStream,
230 base::Unretained(this));
231 }
xunjieli8dff50b2016-07-22 14:19:06232
233 private:
234 void DeleteStream(int result) {
235 stream_.reset();
236 SetResult(result);
237 }
238
239 std::unique_ptr<QuicHttpStream> stream_;
xunjieli8dff50b2016-07-22 14:19:06240};
241
[email protected]f702d572012-12-04 15:56:20242} // namespace
243
[email protected]24e5bc52013-09-18 15:36:58244class QuicHttpStreamPeer {
245 public:
rch08e198572017-05-09 16:56:55246 static QuicChromiumClientStream::Handle* GetQuicChromiumClientStream(
[email protected]24e5bc52013-09-18 15:36:58247 QuicHttpStream* stream) {
rch08e198572017-05-09 16:56:55248 return stream->stream_.get();
[email protected]24e5bc52013-09-18 15:36:58249 }
250};
251
David Schinazi09e9a6012019-10-03 17:37:57252class QuicHttpStreamTest : public ::testing::TestWithParam<TestParams>,
Gabriel Charette694c3c332019-08-19 14:53:05253 public WithTaskEnvironment {
rchfb47f712017-05-21 03:24:00254 public:
255 void CloseStream(QuicHttpStream* stream, int /*rv*/) { stream->Close(false); }
256
[email protected]f702d572012-12-04 15:56:20257 protected:
[email protected]1e960032013-12-20 19:00:20258 static const bool kFin = true;
259 static const bool kIncludeVersion = true;
[email protected]1e960032013-12-20 19:00:20260
[email protected]f702d572012-12-04 15:56:20261 // Holds a packet to be written to the wire, and the IO mode that should
262 // be used by the mock socket when performing the write.
263 struct PacketToWrite {
Ryan Hamilton8d9ee76e2018-05-29 23:52:52264 PacketToWrite(IoMode mode, quic::QuicReceivedPacket* packet)
rjshaded5ced072015-12-18 19:26:02265 : mode(mode), packet(packet) {}
rtenneti15656ae2016-01-23 03:05:03266 PacketToWrite(IoMode mode, int rv) : mode(mode), packet(nullptr), rv(rv) {}
[email protected]f702d572012-12-04 15:56:20267 IoMode mode;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52268 quic::QuicReceivedPacket* packet;
rtenneti15656ae2016-01-23 03:05:03269 int rv;
[email protected]f702d572012-12-04 15:56:20270 };
271
272 QuicHttpStreamTest()
David Schinazi09e9a6012019-10-03 17:37:57273 : version_(GetParam().version),
274 client_headers_include_h2_stream_dependency_(
275 GetParam().client_headers_include_h2_stream_dependency),
Nick Harpera598fc5f2019-06-21 08:46:50276 crypto_config_(
277 quic::test::crypto_test_utils::ProofVerifierForTesting()),
Victor Costan9c7302b2018-08-27 16:39:44278 read_buffer_(base::MakeRefCounted<IOBufferWithSize>(4096)),
Fan Yang32c5a112018-12-10 20:06:33279 promise_id_(GetNthServerInitiatedUnidirectionalStreamId(0)),
280 stream_id_(GetNthClientInitiatedBidirectionalStreamId(0)),
David Schinazic8281052019-01-24 06:14:17281 connection_id_(quic::test::TestConnectionId(2)),
Yixin Wang079ad542018-01-11 04:06:05282 client_maker_(version_,
alyssar2adf3ac2016-05-03 17:12:58283 connection_id_,
284 &clock_,
285 kDefaultServerHostName,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52286 quic::Perspective::IS_CLIENT,
Yixin Wang079ad542018-01-11 04:06:05287 client_headers_include_h2_stream_dependency_),
288 server_maker_(version_,
zhongyi5dbfdd42017-06-20 05:22:15289 connection_id_,
alyssar2adf3ac2016-05-03 17:12:58290 &clock_,
291 kDefaultServerHostName,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52292 quic::Perspective::IS_SERVER,
Yixin Wang079ad542018-01-11 04:06:05293 false),
ckrasic3865ee0f2016-02-29 22:04:56294 random_generator_(0),
Ryan Hamilton0d65a8c2019-06-07 00:46:02295 printer_(version_) {
Renjie Tang98b4d512020-02-08 01:24:19296 FLAGS_quic_enable_http3_grease_randomness = false;
Zhongyi Shi49f8ad2fd2019-12-13 01:20:31297 quic::QuicEnableVersion(version_);
martijn21968ea2016-02-24 18:46:20298 IPAddress ip(192, 0, 2, 33);
[email protected]f702d572012-12-04 15:56:20299 peer_addr_ = IPEndPoint(ip, 443);
300 self_addr_ = IPEndPoint(ip, 8435);
Ryan Hamilton8d9ee76e2018-05-29 23:52:52301 clock_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(20));
Ramin Halavati683bcaa92018-02-14 08:42:39302 request_.traffic_annotation =
303 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f702d572012-12-04 15:56:20304 }
305
306 ~QuicHttpStreamTest() {
Renjieba55fae2018-09-20 03:05:16307 session_->CloseSessionOnError(ERR_ABORTED, quic::QUIC_INTERNAL_ERROR,
308 quic::ConnectionCloseBehavior::SILENT_CLOSE);
[email protected]f702d572012-12-04 15:56:20309 for (size_t i = 0; i < writes_.size(); i++) {
310 delete writes_[i].packet;
311 }
312 }
313
314 // Adds a packet to the list of expected writes.
Ryan Hamilton8d9ee76e2018-05-29 23:52:52315 void AddWrite(std::unique_ptr<quic::QuicReceivedPacket> packet) {
[email protected]1e960032013-12-20 19:00:20316 writes_.push_back(PacketToWrite(SYNCHRONOUS, packet.release()));
[email protected]f702d572012-12-04 15:56:20317 }
318
rtenneti15656ae2016-01-23 03:05:03319 void AddWrite(IoMode mode, int rv) {
320 writes_.push_back(PacketToWrite(mode, rv));
321 }
322
[email protected]f702d572012-12-04 15:56:20323 // Returns the packet to be written at position |pos|.
Ryan Hamilton8d9ee76e2018-05-29 23:52:52324 quic::QuicReceivedPacket* GetWrite(size_t pos) { return writes_[pos].packet; }
[email protected]f702d572012-12-04 15:56:20325
326 bool AtEof() {
rch37de576c2015-05-17 20:28:17327 return socket_data_->AllReadDataConsumed() &&
328 socket_data_->AllWriteDataConsumed();
[email protected]f702d572012-12-04 15:56:20329 }
330
Ryan Hamilton8d9ee76e2018-05-29 23:52:52331 void ProcessPacket(std::unique_ptr<quic::QuicReceivedPacket> packet) {
Victor Vasiliev4f6fb892019-05-31 16:58:31332 connection_->ProcessUdpPacket(ToQuicSocketAddress(self_addr_),
333 ToQuicSocketAddress(peer_addr_), *packet);
[email protected]f702d572012-12-04 15:56:20334 }
335
336 // Configures the test fixture to use the list of expected writes.
337 void Initialize() {
Renjie Tang6ff9a9b2021-02-03 22:11:09338 mock_writes_ = std::make_unique<MockWrite[]>(writes_.size());
[email protected]f702d572012-12-04 15:56:20339 for (size_t i = 0; i < writes_.size(); i++) {
rtenneti15656ae2016-01-23 03:05:03340 if (writes_[i].packet == nullptr) {
341 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].rv, i);
342 } else {
343 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].packet->data(),
344 writes_[i].packet->length());
345 }
bnc614a92d32016-04-04 13:56:07346 }
[email protected]f702d572012-12-04 15:56:20347
Renjie Tang6ff9a9b2021-02-03 22:11:09348 socket_data_ = std::make_unique<StaticSocketDataProvider>(
Ryan Sleevib8d7ea02018-05-07 20:01:01349 base::span<MockRead>(),
Renjie Tang6ff9a9b2021-02-03 22:11:09350 base::make_span(mock_writes_.get(), writes_.size()));
Ryan Hamilton0d65a8c2019-06-07 00:46:02351 socket_data_->set_printer(&printer_);
[email protected]f702d572012-12-04 15:56:20352
Matt Reichhoff0049a0b72021-10-20 20:44:26353 std::unique_ptr<MockUDPClientSocket> socket(
354 new MockUDPClientSocket(socket_data_.get(), NetLog::Get()));
[email protected]e13201d82012-12-12 05:00:32355 socket->Connect(peer_addr_);
[email protected]f702d572012-12-04 15:56:20356 runner_ = new TestTaskRunner(&clock_);
Ryan Hamilton8d9ee76e2018-05-29 23:52:52357 send_algorithm_ = new quic::test::MockSendAlgorithm();
rch7dd15702015-07-01 18:57:57358 EXPECT_CALL(*send_algorithm_, InRecovery()).WillRepeatedly(Return(false));
359 EXPECT_CALL(*send_algorithm_, InSlowStart()).WillRepeatedly(Return(false));
Victor Vasiliev7da08172019-10-14 06:04:25360 if (VersionUsesHttp3(version_.transport_version)) {
Renjie Tangaadb84b2019-08-31 01:00:23361 EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
362 .Times(testing::AtLeast(1));
363 }
Ryan Hamiltona1d1f4a2019-06-26 14:43:04364 EXPECT_CALL(*send_algorithm_, OnCongestionEvent(_, _, _, _, _))
365 .Times(AnyNumber());
rtenneti44f4a2e2015-08-07 14:00:07366 EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
Zhongyi Shica576df2019-04-12 17:43:40367 .WillRepeatedly(Return(quic::kMaxOutgoingPacketSize));
jokulik0e0a00c32016-06-13 21:51:58368 EXPECT_CALL(*send_algorithm_, PacingRate(_))
Ryan Hamilton8d9ee76e2018-05-29 23:52:52369 .WillRepeatedly(Return(quic::QuicBandwidth::Zero()));
Michael Warres74ee3ce2017-10-09 15:26:37370 EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true));
rtenneti44f4a2e2015-08-07 14:00:07371 EXPECT_CALL(*send_algorithm_, BandwidthEstimate())
Ryan Hamilton8d9ee76e2018-05-29 23:52:52372 .WillRepeatedly(Return(quic::QuicBandwidth::Zero()));
rch1e543ec2015-03-29 07:04:40373 EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(AnyNumber());
rch08cae032017-03-29 00:59:15374 EXPECT_CALL(*send_algorithm_, OnApplicationLimited(_)).Times(AnyNumber());
rch0d5bcf62017-05-24 22:48:45375 EXPECT_CALL(*send_algorithm_, GetCongestionControlType())
376 .Times(AnyNumber());
Renjie Tang6ff9a9b2021-02-03 22:11:09377 helper_ = std::make_unique<QuicChromiumConnectionHelper>(
378 &clock_, &random_generator_);
379 alarm_factory_ =
380 std::make_unique<QuicChromiumAlarmFactory>(runner_.get(), &clock_);
rch16c74d1d2016-04-22 06:14:07381
Michael Warres74ee3ce2017-10-09 15:26:37382 connection_ = new TestQuicConnection(
Nick Harper23290b82019-05-02 00:02:56383 quic::test::SupportedVersions(version_), connection_id_, peer_addr_,
384 helper_.get(), alarm_factory_.get(),
Ryan Hamilton9edcf1a2017-11-22 05:55:17385 new QuicChromiumPacketWriter(
386 socket.get(), base::ThreadTaskRunnerHandle::Get().get()));
[email protected]f702d572012-12-04 15:56:20387 connection_->set_visitor(&visitor_);
[email protected]fee17f72013-02-03 07:47:41388 connection_->SetSendAlgorithm(send_algorithm_);
rch03b7a202016-02-05 00:54:20389
390 // Load a certificate that is valid for *.example.org
391 scoped_refptr<X509Certificate> test_cert(
392 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
393 EXPECT_TRUE(test_cert.get());
394
395 verify_details_.cert_verify_result.verified_cert = test_cert;
396 verify_details_.cert_verify_result.is_issued_by_known_root = true;
397 crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details_);
398
xunjieli84adaab2016-09-20 01:12:28399 base::TimeTicks dns_end = base::TimeTicks::Now();
Peter Kastinge5a38ed2021-10-02 03:06:35400 base::TimeTicks dns_start = dns_end - base::Milliseconds(1);
Renjie Tang6ff9a9b2021-02-03 22:11:09401 session_ = std::make_unique<QuicChromiumClientSession>(
xunjielib53b38c2016-03-24 15:54:36402 connection_, std::move(socket),
rtenneti1cd3b162015-09-29 02:58:28403 /*stream_factory=*/nullptr, &crypto_client_stream_factory_, &clock_,
Nick Harper89bc7212018-07-31 19:07:57404 &transport_security_state_, /*ssl_config_service=*/nullptr,
danakjad1777e2016-04-16 00:56:42405 base::WrapUnique(static_cast<QuicServerInfo*>(nullptr)),
Paul Jensen8e3c5d32018-02-19 17:06:33406 QuicSessionKey(kDefaultServerHostName, kDefaultServerPort,
dalyk51ab46b2019-10-15 15:14:34407 PRIVACY_MODE_DISABLED, SocketTag(),
Ben Schwartz3ff4dc1e62021-04-27 21:15:23408 NetworkIsolationKey(), SecureDnsPolicy::kAllow),
Bence Béky1ceba552019-07-19 17:11:05409 /*require_confirmation=*/false,
Bence Béky1ceba552019-07-19 17:11:05410 /*migrate_session_early_v2=*/false,
Zhongyi Shi757fcce2018-06-27 05:41:27411 /*migrate_session_on_network_change_v2=*/false,
412 /*default_network=*/NetworkChangeNotifier::kInvalidNetworkHandle,
Zhongyi Shie01f2db2019-02-22 19:53:23413 quic::QuicTime::Delta::FromMilliseconds(
Ryan Sleevi2e8255b2019-07-17 21:02:21414 kDefaultRetransmittableOnWireTimeout.InMilliseconds()),
Zhongyi Shiaf38c4e42019-08-29 22:49:05415 /*migrate_idle_session=*/false, /*allow_port_migration=*/false,
416 kDefaultIdleSessionMigrationPeriod, kMaxTimeOnNonDefaultNetwork,
Zhongyi Shiee760762018-08-01 00:54:29417 kMaxMigrationsToNonDefaultNetworkOnWriteError,
Zhongyi Shi8b1e43f2017-12-13 20:46:30418 kMaxMigrationsToNonDefaultNetworkOnPathDegrading,
Zhongyi Shi5f587cc2017-11-21 23:24:17419 kQuicYieldAfterPacketsRead,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52420 quic::QuicTime::Delta::FromMilliseconds(
421 kQuicYieldAfterDurationMilliseconds),
Zhongyi Shidbce7f412019-02-01 23:16:29422 /*go_away_on_path_degrading*/ false,
Yixin Wang079ad542018-01-11 04:06:05423 client_headers_include_h2_stream_dependency_, /*cert_verify_flags=*/0,
Matt Menkefca05b62019-09-20 23:15:56424 quic::test::DefaultQuicConfig(),
425 std::make_unique<TestQuicCryptoClientConfigHandle>(&crypto_config_),
Matt Menked804aaf2020-07-21 21:25:48426 "CONNECTION_UNKNOWN", dns_start, dns_end,
427 std::make_unique<quic::QuicClientPushPromiseIndex>(), nullptr,
Zhongyi Shic16b4102019-02-12 00:37:40428 base::DefaultTickClock::GetInstance(),
xunjieli84adaab2016-09-20 01:12:28429 base::ThreadTaskRunnerHandle::Get().get(),
Matt Reichhoff0049a0b72021-10-20 20:44:26430 /*socket_performance_watcher=*/nullptr, NetLog::Get());
rtennetid39bd762015-06-12 01:05:52431 session_->Initialize();
rchf0b18c8a2017-05-05 19:31:57432
Bence Béky6e243aa2019-12-13 19:01:07433 // Blackhole QPACK decoder stream instead of constructing mock writes.
434 if (VersionUsesHttp3(version_.transport_version)) {
435 session_->qpack_decoder()->set_qpack_stream_sender_delegate(
436 &noop_qpack_stream_sender_delegate_);
437 }
438
439 TestCompletionCallback callback;
rch433bf5f2017-02-14 04:10:47440 session_->CryptoConnect(callback.callback());
Ryan Hamilton6c2a2a82017-12-15 02:06:28441 stream_ = std::make_unique<QuicHttpStream>(
Dan McArdle68a5f622021-07-09 20:56:53442 session_->CreateHandle(
443 url::SchemeHostPort(url::kHttpsScheme, "www.example.org", 443)),
Cammie Smith Barnes0f38aff2021-03-02 23:14:35444 std::vector<std::string>() /* dns_aliases */);
Ryan Hamilton6c2a2a82017-12-15 02:06:28445 promised_stream_ = std::make_unique<QuicHttpStream>(
Dan McArdle68a5f622021-07-09 20:56:53446 session_->CreateHandle(
447 url::SchemeHostPort(url::kHttpsScheme, "www.example.org", 443)),
Cammie Smith Barnes0f38aff2021-03-02 23:14:35448 std::vector<std::string>() /* dns_aliases */);
ckrasic3865ee0f2016-02-29 22:04:56449 push_promise_[":path"] = "/bar";
450 push_promise_[":authority"] = "www.example.org";
451 push_promise_[":version"] = "HTTP/1.1";
452 push_promise_[":method"] = "GET";
453 push_promise_[":scheme"] = "https";
454
Kenichi Ishibashif8634ab2021-03-16 23:41:28455 promised_response_[":status"] = "200";
ckrasic3865ee0f2016-02-29 22:04:56456 promised_response_[":version"] = "HTTP/1.1";
457 promised_response_["content-type"] = "text/plain";
458
David Schinazi3f7465c2019-07-12 01:57:05459 promise_url_ =
460 quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
[email protected]6cca996b2013-01-25 07:43:36461 }
462
bnc614a92d32016-04-04 13:56:07463 void SetRequest(const string& method,
464 const string& path,
[email protected]1e960032013-12-20 19:00:20465 RequestPriority priority) {
rchcd379012017-04-12 21:53:32466 request_headers_ = client_maker_.GetRequestHeaders(method, "https", path);
[email protected]6cca996b2013-01-25 07:43:36467 }
468
bnc614a92d32016-04-04 13:56:07469 void SetResponse(const string& status, const string& body) {
alyssar2adf3ac2016-05-03 17:12:58470 response_headers_ = server_maker_.GetResponseHeaders(status);
[email protected]92bf17c2014-03-03 21:14:03471 response_data_ = body;
[email protected]6cca996b2013-01-25 07:43:36472 }
[email protected]f702d572012-12-04 15:56:20473
Ryan Hamilton8d9ee76e2018-05-29 23:52:52474 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientDataPacket(
Fan Yangac867502019-01-28 21:10:23475 uint64_t packet_number,
[email protected]e8ff26842013-03-22 21:02:05476 bool should_include_version,
[email protected]f702d572012-12-04 15:56:20477 bool fin,
Victor Vasiliev47ecb6a2020-10-14 17:22:10478 absl::string_view data) {
Ryan Hamilton7505eb92019-06-08 00:22:17479 return client_maker_.MakeDataPacket(packet_number, stream_id_,
480 should_include_version, fin, data);
alyssar2adf3ac2016-05-03 17:12:58481 }
482
Ryan Hamilton8d9ee76e2018-05-29 23:52:52483 std::unique_ptr<quic::QuicReceivedPacket> ConstructServerDataPacket(
Fan Yangac867502019-01-28 21:10:23484 uint64_t packet_number,
alyssar2adf3ac2016-05-03 17:12:58485 bool should_include_version,
486 bool fin,
Victor Vasiliev47ecb6a2020-10-14 17:22:10487 absl::string_view data) {
Ryan Hamilton7505eb92019-06-08 00:22:17488 return server_maker_.MakeDataPacket(packet_number, stream_id_,
489 should_include_version, fin, data);
ckrasic3865ee0f2016-02-29 22:04:56490 }
491
Ryan Hamilton8d9ee76e2018-05-29 23:52:52492 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23493 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52494 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56495 bool should_include_version,
496 bool fin,
497 RequestPriority request_priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02498 size_t* spdy_headers_frame_length) {
Yixin Wang7a3f1b8d2018-01-17 21:40:48499 return InnerConstructRequestHeadersPacket(
500 packet_number, stream_id, should_include_version, fin, request_priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02501 0, spdy_headers_frame_length);
Yixin Wang7a3f1b8d2018-01-17 21:40:48502 }
503
Ryan Hamilton8d9ee76e2018-05-29 23:52:52504 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23505 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52506 quic::QuicStreamId stream_id,
Yixin Wang7a3f1b8d2018-01-17 21:40:48507 bool should_include_version,
508 bool fin,
509 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52510 quic::QuicStreamId parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02511 size_t* spdy_headers_frame_length) {
Ryan Hamilton0239aac2018-05-19 00:03:13512 spdy::SpdyPriority priority =
ckrasic3865ee0f2016-02-29 22:04:56513 ConvertRequestPriorityToQuicPriority(request_priority);
alyssar2adf3ac2016-05-03 17:12:58514 return client_maker_.MakeRequestHeadersPacket(
ckrasic3865ee0f2016-02-29 22:04:56515 packet_number, stream_id, should_include_version, fin, priority,
Yixin Wang7a3f1b8d2018-01-17 21:40:48516 std::move(request_headers_), parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02517 spdy_headers_frame_length);
[email protected]f702d572012-12-04 15:56:20518 }
519
Ryan Hamilton8d9ee76e2018-05-29 23:52:52520 std::unique_ptr<quic::QuicReceivedPacket>
Yixin Wange7ecc472018-03-06 19:00:25521 ConstructRequestHeadersAndDataFramesPacket(
Fan Yangac867502019-01-28 21:10:23522 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52523 quic::QuicStreamId stream_id,
Yixin Wange7ecc472018-03-06 19:00:25524 bool should_include_version,
525 bool fin,
526 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52527 quic::QuicStreamId parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25528 size_t* spdy_headers_frame_length,
529 const std::vector<std::string>& data_writes) {
Ryan Hamilton0239aac2018-05-19 00:03:13530 spdy::SpdyPriority priority =
Yixin Wange7ecc472018-03-06 19:00:25531 ConvertRequestPriorityToQuicPriority(request_priority);
532 return client_maker_.MakeRequestHeadersAndMultipleDataFramesPacket(
533 packet_number, stream_id, should_include_version, fin, priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02534 std::move(request_headers_), parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25535 spdy_headers_frame_length, data_writes);
536 }
537
Ryan Hamilton8d9ee76e2018-05-29 23:52:52538 std::unique_ptr<quic::QuicReceivedPacket> ConstructRequestAndRstPacket(
Fan Yangac867502019-01-28 21:10:23539 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52540 quic::QuicStreamId stream_id,
Yixin Wange7ecc472018-03-06 19:00:25541 bool should_include_version,
542 bool fin,
543 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52544 quic::QuicStreamId parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25545 size_t* spdy_headers_frame_length,
Ryan Hamiltonb5d4c5a2019-06-21 22:08:41546 quic::QuicRstStreamErrorCode error_code) {
Ryan Hamilton0239aac2018-05-19 00:03:13547 spdy::SpdyPriority priority =
Yixin Wange7ecc472018-03-06 19:00:25548 ConvertRequestPriorityToQuicPriority(request_priority);
549 return client_maker_.MakeRequestHeadersAndRstPacket(
550 packet_number, stream_id, should_include_version, fin, priority,
551 std::move(request_headers_), parent_stream_id,
Ryan Hamiltonb5d4c5a2019-06-21 22:08:41552 spdy_headers_frame_length, error_code);
Yixin Wange7ecc472018-03-06 19:00:25553 }
554
Ryan Hamilton8d9ee76e2018-05-29 23:52:52555 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructResponseHeadersPacket(
Fan Yangac867502019-01-28 21:10:23556 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52557 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56558 bool fin,
559 size_t* spdy_headers_frame_length) {
alyssar2adf3ac2016-05-03 17:12:58560 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26561 packet_number, stream_id, !kIncludeVersion, fin,
Ryan Hamilton0d65a8c2019-06-07 00:46:02562 std::move(response_headers_), spdy_headers_frame_length);
[email protected]1e960032013-12-20 19:00:20563 }
564
Ryan Hamilton8d9ee76e2018-05-29 23:52:52565 std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseHeadersPacket(
Fan Yangac867502019-01-28 21:10:23566 uint64_t packet_number,
sclittlec4dc1a32015-09-24 00:15:45567 bool fin,
568 size_t* spdy_headers_frame_length) {
ckrasic3865ee0f2016-02-29 22:04:56569 return InnerConstructResponseHeadersPacket(packet_number, stream_id_, fin,
570 spdy_headers_frame_length);
[email protected]1e960032013-12-20 19:00:20571 }
572
Ryan Hamilton8d9ee76e2018-05-29 23:52:52573 std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseTrailersPacket(
Fan Yangac867502019-01-28 21:10:23574 uint64_t packet_number,
xunjieli34291fe12016-03-02 13:58:38575 bool fin,
Bence Béky4c325e52020-10-22 20:48:01576 spdy::Http2HeaderBlock trailers,
Ryan Hamilton0d65a8c2019-06-07 00:46:02577 size_t* spdy_headers_frame_length) {
alyssar2adf3ac2016-05-03 17:12:58578 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26579 packet_number, stream_id_, !kIncludeVersion, fin, std::move(trailers),
Ryan Hamilton0d65a8c2019-06-07 00:46:02580 spdy_headers_frame_length);
xunjieli34291fe12016-03-02 13:58:38581 }
582
Ryan Hamilton8d9ee76e2018-05-29 23:52:52583 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientRstStreamErrorPacket(
Fan Yangac867502019-01-28 21:10:23584 uint64_t packet_number,
maksim.sisov84e20c92016-06-23 08:49:34585 bool include_version) {
586 return client_maker_.MakeRstPacket(packet_number, include_version,
587 stream_id_,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52588 quic::QUIC_ERROR_PROCESSING_STREAM);
maksim.sisov84e20c92016-06-23 08:49:34589 }
590
Ryan Hamilton8d9ee76e2018-05-29 23:52:52591 std::unique_ptr<quic::QuicReceivedPacket> ConstructAckAndRstStreamPacket(
Fan Yangac867502019-01-28 21:10:23592 uint64_t packet_number) {
Renjie Tangcd594f32020-07-11 20:18:34593 return client_maker_.MakeAckAndRstPacket(packet_number, !kIncludeVersion,
594 stream_id_,
595 quic::QUIC_STREAM_CANCELLED, 2, 1);
[email protected]c5e1aca2014-01-30 04:03:04596 }
597
Ryan Hamilton8d9ee76e2018-05-29 23:52:52598 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientAckPacket(
Fan Yangac867502019-01-28 21:10:23599 uint64_t packet_number,
600 uint64_t largest_received,
Renjie Tangcd594f32020-07-11 20:18:34601 uint64_t smallest_received) {
alyssar2adf3ac2016-05-03 17:12:58602 return client_maker_.MakeAckPacket(packet_number, largest_received,
Renjie Tangcd594f32020-07-11 20:18:34603 smallest_received);
alyssar2adf3ac2016-05-03 17:12:58604 }
605
Ryan Hamilton8d9ee76e2018-05-29 23:52:52606 std::unique_ptr<quic::QuicReceivedPacket> ConstructServerAckPacket(
Fan Yangac867502019-01-28 21:10:23607 uint64_t packet_number,
608 uint64_t largest_received,
609 uint64_t smallest_received,
610 uint64_t least_unacked) {
alyssar2adf3ac2016-05-03 17:12:58611 return server_maker_.MakeAckPacket(packet_number, largest_received,
Bence Béky7a45d4d2020-05-08 01:59:23612 smallest_received, least_unacked);
[email protected]63534512012-12-23 18:49:00613 }
614
Ryan Hamilton0d65a8c2019-06-07 00:46:02615 std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket() {
616 return client_maker_.MakeInitialSettingsPacket(1);
fayang3bcb8b502016-12-07 21:44:37617 }
618
Renjie Tangaadb84b2019-08-31 01:00:23619 std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket(
620 int packet_number) {
621 return client_maker_.MakeInitialSettingsPacket(packet_number);
622 }
623
Victor Vasiliev076657c2019-03-12 02:46:43624 std::string ConstructDataHeader(size_t body_len) {
Nick Harperc6cb7a612020-02-24 20:03:32625 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:41626 return "";
627 }
Ian Swett17d4d1c02021-06-08 19:52:41628 quic::QuicBuffer buffer = quic::HttpEncoder::SerializeDataFrameHeader(
629 body_len, quic::SimpleBufferAllocator::Get());
630 return std::string(buffer.data(), buffer.size());
Renjief49758b2019-01-11 23:32:41631 }
632
Ryan Hamilton8d9ee76e2018-05-29 23:52:52633 void ReceivePromise(quic::QuicStreamId id) {
634 auto headers = quic::test::AsHeaderList(push_promise_);
rch08e198572017-05-09 16:56:55635 QuicChromiumClientStream::Handle* stream =
ckrasic3865ee0f2016-02-29 22:04:56636 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
ckrasic32b17dcd2016-10-31 06:15:35637 stream->OnPromiseHeaderList(id, headers.uncompressed_header_bytes(),
638 headers);
ckrasic3865ee0f2016-02-29 22:04:56639 }
640
xunjieli84adaab2016-09-20 01:12:28641 void ExpectLoadTimingValid(const LoadTimingInfo& load_timing_info,
xunjieli100937eb52016-09-15 20:09:37642 bool session_reused) {
643 EXPECT_EQ(session_reused, load_timing_info.socket_reused);
xunjieli84adaab2016-09-20 01:12:28644 if (session_reused) {
645 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
646 } else {
647 ExpectConnectTimingHasTimes(
648 load_timing_info.connect_timing,
649 CONNECT_TIMING_HAS_SSL_TIMES | CONNECT_TIMING_HAS_DNS_TIMES);
650 }
651 ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info);
xunjieli100937eb52016-09-15 20:09:37652 }
653
Fan Yang32c5a112018-12-10 20:06:33654 quic::QuicStreamId GetNthClientInitiatedBidirectionalStreamId(int n) {
Nick Harper23290b82019-05-02 00:02:56655 return quic::test::GetNthClientInitiatedBidirectionalStreamId(
656 version_.transport_version, n);
ckrasicbf2f59c2017-05-04 23:54:36657 }
658
Fan Yang32c5a112018-12-10 20:06:33659 quic::QuicStreamId GetNthServerInitiatedUnidirectionalStreamId(int n) {
Nick Harper23290b82019-05-02 00:02:56660 return quic::test::GetNthServerInitiatedUnidirectionalStreamId(
661 version_.transport_version, n);
ckrasicbf2f59c2017-05-04 23:54:36662 }
663
Ryan Hamiltona1d1f4a2019-06-26 14:43:04664 QuicFlagSaver saver_;
665
Nick Harper23290b82019-05-02 00:02:56666 const quic::ParsedQuicVersion version_;
Yixin Wang079ad542018-01-11 04:06:05667 const bool client_headers_include_h2_stream_dependency_;
668
Matt Reichhoff0049a0b72021-10-20 20:44:26669 NetLogWithSource net_log_with_source_{
670 NetLogWithSource::Make(NetLog::Get(), NetLogSourceType::NONE)};
671 RecordingNetLogObserver net_log_observer_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52672 quic::test::MockSendAlgorithm* send_algorithm_;
[email protected]f702d572012-12-04 15:56:20673 scoped_refptr<TestTaskRunner> runner_;
danakjad1777e2016-04-16 00:56:42674 std::unique_ptr<MockWrite[]> mock_writes_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52675 quic::MockClock clock_;
[email protected]f702d572012-12-04 15:56:20676 TestQuicConnection* connection_;
danakjad1777e2016-04-16 00:56:42677 std::unique_ptr<QuicChromiumConnectionHelper> helper_;
rch16c74d1d2016-04-22 06:14:07678 std::unique_ptr<QuicChromiumAlarmFactory> alarm_factory_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52679 testing::StrictMock<quic::test::MockQuicConnectionVisitor> visitor_;
rch97827ee2017-05-24 23:49:12680 std::unique_ptr<UploadDataStream> upload_data_stream_;
danakjad1777e2016-04-16 00:56:42681 std::unique_ptr<QuicHttpStream> stream_;
[email protected]5db452202014-08-19 05:22:15682 TransportSecurityState transport_security_state_;
danakjad1777e2016-04-16 00:56:42683 std::unique_ptr<QuicChromiumClientSession> session_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52684 quic::QuicCryptoClientConfig crypto_config_;
[email protected]f702d572012-12-04 15:56:20685 TestCompletionCallback callback_;
686 HttpRequestInfo request_;
687 HttpRequestHeaders headers_;
688 HttpResponseInfo response_;
689 scoped_refptr<IOBufferWithSize> read_buffer_;
Bence Béky4c325e52020-10-22 20:48:01690 spdy::Http2HeaderBlock request_headers_;
691 spdy::Http2HeaderBlock response_headers_;
bnc614a92d32016-04-04 13:56:07692 string request_data_;
693 string response_data_;
[email protected]f702d572012-12-04 15:56:20694
ckrasic3865ee0f2016-02-29 22:04:56695 // For server push testing
danakjad1777e2016-04-16 00:56:42696 std::unique_ptr<QuicHttpStream> promised_stream_;
Bence Béky4c325e52020-10-22 20:48:01697 spdy::Http2HeaderBlock push_promise_;
698 spdy::Http2HeaderBlock promised_response_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52699 const quic::QuicStreamId promise_id_;
ckrasic3865ee0f2016-02-29 22:04:56700 string promise_url_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52701 const quic::QuicStreamId stream_id_;
ckrasic3865ee0f2016-02-29 22:04:56702
Ryan Hamilton8d9ee76e2018-05-29 23:52:52703 const quic::QuicConnectionId connection_id_;
alyssar2adf3ac2016-05-03 17:12:58704 QuicTestPacketMaker client_maker_;
705 QuicTestPacketMaker server_maker_;
[email protected]f702d572012-12-04 15:56:20706 IPEndPoint self_addr_;
707 IPEndPoint peer_addr_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52708 quic::test::MockRandom random_generator_;
rch03b7a202016-02-05 00:54:20709 ProofVerifyDetailsChromium verify_details_;
[email protected]e8ff26842013-03-22 21:02:05710 MockCryptoClientStreamFactory crypto_client_stream_factory_;
danakjad1777e2016-04-16 00:56:42711 std::unique_ptr<StaticSocketDataProvider> socket_data_;
Ryan Hamilton0d65a8c2019-06-07 00:46:02712 QuicPacketPrinter printer_;
[email protected]f702d572012-12-04 15:56:20713 std::vector<PacketToWrite> writes_;
Bence Béky6e243aa2019-12-13 19:01:07714 quic::test::NoopQpackStreamSenderDelegate noop_qpack_stream_sender_delegate_;
[email protected]f702d572012-12-04 15:56:20715};
716
David Schinazi09e9a6012019-10-03 17:37:57717INSTANTIATE_TEST_SUITE_P(VersionIncludeStreamDependencySequence,
718 QuicHttpStreamTest,
719 ::testing::ValuesIn(GetTestParams()),
720 ::testing::PrintToStringParamName());
[email protected]1e960032013-12-20 19:00:20721
722TEST_P(QuicHttpStreamTest, RenewStreamForAuth) {
[email protected]ed3fc15d2013-03-08 18:37:44723 Initialize();
rtennetibe635732014-10-02 22:51:42724 EXPECT_EQ(nullptr, stream_->RenewStreamForAuth());
[email protected]f702d572012-12-04 15:56:20725}
726
mmenkebd84c392015-09-02 14:12:34727TEST_P(QuicHttpStreamTest, CanReuseConnection) {
[email protected]ed3fc15d2013-03-08 18:37:44728 Initialize();
mmenkebd84c392015-09-02 14:12:34729 EXPECT_FALSE(stream_->CanReuseConnection());
[email protected]f702d572012-12-04 15:56:20730}
731
jri231c2972016-03-08 19:50:11732TEST_P(QuicHttpStreamTest, DisableConnectionMigrationForStream) {
Zhongyi Shibb28b1f2018-07-18 02:41:26733 request_.load_flags |= LOAD_DISABLE_CONNECTION_MIGRATION_TO_CELLULAR;
jri231c2972016-03-08 19:50:11734 Initialize();
Matt Reichhoff0049a0b72021-10-20 20:44:26735 EXPECT_EQ(OK, stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
736 net_log_with_source_,
737 callback_.callback()));
rch08e198572017-05-09 16:56:55738 QuicChromiumClientStream::Handle* client_stream =
jri231c2972016-03-08 19:50:11739 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
Zhongyi Shibb28b1f2018-07-18 02:41:26740 EXPECT_FALSE(client_stream->can_migrate_to_cellular_network());
jri231c2972016-03-08 19:50:11741}
742
[email protected]1e960032013-12-20 19:00:20743TEST_P(QuicHttpStreamTest, GetRequest) {
744 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:45745 size_t spdy_request_header_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:23746 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:25747 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:23748 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:37749 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23750 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
751 kIncludeVersion, kFin, DEFAULT_PRIORITY,
752 &spdy_request_header_frame_length));
fayang3bcb8b502016-12-07 21:44:37753
[email protected]f702d572012-12-04 15:56:20754 Initialize();
755
756 request_.method = "GET";
rchcd379012017-04-12 21:53:32757 request_.url = GURL("https://www.example.org/");
[email protected]f702d572012-12-04 15:56:20758
xunjieli100937eb52016-09-15 20:09:37759 // Make sure getting load timing from the stream early does not crash.
760 LoadTimingInfo load_timing_info;
761 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
762
Matt Reichhoff0049a0b72021-10-20 20:44:26763 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
764 net_log_with_source_,
765 callback_.callback()));
rjshaded5ced072015-12-18 19:26:02766 EXPECT_EQ(OK,
767 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20768
769 // Ack the request.
Renjie90e808e2019-01-24 07:24:04770 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]f702d572012-12-04 15:56:20771
robpercival214763f2016-07-01 23:27:01772 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
773 IsError(ERR_IO_PENDING));
[email protected]f702d572012-12-04 15:56:20774
Kenichi Ishibashif8634ab2021-03-16 23:41:28775 SetResponse("404", string());
sclittlec4dc1a32015-09-24 00:15:45776 size_t spdy_response_header_frame_length;
777 ProcessPacket(ConstructResponseHeadersPacket(
778 2, kFin, &spdy_response_header_frame_length));
[email protected]f702d572012-12-04 15:56:20779
780 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:01781 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]cadac622013-06-11 16:46:36782 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:20783 EXPECT_EQ(404, response_.headers->response_code());
784 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
[email protected]6ed67432014-06-24 01:53:53785 EXPECT_FALSE(response_.response_time.is_null());
786 EXPECT_FALSE(response_.request_time.is_null());
[email protected]f702d572012-12-04 15:56:20787
788 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:02789 EXPECT_EQ(0,
790 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
791 callback_.callback()));
[email protected]f702d572012-12-04 15:56:20792 EXPECT_TRUE(stream_->IsResponseBodyComplete());
793 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:10794
xunjieli100937eb52016-09-15 20:09:37795 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
xunjieli84adaab2016-09-20 01:12:28796 ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
xunjieli100937eb52016-09-15 20:09:37797
sclittle1edeeb22015-09-02 20:46:10798 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:45799 // headers and payload.
800 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
801 stream_->GetTotalSentBytes());
802 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length),
803 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:20804}
805
xunjieli100937eb52016-09-15 20:09:37806TEST_P(QuicHttpStreamTest, LoadTimingTwoRequests) {
807 SetRequest("GET", "/", DEFAULT_PRIORITY);
808 size_t spdy_request_header_frame_length;
809
Renjie Tangaadb84b2019-08-31 01:00:23810 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:25811 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:23812 AddWrite(ConstructInitialSettingsPacket(packet_number++));
xunjieli100937eb52016-09-15 20:09:37813 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23814 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
815 kIncludeVersion, kFin, DEFAULT_PRIORITY,
816 &spdy_request_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37817
818 // SetRequest() again for second request as |request_headers_| was moved.
819 SetRequest("GET", "/", DEFAULT_PRIORITY);
820 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23821 packet_number++, GetNthClientInitiatedBidirectionalStreamId(1),
822 kIncludeVersion, kFin, DEFAULT_PRIORITY,
823 GetNthClientInitiatedBidirectionalStreamId(0),
Ryan Hamilton0d65a8c2019-06-07 00:46:02824 &spdy_request_header_frame_length));
Renjie Tangcd594f32020-07-11 20:18:34825 AddWrite(
826 ConstructClientAckPacket(packet_number++, 3, 1)); // Ack the responses.
xunjieli100937eb52016-09-15 20:09:37827
828 Initialize();
829
830 request_.method = "GET";
rchcd379012017-04-12 21:53:32831 request_.url = GURL("https://www.example.org/");
xunjieli100937eb52016-09-15 20:09:37832 // Start first request.
Matt Reichhoff0049a0b72021-10-20 20:44:26833 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
834 net_log_with_source_,
835 callback_.callback()));
xunjieli100937eb52016-09-15 20:09:37836 EXPECT_EQ(OK,
837 stream_->SendRequest(headers_, &response_, callback_.callback()));
838
839 // Start a second request.
Dan McArdle68a5f622021-07-09 20:56:53840 QuicHttpStream stream2(session_->CreateHandle(url::SchemeHostPort(
841 url::kHttpsScheme, "www.example.org", 443)),
842 {} /* dns_aliases */);
xunjieli100937eb52016-09-15 20:09:37843 TestCompletionCallback callback2;
Matt Reichhoff0049a0b72021-10-20 20:44:26844 EXPECT_EQ(
845 OK, stream2.InitializeStream(&request_, true, DEFAULT_PRIORITY,
846 net_log_with_source_, callback2.callback()));
xunjieli100937eb52016-09-15 20:09:37847 EXPECT_EQ(OK,
848 stream2.SendRequest(headers_, &response_, callback2.callback()));
849
850 // Ack both requests.
Renjie90e808e2019-01-24 07:24:04851 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
xunjieli100937eb52016-09-15 20:09:37852
853 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
854 IsError(ERR_IO_PENDING));
855 size_t spdy_response_header_frame_length;
Kenichi Ishibashif8634ab2021-03-16 23:41:28856 SetResponse("200", string());
xunjieli100937eb52016-09-15 20:09:37857 ProcessPacket(InnerConstructResponseHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33858 2, GetNthClientInitiatedBidirectionalStreamId(0), kFin,
ckrasicbf2f59c2017-05-04 23:54:36859 &spdy_response_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37860
861 // Now that the headers have been processed, the callback will return.
862 EXPECT_THAT(callback_.WaitForResult(), IsOk());
863 EXPECT_EQ(200, response_.headers->response_code());
864
865 // There is no body, so this should return immediately.
866 EXPECT_EQ(0,
867 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
868 callback_.callback()));
869 EXPECT_TRUE(stream_->IsResponseBodyComplete());
870
871 LoadTimingInfo load_timing_info;
872 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
xunjieli84adaab2016-09-20 01:12:28873 ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
xunjieli100937eb52016-09-15 20:09:37874
875 // SetResponse() again for second request as |response_headers_| was moved.
Kenichi Ishibashif8634ab2021-03-16 23:41:28876 SetResponse("200", string());
xunjieli100937eb52016-09-15 20:09:37877 EXPECT_THAT(stream2.ReadResponseHeaders(callback2.callback()),
878 IsError(ERR_IO_PENDING));
879
880 ProcessPacket(InnerConstructResponseHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33881 3, GetNthClientInitiatedBidirectionalStreamId(1), kFin,
ckrasicbf2f59c2017-05-04 23:54:36882 &spdy_response_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37883
884 EXPECT_THAT(callback2.WaitForResult(), IsOk());
885
886 // There is no body, so this should return immediately.
887 EXPECT_EQ(0,
888 stream2.ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
889 callback2.callback()));
890 EXPECT_TRUE(stream2.IsResponseBodyComplete());
891
892 LoadTimingInfo load_timing_info2;
893 EXPECT_TRUE(stream2.GetLoadTimingInfo(&load_timing_info2));
xunjieli84adaab2016-09-20 01:12:28894 ExpectLoadTimingValid(load_timing_info2, /*session_reused=*/true);
xunjieli100937eb52016-09-15 20:09:37895}
896
xunjieli34291fe12016-03-02 13:58:38897// QuicHttpStream does not currently support trailers. It should ignore
898// trailers upon receiving them.
899TEST_P(QuicHttpStreamTest, GetRequestWithTrailers) {
900 SetRequest("GET", "/", DEFAULT_PRIORITY);
901 size_t spdy_request_header_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:23902 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:25903 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:23904 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:37905 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23906 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
907 kIncludeVersion, kFin, DEFAULT_PRIORITY,
908 &spdy_request_header_frame_length));
Renjie Tangcd594f32020-07-11 20:18:34909 AddWrite(
910 ConstructClientAckPacket(packet_number++, 3, 1)); // Ack the data packet.
xunjieli34291fe12016-03-02 13:58:38911
912 Initialize();
913
914 request_.method = "GET";
rchcd379012017-04-12 21:53:32915 request_.url = GURL("https://www.example.org/");
xunjieli34291fe12016-03-02 13:58:38916
Matt Reichhoff0049a0b72021-10-20 20:44:26917 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
918 net_log_with_source_,
919 callback_.callback()));
xunjieli5fafe142016-03-23 23:32:54920
xunjieli34291fe12016-03-02 13:58:38921 EXPECT_EQ(OK,
922 stream_->SendRequest(headers_, &response_, callback_.callback()));
xunjieli34291fe12016-03-02 13:58:38923 // Ack the request.
Renjie90e808e2019-01-24 07:24:04924 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
xunjieli34291fe12016-03-02 13:58:38925
robpercival214763f2016-07-01 23:27:01926 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
927 IsError(ERR_IO_PENDING));
xunjieli34291fe12016-03-02 13:58:38928
Kenichi Ishibashif8634ab2021-03-16 23:41:28929 SetResponse("200", string());
xunjieli34291fe12016-03-02 13:58:38930
931 // Send the response headers.
932 size_t spdy_response_header_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:02933 ProcessPacket(ConstructResponseHeadersPacket(
934 2, !kFin, &spdy_response_header_frame_length));
xunjieli34291fe12016-03-02 13:58:38935 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:01936 EXPECT_THAT(callback_.WaitForResult(), IsOk());
xunjieli34291fe12016-03-02 13:58:38937 ASSERT_TRUE(response_.headers.get());
938 EXPECT_EQ(200, response_.headers->response_code());
939 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
940 EXPECT_FALSE(response_.response_time.is_null());
941 EXPECT_FALSE(response_.request_time.is_null());
942
943 // Send the response body.
944 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:43945 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:17946 ProcessPacket(
947 ConstructServerDataPacket(3, false, !kFin, header + kResponseBody));
Bence Béky4c325e52020-10-22 20:48:01948 spdy::Http2HeaderBlock trailers;
xunjieli34291fe12016-03-02 13:58:38949 size_t spdy_trailers_frame_length;
950 trailers["foo"] = "bar";
Victor Vasiliev7da08172019-10-14 06:04:25951 if (!quic::VersionUsesHttp3(version_.transport_version)) {
Ryan Hamiltona1d1f4a2019-06-26 14:43:04952 trailers[quic::kFinalOffsetHeaderKey] =
953 base::NumberToString(strlen(kResponseBody) + header.length());
954 }
Ryan Hamilton0d65a8c2019-06-07 00:46:02955 ProcessPacket(ConstructResponseTrailersPacket(4, kFin, std::move(trailers),
956 &spdy_trailers_frame_length));
xunjieli34291fe12016-03-02 13:58:38957
958 // Make sure trailers are processed.
fdoray92e35a72016-06-10 15:54:55959 base::RunLoop().RunUntilIdle();
xunjieli34291fe12016-03-02 13:58:38960
961 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
962 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
963 callback_.callback()));
964 EXPECT_TRUE(stream_->IsResponseBodyComplete());
965
966 EXPECT_EQ(OK,
967 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
968 callback_.callback()));
969
970 EXPECT_TRUE(stream_->IsResponseBodyComplete());
971 EXPECT_TRUE(AtEof());
972
973 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
974 // headers and payload.
975 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
976 stream_->GetTotalSentBytes());
Renjief49758b2019-01-11 23:32:41977 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length +
978 strlen(kResponseBody) + header.length() +
979 +spdy_trailers_frame_length),
980 stream_->GetTotalReceivedBytes());
xunjieli5fafe142016-03-23 23:32:54981 // Check that NetLog was filled as expected.
Matt Reichhoff0049a0b72021-10-20 20:44:26982 auto entries = net_log_observer_.GetEntries();
xunjieli5fafe142016-03-23 23:32:54983 size_t pos = ExpectLogContainsSomewhere(
984 entries, /*min_offset=*/0,
mikecirone8b85c432016-09-08 19:11:00985 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
986 NetLogEventPhase::NONE);
xunjieli5fafe142016-03-23 23:32:54987 pos = ExpectLogContainsSomewhere(
988 entries, /*min_offset=*/pos,
mikecirone8b85c432016-09-08 19:11:00989 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
990 NetLogEventPhase::NONE);
xunjieli5fafe142016-03-23 23:32:54991 ExpectLogContainsSomewhere(
992 entries, /*min_offset=*/pos,
mikecirone8b85c432016-09-08 19:11:00993 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
994 NetLogEventPhase::NONE);
xunjieli34291fe12016-03-02 13:58:38995}
996
Bence Béky6c2c78f2020-08-28 16:49:06997TEST_P(QuicHttpStreamTest, ElideHeadersInNetLog) {
998 Initialize();
999
1000 // QuicHttp3Logger is only used with HTTP/3.
1001 if (!VersionUsesHttp3(version_.transport_version)) {
1002 return;
1003 }
1004
Matt Reichhoff0049a0b72021-10-20 20:44:261005 net_log_observer_.SetObserverCaptureMode(NetLogCaptureMode::kDefault);
Bence Béky6c2c78f2020-08-28 16:49:061006
Bence Békye0d3747d2020-08-28 23:16:401007 // Send first request.
Bence Béky6c2c78f2020-08-28 16:49:061008 SetRequest("GET", "/", DEFAULT_PRIORITY);
1009 request_.method = "GET";
1010 request_.url = GURL("https://www.example.org/");
1011 headers_.SetHeader(HttpRequestHeaders::kCookie, "secret");
1012
1013 size_t spdy_request_header_frame_length;
Bence Békye0d3747d2020-08-28 23:16:401014 int outgoing_packet_number = 1;
1015 AddWrite(ConstructInitialSettingsPacket(outgoing_packet_number++));
Bence Béky6c2c78f2020-08-28 16:49:061016 AddWrite(InnerConstructRequestHeadersPacket(
Bence Békye0d3747d2020-08-28 23:16:401017 outgoing_packet_number++, stream_id_, kIncludeVersion, kFin,
1018 DEFAULT_PRIORITY, &spdy_request_header_frame_length));
Bence Béky6c2c78f2020-08-28 16:49:061019
Matt Reichhoff0049a0b72021-10-20 20:44:261020 EXPECT_THAT(
1021 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
1022 net_log_with_source_, callback_.callback()),
1023 IsOk());
Bence Béky6c2c78f2020-08-28 16:49:061024 EXPECT_THAT(stream_->SendRequest(headers_, &response_, callback_.callback()),
1025 IsOk());
Bence Békye0d3747d2020-08-28 23:16:401026 int incoming_packet_number = 1;
1027 ProcessPacket(ConstructServerAckPacket(incoming_packet_number++, 1, 1,
1028 1)); // Ack the request.
Bence Béky6c2c78f2020-08-28 16:49:061029
Bence Békye0d3747d2020-08-28 23:16:401030 // Process first response.
Kenichi Ishibashif8634ab2021-03-16 23:41:281031 SetResponse("200", string());
Bence Béky6c2c78f2020-08-28 16:49:061032 response_headers_["set-cookie"] = "secret";
1033 size_t spdy_response_header_frame_length;
1034 ProcessPacket(ConstructResponseHeadersPacket(
Bence Békye0d3747d2020-08-28 23:16:401035 incoming_packet_number++, kFin, &spdy_response_header_frame_length));
Bence Béky6c2c78f2020-08-28 16:49:061036 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
Bence Béky6c2c78f2020-08-28 16:49:061037
1038 ASSERT_TRUE(response_.headers.get());
1039 EXPECT_EQ(200, response_.headers->response_code());
1040 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1041 EXPECT_TRUE(response_.headers->HasHeaderValue("set-cookie", "secret"));
1042
Matt Reichhoff0049a0b72021-10-20 20:44:261043 net_log_observer_.SetObserverCaptureMode(
1044 NetLogCaptureMode::kIncludeSensitive);
Bence Béky6c2c78f2020-08-28 16:49:061045
Bence Békye0d3747d2020-08-28 23:16:401046 // Send second request.
1047 quic::QuicStreamId stream_id = GetNthClientInitiatedBidirectionalStreamId(1);
1048 request_.url = GURL("https://www.example.org/foo");
Bence Béky6c2c78f2020-08-28 16:49:061049
Bence Békye0d3747d2020-08-28 23:16:401050 AddWrite(InnerConstructRequestHeadersPacket(
1051 outgoing_packet_number++, stream_id, kIncludeVersion, kFin,
1052 DEFAULT_PRIORITY, &spdy_request_header_frame_length));
Bence Béky6c2c78f2020-08-28 16:49:061053
Bence Békye0d3747d2020-08-28 23:16:401054 auto stream = std::make_unique<QuicHttpStream>(
Dan McArdle68a5f622021-07-09 20:56:531055 session_->CreateHandle(
1056 url::SchemeHostPort(url::kHttpsScheme, "www.example.org/foo", 443)),
Cammie Smith Barnes0f38aff2021-03-02 23:14:351057 std::vector<std::string>() /* dns_aliases */);
Matt Reichhoff0049a0b72021-10-20 20:44:261058 EXPECT_THAT(
1059 stream->InitializeStream(&request_, true, DEFAULT_PRIORITY,
1060 net_log_with_source_, callback_.callback()),
1061 IsOk());
Bence Békye0d3747d2020-08-28 23:16:401062 EXPECT_THAT(stream->SendRequest(headers_, &response_, callback_.callback()),
1063 IsOk());
1064 ProcessPacket(ConstructServerAckPacket(incoming_packet_number++, 1, 1,
1065 1)); // Ack the request.
Bence Béky6c2c78f2020-08-28 16:49:061066
Bence Békye0d3747d2020-08-28 23:16:401067 // Process second response.
Kenichi Ishibashif8634ab2021-03-16 23:41:281068 SetResponse("200", string());
Bence Békye0d3747d2020-08-28 23:16:401069 response_headers_["set-cookie"] = "secret";
1070 ProcessPacket(InnerConstructResponseHeadersPacket(
1071 incoming_packet_number++, stream_id, kFin,
1072 &spdy_response_header_frame_length));
1073 EXPECT_THAT(stream->ReadResponseHeaders(callback_.callback()), IsOk());
Bence Béky6c2c78f2020-08-28 16:49:061074
Bence Békye0d3747d2020-08-28 23:16:401075 ASSERT_TRUE(response_.headers.get());
1076 EXPECT_EQ(200, response_.headers->response_code());
1077 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1078 EXPECT_TRUE(response_.headers->HasHeaderValue("set-cookie", "secret"));
1079
1080 EXPECT_TRUE(AtEof());
1081
1082 // Check that sensitive header value were stripped
1083 // for the first transaction (logged with NetLogCaptureMode::kDefault)
1084 // but not for the second (logged with NetLogCaptureMode::kIncludeSensitive).
1085 auto entries =
Matt Reichhoff0049a0b72021-10-20 20:44:261086 net_log_observer_.GetEntriesWithType(NetLogEventType::HTTP3_HEADERS_SENT);
Bence Békye0d3747d2020-08-28 23:16:401087 ASSERT_EQ(2u, entries.size());
1088 EXPECT_TRUE(
1089 CheckHeader(entries[0].params, "cookie", "[6 bytes were stripped]"));
1090 EXPECT_TRUE(CheckHeader(entries[1].params, "cookie", "secret"));
1091
Matt Reichhoff0049a0b72021-10-20 20:44:261092 entries = net_log_observer_.GetEntriesWithType(
1093 NetLogEventType::HTTP3_HEADERS_DECODED);
Bence Békye0d3747d2020-08-28 23:16:401094 ASSERT_EQ(2u, entries.size());
1095 EXPECT_TRUE(
1096 CheckHeader(entries[0].params, "set-cookie", "[6 bytes were stripped]"));
1097 EXPECT_TRUE(CheckHeader(entries[1].params, "set-cookie", "secret"));
Bence Béky6c2c78f2020-08-28 16:49:061098}
1099
[email protected]3e7dca62013-09-10 16:14:231100// Regression test for http://crbug.com/288128
[email protected]1e960032013-12-20 19:00:201101TEST_P(QuicHttpStreamTest, GetRequestLargeResponse) {
1102 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451103 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231104 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251105 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231106 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371107 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231108 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1109 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1110 &spdy_request_headers_frame_length));
[email protected]3e7dca62013-09-10 16:14:231111 Initialize();
1112
1113 request_.method = "GET";
rchcd379012017-04-12 21:53:321114 request_.url = GURL("https://www.example.org/");
[email protected]3e7dca62013-09-10 16:14:231115
Matt Reichhoff0049a0b72021-10-20 20:44:261116 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
1117 net_log_with_source_,
1118 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021119 EXPECT_EQ(OK,
1120 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:231121
1122 // Ack the request.
Renjie90e808e2019-01-24 07:24:041123 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]3e7dca62013-09-10 16:14:231124
robpercival214763f2016-07-01 23:27:011125 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1126 IsError(ERR_IO_PENDING));
[email protected]3e7dca62013-09-10 16:14:231127
Kenichi Ishibashif8634ab2021-03-16 23:41:281128 response_headers_[":status"] = "200";
bnc086b39e12016-06-24 13:05:261129 response_headers_[":version"] = "HTTP/1.1";
1130 response_headers_["content-type"] = "text/plain";
1131 response_headers_["big6"] = string(1000, 'x'); // Lots of x's.
[email protected]3e7dca62013-09-10 16:14:231132
sclittlec4dc1a32015-09-24 00:15:451133 size_t spdy_response_headers_frame_length;
1134 ProcessPacket(ConstructResponseHeadersPacket(
1135 2, kFin, &spdy_response_headers_frame_length));
[email protected]3e7dca62013-09-10 16:14:231136
1137 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:011138 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]3e7dca62013-09-10 16:14:231139 ASSERT_TRUE(response_.headers.get());
1140 EXPECT_EQ(200, response_.headers->response_code());
1141 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1142
1143 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:021144 EXPECT_EQ(0,
1145 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1146 callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:231147 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1148 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101149
1150 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451151 // headers and payload.
1152 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1153 stream_->GetTotalSentBytes());
1154 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length),
1155 stream_->GetTotalReceivedBytes());
[email protected]3e7dca62013-09-10 16:14:231156}
1157
rchf9f103cbc2014-08-30 05:28:041158// Regression test for http://crbug.com/409101
1159TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendRequest) {
1160 SetRequest("GET", "/", DEFAULT_PRIORITY);
1161 Initialize();
1162
1163 request_.method = "GET";
rchcd379012017-04-12 21:53:321164 request_.url = GURL("https://www.example.org/");
rchf9f103cbc2014-08-30 05:28:041165
Matt Reichhoff0049a0b72021-10-20 20:44:261166 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
1167 net_log_with_source_,
1168 callback_.callback()));
rchf9f103cbc2014-08-30 05:28:041169
jri78ec06a2016-03-31 18:19:401170 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521171 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rchf9f103cbc2014-08-30 05:28:041172
1173 EXPECT_EQ(ERR_CONNECTION_CLOSED,
rjshaded5ced072015-12-18 19:26:021174 stream_->SendRequest(headers_, &response_, callback_.callback()));
sclittle1edeeb22015-09-02 20:46:101175
1176 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1177 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rchf9f103cbc2014-08-30 05:28:041178}
1179
rch03b7a202016-02-05 00:54:201180// Regression test for http://crbug.com/584441
1181TEST_P(QuicHttpStreamTest, GetSSLInfoAfterSessionClosed) {
1182 SetRequest("GET", "/", DEFAULT_PRIORITY);
1183 Initialize();
1184
1185 request_.method = "GET";
rchcd379012017-04-12 21:53:321186 request_.url = GURL("https://www.example.org/");
rch03b7a202016-02-05 00:54:201187
Matt Reichhoff0049a0b72021-10-20 20:44:261188 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
1189 net_log_with_source_,
1190 callback_.callback()));
rch03b7a202016-02-05 00:54:201191
1192 SSLInfo ssl_info;
rch11565e02016-02-09 20:13:471193 EXPECT_FALSE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:201194 stream_->GetSSLInfo(&ssl_info);
rch11565e02016-02-09 20:13:471195 EXPECT_TRUE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:201196
jri78ec06a2016-03-31 18:19:401197 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521198 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rch03b7a202016-02-05 00:54:201199
rch11565e02016-02-09 20:13:471200 SSLInfo ssl_info2;
1201 stream_->GetSSLInfo(&ssl_info2);
1202 EXPECT_TRUE(ssl_info2.is_valid());
rch03b7a202016-02-05 00:54:201203}
1204
rchcd379012017-04-12 21:53:321205TEST_P(QuicHttpStreamTest, GetAlternativeService) {
1206 SetRequest("GET", "/", DEFAULT_PRIORITY);
1207 Initialize();
1208
1209 request_.method = "GET";
1210 request_.url = GURL("https://www.example.org/");
1211
Matt Reichhoff0049a0b72021-10-20 20:44:261212 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
1213 net_log_with_source_,
1214 callback_.callback()));
rchcd379012017-04-12 21:53:321215
1216 AlternativeService alternative_service;
1217 EXPECT_TRUE(stream_->GetAlternativeService(&alternative_service));
1218 EXPECT_EQ(AlternativeService(kProtoQUIC, "www.example.org", 443),
1219 alternative_service);
1220
1221 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521222 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rchcd379012017-04-12 21:53:321223
1224 AlternativeService alternative_service2;
1225 EXPECT_TRUE(stream_->GetAlternativeService(&alternative_service2));
1226 EXPECT_EQ(AlternativeService(kProtoQUIC, "www.example.org", 443),
1227 alternative_service2);
1228}
1229
zhongyica364fbb2015-12-12 03:39:121230TEST_P(QuicHttpStreamTest, LogGranularQuicConnectionError) {
1231 SetRequest("GET", "/", DEFAULT_PRIORITY);
1232 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231233 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251234 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231235 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371236 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231237 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1238 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1239 &spdy_request_headers_frame_length));
fayang3bcb8b502016-12-07 21:44:371240 AddWrite(ConstructAckAndRstStreamPacket(3));
zhongyica364fbb2015-12-12 03:39:121241 Initialize();
1242
1243 request_.method = "GET";
rchcd379012017-04-12 21:53:321244 request_.url = GURL("https://www.example.org/");
zhongyica364fbb2015-12-12 03:39:121245
Matt Reichhoff0049a0b72021-10-20 20:44:261246 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
1247 net_log_with_source_,
1248 callback_.callback()));
zhongyica364fbb2015-12-12 03:39:121249 EXPECT_EQ(OK,
1250 stream_->SendRequest(headers_, &response_, callback_.callback()));
1251
1252 // Ack the request.
Renjie90e808e2019-01-24 07:24:041253 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011254 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1255 IsError(ERR_IO_PENDING));
zhongyica364fbb2015-12-12 03:39:121256
Ryan Hamilton8d9ee76e2018-05-29 23:52:521257 quic::QuicConnectionCloseFrame frame;
Zhongyi Shica576df2019-04-12 17:43:401258 frame.quic_error_code = quic::QUIC_PEER_GOING_AWAY;
rch1c5b74a2016-06-23 22:10:551259 session_->connection()->OnConnectionCloseFrame(frame);
zhongyica364fbb2015-12-12 03:39:121260
1261 NetErrorDetails details;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521262 EXPECT_EQ(quic::QUIC_NO_ERROR, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121263 stream_->PopulateNetErrorDetails(&details);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521264 EXPECT_EQ(quic::QUIC_PEER_GOING_AWAY, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121265}
1266
Ryan Hamiltone316e482017-08-17 02:48:531267TEST_P(QuicHttpStreamTest, LogGranularQuicErrorIfHandshakeNotConfirmed) {
rch617e0652017-04-26 17:57:511268 // By default the test setup defaults handshake to be confirmed. Manually set
1269 // it to be not confirmed.
rch617e0652017-04-26 17:57:511270 crypto_client_stream_factory_.set_handshake_mode(
Ryan Hamilton9835e662018-08-02 05:36:271271 MockCryptoClientStream::ZERO_RTT);
rch617e0652017-04-26 17:57:511272
zhongyica364fbb2015-12-12 03:39:121273 SetRequest("GET", "/", DEFAULT_PRIORITY);
1274 size_t spdy_request_headers_frame_length;
Michael Warres167db3e2019-03-01 21:38:031275 client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
Nick Harper057264a82019-09-12 23:33:491276 client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
1277 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251278 if (VersionUsesHttp3(version_.transport_version))
Nick Harper057264a82019-09-12 23:33:491279 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371280 AddWrite(InnerConstructRequestHeadersPacket(
Nick Harper057264a82019-09-12 23:33:491281 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1282 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1283 &spdy_request_headers_frame_length));
zhongyica364fbb2015-12-12 03:39:121284 Initialize();
1285
1286 request_.method = "GET";
rchcd379012017-04-12 21:53:321287 request_.url = GURL("https://www.example.org/");
zhongyica364fbb2015-12-12 03:39:121288
Matt Reichhoff0049a0b72021-10-20 20:44:261289 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
1290 net_log_with_source_,
1291 callback_.callback()));
zhongyica364fbb2015-12-12 03:39:121292 EXPECT_EQ(OK,
1293 stream_->SendRequest(headers_, &response_, callback_.callback()));
1294
1295 // Ack the request.
Renjie90e808e2019-01-24 07:24:041296 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011297 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1298 IsError(ERR_IO_PENDING));
zhongyica364fbb2015-12-12 03:39:121299
Ryan Hamilton8d9ee76e2018-05-29 23:52:521300 quic::QuicConnectionCloseFrame frame;
Zhongyi Shica576df2019-04-12 17:43:401301 frame.quic_error_code = quic::QUIC_PEER_GOING_AWAY;
rch1c5b74a2016-06-23 22:10:551302 session_->connection()->OnConnectionCloseFrame(frame);
zhongyica364fbb2015-12-12 03:39:121303
1304 NetErrorDetails details;
zhongyica364fbb2015-12-12 03:39:121305 stream_->PopulateNetErrorDetails(&details);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521306 EXPECT_EQ(quic::QUIC_PEER_GOING_AWAY, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121307}
1308
rch11a114a2014-09-04 23:41:591309// Regression test for http://crbug.com/409871
1310TEST_P(QuicHttpStreamTest, SessionClosedBeforeReadResponseHeaders) {
1311 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451312 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231313 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251314 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231315 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371316 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231317 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1318 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1319 &spdy_request_headers_frame_length));
rch11a114a2014-09-04 23:41:591320 Initialize();
1321
1322 request_.method = "GET";
rchcd379012017-04-12 21:53:321323 request_.url = GURL("https://www.example.org/");
rch11a114a2014-09-04 23:41:591324
Matt Reichhoff0049a0b72021-10-20 20:44:261325 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
1326 net_log_with_source_,
1327 callback_.callback()));
rch11a114a2014-09-04 23:41:591328
rjshaded5ced072015-12-18 19:26:021329 EXPECT_EQ(OK,
1330 stream_->SendRequest(headers_, &response_, callback_.callback()));
rch11a114a2014-09-04 23:41:591331
jri78ec06a2016-03-31 18:19:401332 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521333 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rch11a114a2014-09-04 23:41:591334
1335 EXPECT_NE(OK, stream_->ReadResponseHeaders(callback_.callback()));
sclittle1edeeb22015-09-02 20:46:101336
1337 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451338 // headers and payload.
1339 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1340 stream_->GetTotalSentBytes());
sclittle1edeeb22015-09-02 20:46:101341 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rch11a114a2014-09-04 23:41:591342}
1343
[email protected]1e960032013-12-20 19:00:201344TEST_P(QuicHttpStreamTest, SendPostRequest) {
1345 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451346 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231347 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251348 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231349 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Yixin Wange7ecc472018-03-06 19:00:251350
Victor Vasiliev076657c2019-03-12 02:46:431351 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:321352 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411353 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231354 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1355 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1356 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411357 } else {
1358 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231359 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1360 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1361 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411362 }
Yixin Wange7ecc472018-03-06 19:00:251363
Renjie Tangcd594f32020-07-11 20:18:341364 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]f702d572012-12-04 15:56:201365
1366 Initialize();
1367
danakjad1777e2016-04-16 00:56:421368 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:191369 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
ricea2deef682016-09-09 08:04:071370 kUploadData, strlen(kUploadData)));
rch97827ee2017-05-24 23:49:121371 upload_data_stream_ =
Jeremy Roman0579ed62017-08-29 15:56:191372 std::make_unique<ElementsUploadDataStream>(std::move(element_readers), 0);
[email protected]f702d572012-12-04 15:56:201373 request_.method = "POST";
rchcd379012017-04-12 21:53:321374 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121375 request_.upload_data_stream = upload_data_stream_.get();
Bence Békyd8a21fc32018-06-27 18:29:581376 ASSERT_THAT(request_.upload_data_stream->Init(CompletionOnceCallback(),
tfarina42834112016-09-22 13:38:201377 NetLogWithSource()),
1378 IsOk());
[email protected]f702d572012-12-04 15:56:201379
Matt Reichhoff0049a0b72021-10-20 20:44:261380 EXPECT_EQ(OK, stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1381 net_log_with_source_,
1382 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021383 EXPECT_EQ(OK,
1384 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:201385
1386 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041387 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]f702d572012-12-04 15:56:201388
1389 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281390 SetResponse("200", string());
sclittlec4dc1a32015-09-24 00:15:451391 size_t spdy_response_headers_frame_length;
1392 ProcessPacket(ConstructResponseHeadersPacket(
1393 2, !kFin, &spdy_response_headers_frame_length));
[email protected]f702d572012-12-04 15:56:201394
rchfb47f712017-05-21 03:24:001395 // The headers have already arrived.
1396 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]cadac622013-06-11 16:46:361397 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:201398 EXPECT_EQ(200, response_.headers->response_code());
1399 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1400
1401 // Send the response body.
1402 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431403 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:411404 ProcessPacket(
Ryan Hamilton7505eb92019-06-08 00:22:171405 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
[email protected]f702d572012-12-04 15:56:201406 // Since the body has already arrived, this should return immediately.
1407 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
1408 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1409 callback_.callback()));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291410 EXPECT_EQ(0,
1411 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1412 callback_.callback()));
1413
1414 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1415 EXPECT_TRUE(AtEof());
1416
1417 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
1418 // headers and payload.
1419 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411420 strlen(kUploadData) + header.length()),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291421 stream_->GetTotalSentBytes());
1422 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411423 strlen(kResponseBody) + header2.length()),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291424 stream_->GetTotalReceivedBytes());
1425}
1426
1427TEST_P(QuicHttpStreamTest, SendPostRequestAndReceiveSoloFin) {
1428 SetRequest("POST", "/", DEFAULT_PRIORITY);
1429 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231430 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251431 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231432 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431433 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:321434 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411435 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231436 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1437 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1438 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411439 } else {
1440 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231441 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1442 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1443 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411444 }
1445
Renjie Tangcd594f32020-07-11 20:18:341446 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291447
1448 Initialize();
1449
1450 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:191451 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
Ryan Hamilton2ef0a9c2017-07-25 03:18:291452 kUploadData, strlen(kUploadData)));
1453 upload_data_stream_ =
Jeremy Roman0579ed62017-08-29 15:56:191454 std::make_unique<ElementsUploadDataStream>(std::move(element_readers), 0);
Ryan Hamilton2ef0a9c2017-07-25 03:18:291455 request_.method = "POST";
1456 request_.url = GURL("https://www.example.org/");
1457 request_.upload_data_stream = upload_data_stream_.get();
Bence Békyd8a21fc32018-06-27 18:29:581458 ASSERT_THAT(request_.upload_data_stream->Init(CompletionOnceCallback(),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291459 NetLogWithSource()),
1460 IsOk());
1461
Matt Reichhoff0049a0b72021-10-20 20:44:261462 EXPECT_EQ(OK, stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1463 net_log_with_source_,
1464 callback_.callback()));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291465 EXPECT_EQ(OK,
1466 stream_->SendRequest(headers_, &response_, callback_.callback()));
1467
1468 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041469 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291470
1471 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281472 SetResponse("200", string());
Ryan Hamilton2ef0a9c2017-07-25 03:18:291473 size_t spdy_response_headers_frame_length;
1474 ProcessPacket(ConstructResponseHeadersPacket(
1475 2, !kFin, &spdy_response_headers_frame_length));
1476
1477 // The headers have already arrived.
1478 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
1479 ASSERT_TRUE(response_.headers.get());
1480 EXPECT_EQ(200, response_.headers->response_code());
1481 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1482
1483 // Send the response body.
1484 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431485 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:411486 ProcessPacket(
Ryan Hamilton7505eb92019-06-08 00:22:171487 ConstructServerDataPacket(3, false, !kFin, header2 + kResponseBody));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291488 // Since the body has already arrived, this should return immediately.
1489 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
1490 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1491 callback_.callback()));
Ryan Hamilton7505eb92019-06-08 00:22:171492 ProcessPacket(ConstructServerDataPacket(4, false, kFin, ""));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291493 EXPECT_EQ(0,
1494 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1495 callback_.callback()));
[email protected]f702d572012-12-04 15:56:201496
1497 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1498 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101499
1500 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451501 // headers and payload.
1502 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411503 strlen(kUploadData) + header.length()),
sclittle1edeeb22015-09-02 20:46:101504 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451505 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411506 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101507 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:201508}
1509
[email protected]1e960032013-12-20 19:00:201510TEST_P(QuicHttpStreamTest, SendChunkedPostRequest) {
1511 SetRequest("POST", "/", DEFAULT_PRIORITY);
[email protected]c9e49a02013-02-26 05:56:471512 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:451513 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231514 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251515 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231516 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431517 std::string header = ConstructDataHeader(chunk_size);
Nick Harperc6cb7a612020-02-24 20:03:321518 if (version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411519 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231520 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1521 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1522 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjie Tangd5133972019-12-06 00:20:281523 AddWrite(ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin,
1524 {header + kUploadData}));
Renjief49758b2019-01-11 23:32:411525 } else {
1526 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231527 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1528 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1529 &spdy_request_headers_frame_length, {kUploadData}));
1530 AddWrite(ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin,
1531 kUploadData));
Renjief49758b2019-01-11 23:32:411532 }
1533
Renjie Tangcd594f32020-07-11 20:18:341534 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]c9e49a02013-02-26 05:56:471535 Initialize();
1536
Jeremy Roman0579ed62017-08-29 15:56:191537 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121538 auto* chunked_upload_stream =
1539 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1540 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
[email protected]c9e49a02013-02-26 05:56:471541
1542 request_.method = "POST";
rchcd379012017-04-12 21:53:321543 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121544 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071545 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201546 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]c9e49a02013-02-26 05:56:471547
Matt Reichhoff0049a0b72021-10-20 20:44:261548 ASSERT_EQ(OK, stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1549 net_log_with_source_,
1550 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021551 ASSERT_EQ(ERR_IO_PENDING,
1552 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]c9e49a02013-02-26 05:56:471553
rch97827ee2017-05-24 23:49:121554 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
robpercival214763f2016-07-01 23:27:011555 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]c9e49a02013-02-26 05:56:471556
1557 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041558 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]c9e49a02013-02-26 05:56:471559
1560 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281561 SetResponse("200", string());
sclittlec4dc1a32015-09-24 00:15:451562 size_t spdy_response_headers_frame_length;
1563 ProcessPacket(ConstructResponseHeadersPacket(
1564 2, !kFin, &spdy_response_headers_frame_length));
[email protected]c9e49a02013-02-26 05:56:471565
rchfb47f712017-05-21 03:24:001566 // The headers have already arrived.
1567 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]cadac622013-06-11 16:46:361568 ASSERT_TRUE(response_.headers.get());
[email protected]c9e49a02013-02-26 05:56:471569 EXPECT_EQ(200, response_.headers->response_code());
1570 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1571
1572 // Send the response body.
1573 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431574 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171575 ProcessPacket(
1576 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
[email protected]c9e49a02013-02-26 05:56:471577
1578 // Since the body has already arrived, this should return immediately.
1579 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1580 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1581 callback_.callback()));
1582
1583 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1584 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101585
1586 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451587 // headers and payload.
1588 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411589 strlen(kUploadData) * 2 + header.length() * 2),
sclittle1edeeb22015-09-02 20:46:101590 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451591 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411592 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101593 stream_->GetTotalReceivedBytes());
[email protected]c9e49a02013-02-26 05:56:471594}
1595
[email protected]16ba7742014-08-22 00:57:251596TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithFinalEmptyDataPacket) {
1597 SetRequest("POST", "/", DEFAULT_PRIORITY);
1598 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:451599 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231600 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251601 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231602 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431603 std::string header = ConstructDataHeader(chunk_size);
Renjief49758b2019-01-11 23:32:411604
Nick Harperc6cb7a612020-02-24 20:03:321605 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411606 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231607 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1608 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1609 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411610 } else {
1611 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231612 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1613 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1614 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411615 }
Renjie Tangaadb84b2019-08-31 01:00:231616 AddWrite(
1617 ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin, ""));
Renjie Tangcd594f32020-07-11 20:18:341618 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]16ba7742014-08-22 00:57:251619 Initialize();
1620
Jeremy Roman0579ed62017-08-29 15:56:191621 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121622 auto* chunked_upload_stream =
1623 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1624 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
[email protected]16ba7742014-08-22 00:57:251625
1626 request_.method = "POST";
rchcd379012017-04-12 21:53:321627 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121628 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071629 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201630 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]16ba7742014-08-22 00:57:251631
Matt Reichhoff0049a0b72021-10-20 20:44:261632 ASSERT_EQ(OK, stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1633 net_log_with_source_,
1634 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021635 ASSERT_EQ(ERR_IO_PENDING,
1636 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251637
rch97827ee2017-05-24 23:49:121638 chunked_upload_stream->AppendData(nullptr, 0, true);
robpercival214763f2016-07-01 23:27:011639 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]16ba7742014-08-22 00:57:251640
Renjie90e808e2019-01-24 07:24:041641 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]16ba7742014-08-22 00:57:251642
1643 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281644 SetResponse("200", string());
sclittlec4dc1a32015-09-24 00:15:451645 size_t spdy_response_headers_frame_length;
1646 ProcessPacket(ConstructResponseHeadersPacket(
1647 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251648
rchfb47f712017-05-21 03:24:001649 // The headers have already arrived.
1650 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]16ba7742014-08-22 00:57:251651 ASSERT_TRUE(response_.headers.get());
1652 EXPECT_EQ(200, response_.headers->response_code());
1653 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1654
1655 // Send the response body.
1656 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431657 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171658 ProcessPacket(
1659 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
[email protected]16ba7742014-08-22 00:57:251660
rchb27683c2015-07-29 23:53:501661 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251662 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1663 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1664 callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251665 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1666 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101667
1668 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451669 // headers and payload.
1670 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411671 strlen(kUploadData) + header.length()),
sclittle1edeeb22015-09-02 20:46:101672 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451673 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411674 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101675 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251676}
1677
1678TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithOneEmptyDataPacket) {
1679 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451680 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231681 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251682 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231683 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371684 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231685 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1686 kIncludeVersion, !kFin, DEFAULT_PRIORITY,
1687 &spdy_request_headers_frame_length));
1688 AddWrite(
1689 ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin, ""));
Renjie Tangcd594f32020-07-11 20:18:341690 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]16ba7742014-08-22 00:57:251691 Initialize();
1692
Jeremy Roman0579ed62017-08-29 15:56:191693 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121694 auto* chunked_upload_stream =
1695 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
[email protected]16ba7742014-08-22 00:57:251696
1697 request_.method = "POST";
rchcd379012017-04-12 21:53:321698 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121699 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071700 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201701 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]16ba7742014-08-22 00:57:251702
Matt Reichhoff0049a0b72021-10-20 20:44:261703 ASSERT_EQ(OK, stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1704 net_log_with_source_,
1705 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021706 ASSERT_EQ(ERR_IO_PENDING,
1707 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251708
rch97827ee2017-05-24 23:49:121709 chunked_upload_stream->AppendData(nullptr, 0, true);
robpercival214763f2016-07-01 23:27:011710 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]16ba7742014-08-22 00:57:251711
Renjie90e808e2019-01-24 07:24:041712 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]16ba7742014-08-22 00:57:251713
1714 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281715 SetResponse("200", string());
sclittlec4dc1a32015-09-24 00:15:451716 size_t spdy_response_headers_frame_length;
1717 ProcessPacket(ConstructResponseHeadersPacket(
1718 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251719
rchfb47f712017-05-21 03:24:001720 // The headers have already arrived.
1721 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]16ba7742014-08-22 00:57:251722 ASSERT_TRUE(response_.headers.get());
1723 EXPECT_EQ(200, response_.headers->response_code());
1724 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1725
1726 // Send the response body.
1727 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431728 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171729 ProcessPacket(
1730 ConstructServerDataPacket(3, false, kFin, header + kResponseBody));
[email protected]16ba7742014-08-22 00:57:251731
rchb27683c2015-07-29 23:53:501732 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251733 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1734 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1735 callback_.callback()));
1736
1737 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1738 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101739
1740 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451741 // headers and payload.
1742 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1743 stream_->GetTotalSentBytes());
1744 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411745 strlen(kResponseBody) + header.length()),
sclittle1edeeb22015-09-02 20:46:101746 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251747}
1748
Bence Békye3c6f122020-05-08 01:09:471749TEST_P(QuicHttpStreamTest, SendChunkedPostRequestAbortedByResetStream) {
1750 SetRequest("POST", "/", DEFAULT_PRIORITY);
1751 size_t chunk_size = strlen(kUploadData);
1752 size_t spdy_request_headers_frame_length;
1753 int packet_number = 1;
1754
1755 if (version_.UsesHttp3()) {
1756 AddWrite(ConstructInitialSettingsPacket(packet_number++));
1757 }
1758
1759 std::string header = ConstructDataHeader(chunk_size);
1760 if (version_.HasIetfQuicFrames()) {
1761 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1762 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1763 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1764 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjie Tangcd594f32020-07-11 20:18:341765 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
Fan Yang8d4177792021-07-16 17:48:531766 AddWrite(client_maker_.MakeAckAndRstPacket(
1767 packet_number++, true, stream_id_, quic::QUIC_STREAM_NO_ERROR, 4, 1,
Renjie Tangcd594f32020-07-11 20:18:341768 /* include_stop_sending_if_v99 = */ false));
Bence Békye3c6f122020-05-08 01:09:471769 } else {
1770 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1771 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1772 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1773 &spdy_request_headers_frame_length, {kUploadData}));
Renjie Tangcd594f32020-07-11 20:18:341774 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
Bence Békye3c6f122020-05-08 01:09:471775 AddWrite(client_maker_.MakeAckAndRstPacket(
1776 packet_number++,
1777 /* include_version = */ false, stream_id_,
Renjie Tangcd594f32020-07-11 20:18:341778 quic::QUIC_RST_ACKNOWLEDGEMENT, 4, 1,
Bence Békye3c6f122020-05-08 01:09:471779 /* include_stop_sending_if_v99 = */ false));
1780 }
1781
1782 Initialize();
1783
1784 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
1785 auto* chunked_upload_stream =
1786 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1787 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
1788
1789 request_.method = "POST";
1790 request_.url = GURL("https://www.example.org/");
1791 request_.upload_data_stream = upload_data_stream_.get();
1792 ASSERT_THAT(request_.upload_data_stream->Init(
1793 TestCompletionCallback().callback(), NetLogWithSource()),
1794 IsOk());
Matt Reichhoff0049a0b72021-10-20 20:44:261795 ASSERT_THAT(
1796 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1797 net_log_with_source_, callback_.callback()),
1798 IsOk());
Bence Békye3c6f122020-05-08 01:09:471799 ASSERT_THAT(stream_->SendRequest(headers_, &response_, callback_.callback()),
1800 IsError(ERR_IO_PENDING));
1801
1802 // Ack both packets in the request.
1803 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
1804
1805 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281806 SetResponse("200", string());
Bence Békye3c6f122020-05-08 01:09:471807 size_t spdy_response_headers_frame_length;
1808 ProcessPacket(ConstructResponseHeadersPacket(
1809 2, !kFin, &spdy_response_headers_frame_length));
1810
1811 // Send the response body.
1812 const char kResponseBody[] = "Hello world!";
1813 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
1814 ProcessPacket(
1815 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
1816
Bence Béky050ec6d2021-02-25 22:07:051817 if (version_.HasIetfQuicFrames()) {
1818 // In IETF QUIC, the server uses a STOP_SENDING frame to notify the client
1819 // that it does not need any further data to fully process the request.
1820 ProcessPacket(server_maker_.MakeStopSendingPacket(
1821 4, /* include_version = */ false, stream_id_,
1822 quic::QUIC_STREAM_NO_ERROR));
1823 } else {
1824 // Server resets stream with H3_NO_ERROR before request body is complete.
1825 ProcessPacket(server_maker_.MakeRstPacket(4, /* include_version = */ false,
1826 stream_id_,
1827 quic::QUIC_STREAM_NO_ERROR));
1828 }
Bence Békye3c6f122020-05-08 01:09:471829
1830 // Finish feeding request body to QuicHttpStream. Data will be discarded.
1831 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1832 EXPECT_THAT(callback_.WaitForResult(), IsOk());
1833
1834 // Verify response.
1835 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
1836 ASSERT_TRUE(response_.headers.get());
1837 EXPECT_EQ(200, response_.headers->response_code());
1838 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1839 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1840 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1841 callback_.callback()));
1842 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1843 EXPECT_TRUE(AtEof());
1844
1845 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
1846 // headers and payload.
1847 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
1848 strlen(kUploadData) + header.length()),
1849 stream_->GetTotalSentBytes());
1850 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1851 strlen(kResponseBody) + header2.length()),
1852 stream_->GetTotalReceivedBytes());
1853}
1854
[email protected]1e960032013-12-20 19:00:201855TEST_P(QuicHttpStreamTest, DestroyedEarly) {
1856 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451857 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231858 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251859 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231860 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371861 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231862 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1863 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1864 &spdy_request_headers_frame_length));
1865 AddWrite(ConstructAckAndRstStreamPacket(packet_number++));
[email protected]63534512012-12-23 18:49:001866 Initialize();
1867
1868 request_.method = "GET";
rchcd379012017-04-12 21:53:321869 request_.url = GURL("https://www.example.org/");
[email protected]63534512012-12-23 18:49:001870
Matt Reichhoff0049a0b72021-10-20 20:44:261871 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
1872 net_log_with_source_,
1873 callback_.callback()));
rjshaded5ced072015-12-18 19:26:021874 EXPECT_EQ(OK,
1875 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]63534512012-12-23 18:49:001876
1877 // Ack the request.
Renjie90e808e2019-01-24 07:24:041878 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
rchfb47f712017-05-21 03:24:001879 EXPECT_THAT(stream_->ReadResponseHeaders(
Yannic Bonenberger3c96beb2019-09-03 20:41:371880 base::BindOnce(&QuicHttpStreamTest::CloseStream,
1881 base::Unretained(this), stream_.get())),
robpercival214763f2016-07-01 23:27:011882 IsError(ERR_IO_PENDING));
[email protected]63534512012-12-23 18:49:001883
1884 // Send the response with a body.
Kenichi Ishibashif8634ab2021-03-16 23:41:281885 SetResponse("404", "hello world!");
[email protected]63534512012-12-23 18:49:001886 // In the course of processing this packet, the QuicHttpStream close itself.
rchfb47f712017-05-21 03:24:001887 size_t response_size = 0;
rch1bcfddf22017-06-03 00:26:291888 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin, &response_size));
[email protected]63534512012-12-23 18:49:001889
fdoray92e35a72016-06-10 15:54:551890 base::RunLoop().RunUntilIdle();
rchb27683c2015-07-29 23:53:501891
[email protected]63534512012-12-23 18:49:001892 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101893
1894 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451895 // headers and payload.
1896 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1897 stream_->GetTotalSentBytes());
rchfb47f712017-05-21 03:24:001898 // The stream was closed after receiving the headers.
1899 EXPECT_EQ(static_cast<int64_t>(response_size),
1900 stream_->GetTotalReceivedBytes());
[email protected]63534512012-12-23 18:49:001901}
1902
[email protected]1e960032013-12-20 19:00:201903TEST_P(QuicHttpStreamTest, Priority) {
1904 SetRequest("GET", "/", MEDIUM);
sclittlec4dc1a32015-09-24 00:15:451905 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231906 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251907 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231908 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371909 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231910 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1911 kIncludeVersion, kFin, MEDIUM, &spdy_request_headers_frame_length));
[email protected]24e5bc52013-09-18 15:36:581912 Initialize();
1913
1914 request_.method = "GET";
rchcd379012017-04-12 21:53:321915 request_.url = GURL("https://www.example.org/");
[email protected]24e5bc52013-09-18 15:36:581916
Matt Reichhoff0049a0b72021-10-20 20:44:261917 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, MEDIUM,
1918 net_log_with_source_,
1919 callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581920
rjshaded5ced072015-12-18 19:26:021921 EXPECT_EQ(OK,
1922 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581923
[email protected]24e5bc52013-09-18 15:36:581924 // Ack the request.
Renjie90e808e2019-01-24 07:24:041925 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011926 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1927 IsError(ERR_IO_PENDING));
[email protected]24e5bc52013-09-18 15:36:581928
1929 // Send the response with a body.
Kenichi Ishibashif8634ab2021-03-16 23:41:281930 SetResponse("404", "hello world!");
rchfb47f712017-05-21 03:24:001931 size_t response_size = 0;
1932 ProcessPacket(ConstructResponseHeadersPacket(2, kFin, &response_size));
[email protected]24e5bc52013-09-18 15:36:581933
rchfb47f712017-05-21 03:24:001934 EXPECT_EQ(OK, callback_.WaitForResult());
rchb27683c2015-07-29 23:53:501935
[email protected]24e5bc52013-09-18 15:36:581936 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101937
1938 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451939 // headers and payload.
1940 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1941 stream_->GetTotalSentBytes());
rchfb47f712017-05-21 03:24:001942 EXPECT_EQ(static_cast<int64_t>(response_size),
1943 stream_->GetTotalReceivedBytes());
[email protected]24e5bc52013-09-18 15:36:581944}
1945
xunjieli8dff50b2016-07-22 14:19:061946TEST_P(QuicHttpStreamTest, SessionClosedDuringDoLoop) {
1947 SetRequest("POST", "/", DEFAULT_PRIORITY);
1948 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231949 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251950 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231951 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431952 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:321953 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411954 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231955 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1956 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1957 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411958 } else {
1959 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231960 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1961 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1962 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411963 }
1964
xunjieli8dff50b2016-07-22 14:19:061965 // Second data write will result in a synchronous failure which will close
1966 // the session.
1967 AddWrite(SYNCHRONOUS, ERR_FAILED);
1968 Initialize();
1969
Jeremy Roman0579ed62017-08-29 15:56:191970 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121971 auto* chunked_upload_stream =
1972 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
xunjieli8dff50b2016-07-22 14:19:061973
1974 request_.method = "POST";
rchcd379012017-04-12 21:53:321975 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121976 request_.upload_data_stream = upload_data_stream_.get();
xunjieli8dff50b2016-07-22 14:19:061977 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201978 TestCompletionCallback().callback(), NetLogWithSource()));
xunjieli8dff50b2016-07-22 14:19:061979
1980 size_t chunk_size = strlen(kUploadData);
rch97827ee2017-05-24 23:49:121981 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
Matt Reichhoff0049a0b72021-10-20 20:44:261982 ASSERT_EQ(OK, stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1983 net_log_with_source_,
1984 callback_.callback()));
xunjieli8dff50b2016-07-22 14:19:061985 QuicHttpStream* stream = stream_.get();
1986 DeleteStreamCallback delete_stream_callback(std::move(stream_));
1987 // SendRequest() completes asynchronously after the final chunk is added.
Yixin Wange7ecc472018-03-06 19:00:251988 // Error does not surface yet since packet write is triggered by a packet
1989 // flusher that tries to bundle request body writes.
xunjieli8dff50b2016-07-22 14:19:061990 ASSERT_EQ(ERR_IO_PENDING,
1991 stream->SendRequest(headers_, &response_, callback_.callback()));
rch97827ee2017-05-24 23:49:121992 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
xunjieli8dff50b2016-07-22 14:19:061993 int rv = callback_.WaitForResult();
Yixin Wange7ecc472018-03-06 19:00:251994 EXPECT_EQ(OK, rv);
1995 // Error will be surfaced once an attempt to read the response occurs.
1996 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1997 stream->ReadResponseHeaders(callback_.callback()));
xunjieli8dff50b2016-07-22 14:19:061998}
1999
rtenneti15656ae2016-01-23 03:05:032000TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersComplete) {
2001 SetRequest("POST", "/", DEFAULT_PRIORITY);
Victor Vasiliev7da08172019-10-14 06:04:252002 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232003 AddWrite(ConstructInitialSettingsPacket());
rtenneti15656ae2016-01-23 03:05:032004 AddWrite(SYNCHRONOUS, ERR_FAILED);
2005 Initialize();
2006
Jeremy Roman0579ed62017-08-29 15:56:192007 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
Yixin Wange7ecc472018-03-06 19:00:252008 auto* chunked_upload_stream =
2009 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
rtenneti15656ae2016-01-23 03:05:032010
2011 request_.method = "POST";
rchcd379012017-04-12 21:53:322012 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122013 request_.upload_data_stream = upload_data_stream_.get();
rtenneti15656ae2016-01-23 03:05:032014 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202015 TestCompletionCallback().callback(), NetLogWithSource()));
rtenneti15656ae2016-01-23 03:05:032016
Matt Reichhoff0049a0b72021-10-20 20:44:262017 ASSERT_EQ(OK, stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
2018 net_log_with_source_,
2019 callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252020 ASSERT_EQ(ERR_IO_PENDING,
rtenneti15656ae2016-01-23 03:05:032021 stream_->SendRequest(headers_, &response_, callback_.callback()));
mmenkeffff3642017-06-15 17:37:242022
Yixin Wange7ecc472018-03-06 19:00:252023 // Error will be surfaced once |upload_data_stream| triggers the next write.
2024 size_t chunk_size = strlen(kUploadData);
2025 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2026 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR, callback_.WaitForResult());
2027
2028 EXPECT_LE(0, stream_->GetTotalSentBytes());
2029 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2030}
2031
2032TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersCompleteReadResponse) {
2033 SetRequest("POST", "/", DEFAULT_PRIORITY);
Victor Vasiliev7da08172019-10-14 06:04:252034 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232035 AddWrite(ConstructInitialSettingsPacket());
Yixin Wange7ecc472018-03-06 19:00:252036 AddWrite(SYNCHRONOUS, ERR_FAILED);
2037 Initialize();
2038
2039 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
2040 auto* chunked_upload_stream =
2041 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
2042
2043 request_.method = "POST";
2044 request_.url = GURL("https://www.example.org/");
2045 request_.upload_data_stream = upload_data_stream_.get();
2046
2047 size_t chunk_size = strlen(kUploadData);
2048 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2049
2050 ASSERT_EQ(OK, request_.upload_data_stream->Init(
2051 TestCompletionCallback().callback(), NetLogWithSource()));
2052
Matt Reichhoff0049a0b72021-10-20 20:44:262053 ASSERT_EQ(OK, stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
2054 net_log_with_source_,
2055 callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252056 ASSERT_EQ(OK,
2057 stream_->SendRequest(headers_, &response_, callback_.callback()));
2058
2059 // Error will be surfaced once an attempt to read the response occurs.
2060 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
2061 stream_->ReadResponseHeaders(callback_.callback()));
2062
mmenkeffff3642017-06-15 17:37:242063 EXPECT_LE(0, stream_->GetTotalSentBytes());
2064 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rtenneti15656ae2016-01-23 03:05:032065}
2066
2067TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBodyComplete) {
2068 SetRequest("POST", "/", DEFAULT_PRIORITY);
2069 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232070 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252071 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232072 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:372073 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:232074 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2075 kIncludeVersion, !kFin, DEFAULT_PRIORITY,
2076 &spdy_request_headers_frame_length));
rtenneti15656ae2016-01-23 03:05:032077 AddWrite(SYNCHRONOUS, ERR_FAILED);
2078 Initialize();
2079
Jeremy Roman0579ed62017-08-29 15:56:192080 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:122081 auto* chunked_upload_stream =
2082 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
rtenneti15656ae2016-01-23 03:05:032083
2084 request_.method = "POST";
rchcd379012017-04-12 21:53:322085 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122086 request_.upload_data_stream = upload_data_stream_.get();
rtenneti15656ae2016-01-23 03:05:032087 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202088 TestCompletionCallback().callback(), NetLogWithSource()));
rtenneti15656ae2016-01-23 03:05:032089
Matt Reichhoff0049a0b72021-10-20 20:44:262090 ASSERT_EQ(OK, stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
2091 net_log_with_source_,
2092 callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252093 ASSERT_EQ(ERR_IO_PENDING,
rtenneti15656ae2016-01-23 03:05:032094 stream_->SendRequest(headers_, &response_, callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252095
2096 size_t chunk_size = strlen(kUploadData);
2097 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2098 // Error does not surface yet since packet write is triggered by a packet
2099 // flusher that tries to bundle request body writes.
2100 ASSERT_EQ(OK, callback_.WaitForResult());
2101 // Error will be surfaced once an attempt to read the response occurs.
2102 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
2103 stream_->ReadResponseHeaders(callback_.callback()));
2104
2105 EXPECT_LE(0, stream_->GetTotalSentBytes());
2106 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2107}
2108
2109TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBundledBodyComplete) {
2110 SetRequest("POST", "/", DEFAULT_PRIORITY);
2111 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232112 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252113 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232114 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:432115 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:322116 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:412117 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:232118 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2119 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
2120 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:412121 } else {
2122 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:232123 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2124 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
2125 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:412126 }
2127
Yixin Wange7ecc472018-03-06 19:00:252128 AddWrite(SYNCHRONOUS, ERR_FAILED);
2129 Initialize();
2130
2131 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
2132 auto* chunked_upload_stream =
2133 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
2134
2135 request_.method = "POST";
2136 request_.url = GURL("https://www.example.org/");
2137 request_.upload_data_stream = upload_data_stream_.get();
2138
2139 size_t chunk_size = strlen(kUploadData);
2140 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
2141
2142 ASSERT_EQ(OK, request_.upload_data_stream->Init(
2143 TestCompletionCallback().callback(), NetLogWithSource()));
2144
Matt Reichhoff0049a0b72021-10-20 20:44:262145 ASSERT_EQ(OK, stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
2146 net_log_with_source_,
2147 callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252148 ASSERT_EQ(ERR_IO_PENDING,
2149 stream_->SendRequest(headers_, &response_, callback_.callback()));
2150
2151 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2152
2153 // Error does not surface yet since packet write is triggered by a packet
2154 // flusher that tries to bundle request body writes.
2155 ASSERT_EQ(OK, callback_.WaitForResult());
2156 // Error will be surfaced once an attempt to read the response occurs.
2157 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
2158 stream_->ReadResponseHeaders(callback_.callback()));
2159
2160 EXPECT_LE(0, stream_->GetTotalSentBytes());
2161 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rtenneti15656ae2016-01-23 03:05:032162}
2163
ckrasic3865ee0f2016-02-29 22:04:562164TEST_P(QuicHttpStreamTest, ServerPushGetRequest) {
2165 SetRequest("GET", "/", DEFAULT_PRIORITY);
2166 Initialize();
2167
Bin Wue8408792021-08-24 23:25:162168 // Server push is not supported in HTTP/3.
2169 if (version_.UsesHttp3())
2170 return;
2171
ckrasic3865ee0f2016-02-29 22:04:562172 // Initialize the first stream, for receiving the promise on.
2173 request_.method = "GET";
rchcd379012017-04-12 21:53:322174 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562175
Matt Reichhoff0049a0b72021-10-20 20:44:262176 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
2177 net_log_with_source_,
2178 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232179 ASSERT_EQ(OK,
2180 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562181
2182 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2183 // packet, but does it matter?
2184 ReceivePromise(promise_id_);
2185 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2186
2187 request_.url = GURL(promise_url_);
2188
2189 // Make the second stream that will exercise the first step of the
2190 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272191 EXPECT_EQ(OK, promised_stream_->InitializeStream(
Matt Reichhoff0049a0b72021-10-20 20:44:262192 &request_, true, DEFAULT_PRIORITY, net_log_with_source_,
Steven Valdezb4ff0412018-01-18 22:39:272193 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562194
2195 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252196 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562197 size_t spdy_response_headers_frame_length;
2198 ProcessPacket(InnerConstructResponseHeadersPacket(
2199 1, promise_id_, false, &spdy_response_headers_frame_length));
2200
2201 // Receive the promised response body.
2202 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432203 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172204 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2205 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562206
2207 // Now sending a matching request will have successful rendezvous
2208 // with the promised stream.
Ryan Hamiltona1d1f4a2019-06-26 14:43:042209 ASSERT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
ckrasic3865ee0f2016-02-29 22:04:562210 callback_.callback()));
2211
2212 EXPECT_EQ(
2213 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2214 ->id(),
2215 promise_id_);
2216
2217 // The headers will be immediately available.
robpercival214763f2016-07-01 23:27:012218 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2219 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562220
2221 // As will be the body.
2222 EXPECT_EQ(
2223 static_cast<int>(strlen(kResponseBody)),
2224 promised_stream_->ReadResponseBody(
2225 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2226 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2227 EXPECT_TRUE(AtEof());
2228
ckrasic3865ee0f2016-02-29 22:04:562229 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2230 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412231 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562232 promised_stream_->GetTotalReceivedBytes());
2233}
2234
2235TEST_P(QuicHttpStreamTest, ServerPushGetRequestSlowResponse) {
2236 SetRequest("GET", "/", DEFAULT_PRIORITY);
2237 Initialize();
2238
Bin Wue8408792021-08-24 23:25:162239 // Server push is not supported in HTTP/3.
2240 if (version_.UsesHttp3())
2241 return;
2242
ckrasic3865ee0f2016-02-29 22:04:562243 // Initialize the first stream, for receiving the promise on.
2244 request_.method = "GET";
rchcd379012017-04-12 21:53:322245 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562246
Matt Reichhoff0049a0b72021-10-20 20:44:262247 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
2248 net_log_with_source_,
2249 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232250 ASSERT_EQ(OK,
2251 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562252
2253 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2254 // packet, but does it matter?
2255 ReceivePromise(promise_id_);
2256 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2257
2258 request_.url = GURL(promise_url_);
2259
2260 // Make the second stream that will exercise the first step of the
2261 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272262 EXPECT_EQ(OK, promised_stream_->InitializeStream(
Matt Reichhoff0049a0b72021-10-20 20:44:262263 &request_, true, DEFAULT_PRIORITY, net_log_with_source_,
Steven Valdezb4ff0412018-01-18 22:39:272264 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562265
2266 // Now sending a matching request will rendezvous with the promised
2267 // stream, but pending secondary validation.
2268 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2269 headers_, &response_, callback_.callback()));
2270
2271 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252272 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562273 size_t spdy_response_headers_frame_length;
2274 ProcessPacket(InnerConstructResponseHeadersPacket(
2275 1, promise_id_, false, &spdy_response_headers_frame_length));
2276
2277 // Receive the promised response body.
2278 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432279 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172280 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2281 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562282
fdoray92e35a72016-06-10 15:54:552283 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562284
2285 // Rendezvous should have succeeded now, so the promised stream
2286 // should point at our push stream, and we should be able read
2287 // headers and data from it.
robpercival214763f2016-07-01 23:27:012288 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562289
2290 EXPECT_EQ(
2291 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2292 ->id(),
2293 promise_id_);
2294
robpercival214763f2016-07-01 23:27:012295 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2296 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562297
2298 EXPECT_EQ(
2299 static_cast<int>(strlen(kResponseBody)),
2300 promised_stream_->ReadResponseBody(
2301 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2302
2303 // Callback should return
2304 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2305 EXPECT_TRUE(AtEof());
2306
ckrasic3865ee0f2016-02-29 22:04:562307 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2308 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412309 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562310 promised_stream_->GetTotalReceivedBytes());
2311}
2312
ckrasic2c63f9b2016-08-16 23:54:072313// Verify fix for crbug.com/637349
2314TEST_P(QuicHttpStreamTest, ServerPushCancelHttpStreamBeforeResponse) {
2315 SetRequest("GET", "/", DEFAULT_PRIORITY);
2316 Initialize();
2317
Bin Wue8408792021-08-24 23:25:162318 // Server push is not supported in HTTP/3.
2319 if (version_.UsesHttp3())
2320 return;
2321
ckrasic2c63f9b2016-08-16 23:54:072322 // Initialize the first stream, for receiving the promise on.
2323 request_.method = "GET";
rchcd379012017-04-12 21:53:322324 request_.url = GURL("https://www.example.org/");
ckrasic2c63f9b2016-08-16 23:54:072325
Matt Reichhoff0049a0b72021-10-20 20:44:262326 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
2327 net_log_with_source_,
2328 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232329 ASSERT_EQ(OK,
2330 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic2c63f9b2016-08-16 23:54:072331
2332 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2333 // packet, but does it matter?
2334 ReceivePromise(promise_id_);
2335 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2336
2337 request_.url = GURL(promise_url_);
2338
2339 // Make the second stream that will exercise the first step of the
2340 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272341 EXPECT_EQ(OK, promised_stream_->InitializeStream(
Matt Reichhoff0049a0b72021-10-20 20:44:262342 &request_, true, DEFAULT_PRIORITY, net_log_with_source_,
Steven Valdezb4ff0412018-01-18 22:39:272343 callback_.callback()));
ckrasic2c63f9b2016-08-16 23:54:072344
2345 // Now sending a matching request will rendezvous with the promised
2346 // stream, but pending secondary validation.
2347 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2348 headers_, &response_, callback_.callback()));
2349
2350 base::RunLoop().RunUntilIdle();
2351
2352 // Cause of FinalValidation() crash as per bug.
2353 promised_stream_.reset();
2354
2355 // Receive the promised response headers.
2356 response_headers_ = promised_response_.Clone();
2357 size_t spdy_response_headers_frame_length;
2358 ProcessPacket(InnerConstructResponseHeadersPacket(
2359 1, promise_id_, false, &spdy_response_headers_frame_length));
2360}
2361
ckrasic3865ee0f2016-02-29 22:04:562362TEST_P(QuicHttpStreamTest, ServerPushCrossOriginOK) {
2363 SetRequest("GET", "/", DEFAULT_PRIORITY);
2364 Initialize();
2365
Bin Wue8408792021-08-24 23:25:162366 // Server push is not supported in HTTP/3.
2367 if (version_.UsesHttp3())
2368 return;
2369
ckrasic3865ee0f2016-02-29 22:04:562370 // Initialize the first stream, for receiving the promise on.
2371 request_.method = "GET";
rchcd379012017-04-12 21:53:322372 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562373
Matt Reichhoff0049a0b72021-10-20 20:44:262374 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
2375 net_log_with_source_,
2376 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232377 ASSERT_EQ(OK,
2378 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562379
2380 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2381 // packet, but does it matter?
2382
2383 push_promise_[":authority"] = "mail.example.org";
David Schinazi3f7465c2019-07-12 01:57:052384 promise_url_ =
2385 quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
ckrasic3865ee0f2016-02-29 22:04:562386
2387 ReceivePromise(promise_id_);
2388 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2389
2390 request_.url = GURL(promise_url_);
2391
2392 // Make the second stream that will exercise the first step of the
2393 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272394 EXPECT_EQ(OK, promised_stream_->InitializeStream(
Matt Reichhoff0049a0b72021-10-20 20:44:262395 &request_, true, DEFAULT_PRIORITY, net_log_with_source_,
Steven Valdezb4ff0412018-01-18 22:39:272396 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562397
2398 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252399 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562400 size_t spdy_response_headers_frame_length;
2401 ProcessPacket(InnerConstructResponseHeadersPacket(
2402 1, promise_id_, false, &spdy_response_headers_frame_length));
2403
2404 // Receive the promised response body.
2405 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432406 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172407 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2408 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562409
2410 // Now sending a matching request will have successful rendezvous
2411 // with the promised stream.
2412 EXPECT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
2413 callback_.callback()));
2414
2415 EXPECT_EQ(
2416 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2417 ->id(),
2418 promise_id_);
2419
2420 // The headers will be immediately available.
robpercival214763f2016-07-01 23:27:012421 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2422 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562423
2424 // As will be the body.
2425 EXPECT_EQ(
2426 static_cast<int>(strlen(kResponseBody)),
2427 promised_stream_->ReadResponseBody(
2428 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2429 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2430 EXPECT_TRUE(AtEof());
2431
ckrasic3865ee0f2016-02-29 22:04:562432 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2433 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412434 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562435 promised_stream_->GetTotalReceivedBytes());
2436}
2437
2438TEST_P(QuicHttpStreamTest, ServerPushCrossOriginFail) {
2439 SetRequest("GET", "/", DEFAULT_PRIORITY);
2440 Initialize();
2441
Bin Wue8408792021-08-24 23:25:162442 // Server push is not supported in HTTP/3.
2443 if (version_.UsesHttp3())
2444 return;
2445
ckrasic3865ee0f2016-02-29 22:04:562446 // Initialize the first stream, for receiving the promise on.
2447 request_.method = "GET";
rchcd379012017-04-12 21:53:322448 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562449
Matt Reichhoff0049a0b72021-10-20 20:44:262450 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
2451 net_log_with_source_,
2452 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232453 ASSERT_EQ(OK,
2454 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562455
2456 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2457 // packet, but does it matter?
2458 push_promise_[":authority"] = "www.notexample.org";
David Schinazi3f7465c2019-07-12 01:57:052459 promise_url_ =
2460 quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
ckrasic3865ee0f2016-02-29 22:04:562461
2462 ReceivePromise(promise_id_);
2463 // The promise will have been rejected because the cert doesn't
2464 // match.
2465 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
2466}
2467
2468TEST_P(QuicHttpStreamTest, ServerPushVaryCheckOK) {
2469 SetRequest("GET", "/", DEFAULT_PRIORITY);
2470 Initialize();
2471
Bin Wue8408792021-08-24 23:25:162472 // Server push is not supported in HTTP/3.
2473 if (version_.UsesHttp3())
2474 return;
2475
ckrasic3865ee0f2016-02-29 22:04:562476 // Initialize the first stream, for receiving the promise on.
2477 request_.method = "GET";
rchcd379012017-04-12 21:53:322478 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562479
Matt Reichhoff0049a0b72021-10-20 20:44:262480 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
2481 net_log_with_source_,
2482 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232483 ASSERT_EQ(OK,
2484 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562485
2486 push_promise_["accept-encoding"] = "gzip";
ckrasic3865ee0f2016-02-29 22:04:562487
2488 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2489 // packet, but does it matter?
2490 ReceivePromise(promise_id_);
2491 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2492
2493 request_.url = GURL(promise_url_);
2494
2495 // Make the second stream that will exercise the first step of the
2496 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272497 EXPECT_EQ(OK, promised_stream_->InitializeStream(
Matt Reichhoff0049a0b72021-10-20 20:44:262498 &request_, true, DEFAULT_PRIORITY, net_log_with_source_,
Steven Valdezb4ff0412018-01-18 22:39:272499 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562500
2501 headers_.SetHeader("accept-encoding", "gzip");
2502
2503 // Now sending a matching request will rendezvous with the promised
2504 // stream, but pending secondary validation.
2505 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2506 headers_, &response_, callback_.callback()));
2507
2508 // Receive the promised response headers.
2509 promised_response_["vary"] = "accept-encoding";
bnc94893a72016-06-30 13:45:252510 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562511 size_t spdy_response_headers_frame_length;
2512 ProcessPacket(InnerConstructResponseHeadersPacket(
2513 1, promise_id_, false, &spdy_response_headers_frame_length));
2514
2515 // Receive the promised response body.
2516 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432517 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172518 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2519 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562520
fdoray92e35a72016-06-10 15:54:552521 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562522
2523 // Rendezvous should have succeeded now, so the promised stream
2524 // should point at our push stream, and we should be able read
2525 // headers and data from it.
robpercival214763f2016-07-01 23:27:012526 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562527
2528 EXPECT_EQ(
2529 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2530 ->id(),
2531 promise_id_);
2532
robpercival214763f2016-07-01 23:27:012533 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2534 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562535
2536 EXPECT_EQ(
2537 static_cast<int>(strlen(kResponseBody)),
2538 promised_stream_->ReadResponseBody(
2539 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2540
2541 // Callback should return
2542 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2543 EXPECT_TRUE(AtEof());
2544
ckrasic3865ee0f2016-02-29 22:04:562545 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2546 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412547 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562548 promised_stream_->GetTotalReceivedBytes());
2549}
2550
2551TEST_P(QuicHttpStreamTest, ServerPushVaryCheckFail) {
2552 SetRequest("GET", "/", DEFAULT_PRIORITY);
2553 request_headers_[":scheme"] = "https";
2554 request_headers_[":path"] = "/bar";
2555 request_headers_["accept-encoding"] = "sdch";
2556
ckrasic3865ee0f2016-02-29 22:04:562557 Initialize();
2558
Bin Wue8408792021-08-24 23:25:162559 // Server push is not supported in HTTP/3.
2560 if (version_.UsesHttp3())
2561 return;
2562
ckrasic3865ee0f2016-02-29 22:04:562563 // Initialize the first stream, for receiving the promise on.
2564 request_.method = "GET";
rchcd379012017-04-12 21:53:322565 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562566
Matt Reichhoff0049a0b72021-10-20 20:44:262567 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
2568 net_log_with_source_,
2569 callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232570 ASSERT_EQ(OK,
2571 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562572
2573 push_promise_["accept-encoding"] = "gzip";
ckrasic3865ee0f2016-02-29 22:04:562574
2575 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2576 // packet, but does it matter?
2577 ReceivePromise(promise_id_);
2578 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2579
2580 request_.url = GURL(promise_url_);
2581
2582 // Make the second stream that will exercise the first step of the
2583 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272584 EXPECT_EQ(OK, promised_stream_->InitializeStream(
Matt Reichhoff0049a0b72021-10-20 20:44:262585 &request_, true, DEFAULT_PRIORITY, net_log_with_source_,
Steven Valdezb4ff0412018-01-18 22:39:272586 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562587
2588 headers_.SetHeader("accept-encoding", "sdch");
2589
2590 // Now sending a matching request will rendezvous with the promised
2591 // stream, but pending secondary validation.
2592 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2593 headers_, &response_, callback_.callback()));
2594
2595 // Receive the promised response headers.
2596 promised_response_["vary"] = "accept-encoding";
bnc94893a72016-06-30 13:45:252597 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562598 size_t spdy_response_headers_frame_length;
2599 ProcessPacket(InnerConstructResponseHeadersPacket(
2600 1, promise_id_, false, &spdy_response_headers_frame_length));
2601
fdoray92e35a72016-06-10 15:54:552602 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562603
2604 // Rendezvous should have failed due to vary mismatch, so the
2605 // promised stream should have been aborted, and instead we have a
2606 // new, regular client initiated stream.
robpercival214763f2016-07-01 23:27:012607 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562608
2609 // Not a server-initiated stream.
2610 EXPECT_NE(
2611 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2612 ->id(),
2613 promise_id_);
2614
2615 // Instead, a new client-initiated stream.
2616 EXPECT_EQ(
2617 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2618 ->id(),
Nick Harper23290b82019-05-02 00:02:562619 stream_id_ + quic::QuicUtils::StreamIdDelta(version_.transport_version));
ckrasic3865ee0f2016-02-29 22:04:562620
2621 // After rendezvous failure, the push stream has been cancelled.
2622 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
2623
2624 // The rest of the test verifies that the retried as
2625 // client-initiated version of |promised_stream_| works as intended.
2626
2627 // Ack the request.
Renjie90e808e2019-01-24 07:24:042628 ProcessPacket(ConstructServerAckPacket(2, 1, 1, 1));
ckrasic3865ee0f2016-02-29 22:04:562629
Kenichi Ishibashif8634ab2021-03-16 23:41:282630 SetResponse("404", string());
ckrasic3865ee0f2016-02-29 22:04:562631 size_t spdy_response_header_frame_length;
2632 ProcessPacket(InnerConstructResponseHeadersPacket(
Nick Harper23290b82019-05-02 00:02:562633 3,
2634 stream_id_ + quic::QuicUtils::StreamIdDelta(version_.transport_version),
2635 kFin, &spdy_response_header_frame_length));
ckrasic3865ee0f2016-02-29 22:04:562636
fdoray92e35a72016-06-10 15:54:552637 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562638
robpercival214763f2016-07-01 23:27:012639 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2640 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562641 ASSERT_TRUE(response_.headers.get());
2642 EXPECT_EQ(404, response_.headers->response_code());
2643 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
2644 EXPECT_FALSE(response_.response_time.is_null());
2645 EXPECT_FALSE(response_.request_time.is_null());
2646
2647 // There is no body, so this should return immediately.
2648 EXPECT_EQ(
2649 0, promised_stream_->ReadResponseBody(
2650 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2651 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2652
2653 stream_->Close(true);
2654
2655 EXPECT_TRUE(AtEof());
ckrasic3865ee0f2016-02-29 22:04:562656}
2657
maksim.sisov84e20c92016-06-23 08:49:342658TEST_P(QuicHttpStreamTest, DataReadErrorSynchronous) {
2659 SetRequest("POST", "/", DEFAULT_PRIORITY);
2660 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232661 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252662 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232663 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Yixin Wange7ecc472018-03-06 19:00:252664 AddWrite(ConstructRequestAndRstPacket(
Renjie Tangaadb84b2019-08-31 01:00:232665 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2666 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
2667 &spdy_request_headers_frame_length, quic::QUIC_ERROR_PROCESSING_STREAM));
maksim.sisov84e20c92016-06-23 08:49:342668
2669 Initialize();
2670
Jeremy Roman0579ed62017-08-29 15:56:192671 upload_data_stream_ = std::make_unique<ReadErrorUploadDataStream>(
maksim.sisov84e20c92016-06-23 08:49:342672 ReadErrorUploadDataStream::FailureMode::SYNC);
2673 request_.method = "POST";
rchcd379012017-04-12 21:53:322674 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122675 request_.upload_data_stream = upload_data_stream_.get();
maksim.sisov84e20c92016-06-23 08:49:342676 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202677 TestCompletionCallback().callback(), NetLogWithSource()));
maksim.sisov84e20c92016-06-23 08:49:342678
Matt Reichhoff0049a0b72021-10-20 20:44:262679 EXPECT_EQ(OK, stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
2680 net_log_with_source_,
2681 callback_.callback()));
maksim.sisov84e20c92016-06-23 08:49:342682
2683 int result = stream_->SendRequest(headers_, &response_, callback_.callback());
robpercival214763f2016-07-01 23:27:012684 EXPECT_THAT(result, IsError(ERR_FAILED));
maksim.sisov84e20c92016-06-23 08:49:342685
2686 EXPECT_TRUE(AtEof());
2687
2688 // QuicHttpStream::GetTotalSent/ReceivedBytes includes only headers.
2689 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
2690 stream_->GetTotalSentBytes());
2691 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2692}
2693
2694TEST_P(QuicHttpStreamTest, DataReadErrorAsynchronous) {
2695 SetRequest("POST", "/", DEFAULT_PRIORITY);
2696 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232697 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252698 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232699 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:372700 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:232701 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2702 kIncludeVersion, !kFin, DEFAULT_PRIORITY,
2703 &spdy_request_headers_frame_length));
2704 AddWrite(
2705 ConstructClientRstStreamErrorPacket(packet_number++, !kIncludeVersion));
maksim.sisov84e20c92016-06-23 08:49:342706
2707 Initialize();
2708
Jeremy Roman0579ed62017-08-29 15:56:192709 upload_data_stream_ = std::make_unique<ReadErrorUploadDataStream>(
maksim.sisov84e20c92016-06-23 08:49:342710 ReadErrorUploadDataStream::FailureMode::ASYNC);
2711 request_.method = "POST";
rchcd379012017-04-12 21:53:322712 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122713 request_.upload_data_stream = upload_data_stream_.get();
maksim.sisov84e20c92016-06-23 08:49:342714 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202715 TestCompletionCallback().callback(), NetLogWithSource()));
maksim.sisov84e20c92016-06-23 08:49:342716
Matt Reichhoff0049a0b72021-10-20 20:44:262717 EXPECT_EQ(OK, stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
2718 net_log_with_source_,
2719 callback_.callback()));
maksim.sisov84e20c92016-06-23 08:49:342720
2721 int result = stream_->SendRequest(headers_, &response_, callback_.callback());
2722
Renjie90e808e2019-01-24 07:24:042723 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
Kenichi Ishibashif8634ab2021-03-16 23:41:282724 SetResponse("200", string());
maksim.sisov84e20c92016-06-23 08:49:342725
robpercival214763f2016-07-01 23:27:012726 EXPECT_THAT(result, IsError(ERR_IO_PENDING));
2727 EXPECT_THAT(callback_.GetResult(result), IsError(ERR_FAILED));
maksim.sisov84e20c92016-06-23 08:49:342728
2729 EXPECT_TRUE(AtEof());
2730
2731 // QuicHttpStream::GetTotalSent/ReceivedBytes includes only headers.
2732 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
2733 stream_->GetTotalSentBytes());
2734 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2735}
2736
Bence Béky97ec688c2021-03-16 13:48:502737TEST_P(QuicHttpStreamTest, GetAcceptChViaAlps) {
2738 AddWrite(ConstructInitialSettingsPacket());
2739 Initialize();
2740
2741 if (!VersionUsesHttp3(version_.transport_version)) {
2742 // ALPS is only implemented for HTTP/3.
2743 return;
2744 }
2745
2746 base::HistogramTester histogram_tester;
2747
2748 session_->OnAcceptChFrameReceivedViaAlps(
Bence Béky41a34f02021-05-07 00:27:482749 {{{"https://www.example.org", "Sec-CH-UA-Platform"}}});
Bence Béky97ec688c2021-03-16 13:48:502750
2751 request_.method = "GET";
2752 request_.url = GURL("https://www.example.org/foo");
2753
Matt Reichhoff0049a0b72021-10-20 20:44:262754 EXPECT_EQ(OK, stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
2755 net_log_with_source_,
2756 callback_.callback()));
Bence Béky41a34f02021-05-07 00:27:482757 EXPECT_EQ("Sec-CH-UA-Platform", stream_->GetAcceptChViaAlps());
Bence Béky97ec688c2021-03-16 13:48:502758 EXPECT_TRUE(AtEof());
2759
2760 histogram_tester.ExpectBucketCount(
2761 "Net.QuicSession.AcceptChFrameReceivedViaAlps", 1, 1);
2762 histogram_tester.ExpectTotalCount(
2763 "Net.QuicSession.AcceptChFrameReceivedViaAlps", 1);
2764 histogram_tester.ExpectBucketCount("Net.QuicSession.AcceptChForOrigin", 1, 1);
2765 histogram_tester.ExpectTotalCount("Net.QuicSession.AcceptChForOrigin", 1);
2766}
2767
[email protected]f702d572012-12-04 15:56:202768} // namespace test
[email protected]f702d572012-12-04 15:56:202769} // namespace net