blob: a28084f5e6d3de74efa516a895b694e5a3da7828 [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"
Avi Drissman4365a4782018-12-28 19:26:2415#include "base/stl_util.h"
Bence Békye0d3747d2020-08-28 23:16:4016#include "base/strings/strcat.h"
xunjieli188bd402016-03-12 00:17:2517#include "base/strings/string_number_conversions.h"
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"
[email protected]f702d572012-12-04 15:56:2029#include "net/http/http_response_headers.h"
[email protected]5db452202014-08-19 05:22:1530#include "net/http/transport_security_state.h"
mikecirone8b85c432016-09-08 19:11:0031#include "net/log/net_log_event_type.h"
xunjieli5fafe142016-03-23 23:32:5432#include "net/log/test_net_log.h"
33#include "net/log/test_net_log_util.h"
Victor Vasiliev4f6fb892019-05-31 16:58:3134#include "net/quic/address_utils.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0835#include "net/quic/crypto/proof_verifier_chromium.h"
36#include "net/quic/mock_crypto_client_stream_factory.h"
Ryan Hamiltona1d1f4a2019-06-26 14:43:0437#include "net/quic/platform/impl/quic_test_impl.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0838#include "net/quic/quic_chromium_alarm_factory.h"
39#include "net/quic/quic_chromium_connection_helper.h"
40#include "net/quic/quic_chromium_packet_reader.h"
41#include "net/quic/quic_chromium_packet_writer.h"
Matt Menkefca05b62019-09-20 23:15:5642#include "net/quic/quic_crypto_client_config_handle.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0843#include "net/quic/quic_http_utils.h"
44#include "net/quic/quic_server_info.h"
45#include "net/quic/quic_stream_factory.h"
46#include "net/quic/quic_test_packet_maker.h"
Ryan Hamilton0d65a8c2019-06-07 00:46:0247#include "net/quic/quic_test_packet_printer.h"
Matt Menkefca05b62019-09-20 23:15:5648#include "net/quic/test_quic_crypto_client_config_handle.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0849#include "net/quic/test_task_runner.h"
tbansalca83c002016-04-28 20:56:2850#include "net/socket/socket_performance_watcher.h"
[email protected]f702d572012-12-04 15:56:2051#include "net/socket/socket_test_util.h"
Bence Béky94658bf2018-05-11 19:22:5852#include "net/spdy/spdy_http_utils.h"
rch03b7a202016-02-05 00:54:2053#include "net/test/cert_test_util.h"
robpercival214763f2016-07-01 23:27:0154#include "net/test/gtest_util.h"
rsleevia69c79a2016-06-22 03:28:4355#include "net/test/test_data_directory.h"
Gabriel Charettec7108742019-08-23 03:31:4056#include "net/test/test_with_task_environment.h"
Zhongyi Shid1c00fc42019-12-14 06:05:0957#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
Victor Vasiliev6bb59d22019-03-08 21:34:5158#include "net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.h"
59#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
60#include "net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h"
61#include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
David Schinazi3f7465c2019-07-12 01:57:0562#include "net/third_party/quiche/src/quic/core/http/spdy_server_push_utils.h"
Victor Vasiliev6bb59d22019-03-08 21:34:5163#include "net/third_party/quiche/src/quic/core/quic_connection.h"
64#include "net/third_party/quiche/src/quic/core/quic_utils.h"
65#include "net/third_party/quiche/src/quic/core/quic_write_blocked_list.h"
Ryan Hamiltona1d1f4a2019-06-26 14:43:0466#include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h"
67#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
Victor Vasiliev6bb59d22019-03-08 21:34:5168#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
69#include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
70#include "net/third_party/quiche/src/quic/test_tools/mock_random.h"
Bence Béky6e243aa2019-12-13 19:01:0771#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h"
Victor Vasiliev6bb59d22019-03-08 21:34:5172#include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
73#include "net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h"
74#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
Victor Vasiliev27cc7712019-01-24 11:50:1475#include "net/third_party/quiche/src/spdy/core/spdy_frame_builder.h"
76#include "net/third_party/quiche/src/spdy/core/spdy_framer.h"
77#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
Ramin Halavati683bcaa92018-02-14 08:42:3978#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
[email protected]f702d572012-12-04 15:56:2079#include "testing/gmock/include/gmock/gmock.h"
80#include "testing/gtest/include/gtest/gtest.h"
81
bnc614a92d32016-04-04 13:56:0782using std::string;
[email protected]f702d572012-12-04 15:56:2083using testing::_;
[email protected]06ff5152013-08-29 01:03:0584using testing::AnyNumber;
85using testing::Return;
[email protected]f702d572012-12-04 15:56:2086
87namespace net {
[email protected]f702d572012-12-04 15:56:2088namespace test {
[email protected]f702d572012-12-04 15:56:2089namespace {
90
[email protected]16ba7742014-08-22 00:57:2591const char kUploadData[] = "Really nifty data!";
rch9ae5b3b2016-02-11 00:36:2992const char kDefaultServerHostName[] = "www.example.org";
rchcd379012017-04-12 21:53:3293const uint16_t kDefaultServerPort = 443;
[email protected]f702d572012-12-04 15:56:2094
David Schinazi09e9a6012019-10-03 17:37:5795struct TestParams {
96 quic::ParsedQuicVersion version;
97 bool client_headers_include_h2_stream_dependency;
98};
99
100// Used by ::testing::PrintToStringParamName().
101std::string PrintToString(const TestParams& p) {
Zhongyi Shid1c00fc42019-12-14 06:05:09102 return quiche::QuicheStrCat(
David Schinazi09e9a6012019-10-03 17:37:57103 ParsedQuicVersionToString(p.version), "_",
104 (p.client_headers_include_h2_stream_dependency ? "" : "No"),
105 "Dependency");
106}
107
108std::vector<TestParams> GetTestParams() {
109 std::vector<TestParams> params;
110 quic::ParsedQuicVersionVector all_supported_versions =
111 quic::AllSupportedVersions();
112 for (const auto& version : all_supported_versions) {
113 params.push_back(TestParams{version, false});
114 params.push_back(TestParams{version, true});
115 }
116 return params;
117}
118
Bence Békye0d3747d2020-08-28 23:16:40119// Returns true if |params| is a dict, has an entry with key "headers", that
120// entry is a list of strings, which when interpreted as colon-separated
121// key-value pairs has exactly one entry with |key| and that entry has value
122// |expected_value|.
123bool CheckHeader(const base::Value& params,
124 base::StringPiece key,
125 base::StringPiece expected_value) {
126 if (!params.is_dict()) {
127 return false;
128 }
129 const base::Value* headers = params.FindListKey("headers");
130 if (!headers) {
131 return false;
132 }
133
134 std::string header_prefix = base::StrCat({key, ": "});
135 std::string expected_header = base::StrCat({header_prefix, expected_value});
136
137 auto header_list = headers->GetList();
138 auto header_it = header_list.begin();
139 bool header_found = false;
140 while (header_it != header_list.end()) {
141 if (!header_it->is_string()) {
142 return false;
143 }
144 const std::string& header = header_it->GetString();
145 if (base::StartsWith(header, header_prefix)) {
146 if (header_found) {
147 return false;
148 }
149 if (header != expected_header) {
150 return false;
151 }
152 header_found = true;
153 }
154 ++header_it;
155 }
156 return header_found;
157}
158
Ryan Hamilton8d9ee76e2018-05-29 23:52:52159class TestQuicConnection : public quic::QuicConnection {
[email protected]f702d572012-12-04 15:56:20160 public:
Ryan Hamilton8d9ee76e2018-05-29 23:52:52161 TestQuicConnection(const quic::ParsedQuicVersionVector& versions,
162 quic::QuicConnectionId connection_id,
[email protected]f702d572012-12-04 15:56:20163 IPEndPoint address,
rch12fef552016-01-15 16:26:31164 QuicChromiumConnectionHelper* helper,
rch16c74d1d2016-04-22 06:14:07165 QuicChromiumAlarmFactory* alarm_factory,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52166 quic::QuicPacketWriter* writer)
Victor Vasiliev4f6fb892019-05-31 16:58:31167 : quic::QuicConnection(connection_id,
Nick Harperd049f192020-10-02 02:56:10168 quic::QuicSocketAddress(),
Victor Vasiliev4f6fb892019-05-31 16:58:31169 ToQuicSocketAddress(address),
170 helper,
171 alarm_factory,
172 writer,
173 true /* owns_writer */,
174 quic::Perspective::IS_CLIENT,
175 versions) {}
[email protected]f702d572012-12-04 15:56:20176
Ryan Hamilton8d9ee76e2018-05-29 23:52:52177 void SetSendAlgorithm(quic::SendAlgorithmInterface* send_algorithm) {
178 quic::test::QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
[email protected]f702d572012-12-04 15:56:20179 }
180};
181
maksim.sisov84e20c92016-06-23 08:49:34182// UploadDataStream that always returns errors on data read.
183class ReadErrorUploadDataStream : public UploadDataStream {
184 public:
185 enum class FailureMode { SYNC, ASYNC };
186
187 explicit ReadErrorUploadDataStream(FailureMode mode)
Jeremy Romand54000b22019-07-08 18:40:16188 : UploadDataStream(true, 0), async_(mode) {}
maksim.sisov84e20c92016-06-23 08:49:34189 ~ReadErrorUploadDataStream() override {}
190
191 private:
192 void CompleteRead() { UploadDataStream::OnReadCompleted(ERR_FAILED); }
193
194 // UploadDataStream implementation:
tfarina42834112016-09-22 13:38:20195 int InitInternal(const NetLogWithSource& net_log) override { return OK; }
maksim.sisov84e20c92016-06-23 08:49:34196
197 int ReadInternal(IOBuffer* buf, int buf_len) override {
198 if (async_ == FailureMode::ASYNC) {
199 base::ThreadTaskRunnerHandle::Get()->PostTask(
kylecharf4fe5172019-02-15 18:53:49200 FROM_HERE, base::BindOnce(&ReadErrorUploadDataStream::CompleteRead,
201 weak_factory_.GetWeakPtr()));
maksim.sisov84e20c92016-06-23 08:49:34202 return ERR_IO_PENDING;
203 }
204 return ERR_FAILED;
205 }
206
207 void ResetInternal() override {}
208
209 const FailureMode async_;
210
Jeremy Romand54000b22019-07-08 18:40:16211 base::WeakPtrFactory<ReadErrorUploadDataStream> weak_factory_{this};
maksim.sisov84e20c92016-06-23 08:49:34212
213 DISALLOW_COPY_AND_ASSIGN(ReadErrorUploadDataStream);
214};
215
Bence Béky8ddc2492018-06-13 01:02:04216// A helper class that will delete |stream| when the callback is invoked.
xunjieli8dff50b2016-07-22 14:19:06217class DeleteStreamCallback : public TestCompletionCallbackBase {
218 public:
Bence Béky8ddc2492018-06-13 01:02:04219 explicit DeleteStreamCallback(std::unique_ptr<QuicHttpStream> stream)
220 : stream_(std::move(stream)) {}
xunjieli8dff50b2016-07-22 14:19:06221
Bence Béky8ddc2492018-06-13 01:02:04222 CompletionOnceCallback callback() {
223 return base::BindOnce(&DeleteStreamCallback::DeleteStream,
224 base::Unretained(this));
225 }
xunjieli8dff50b2016-07-22 14:19:06226
227 private:
228 void DeleteStream(int result) {
229 stream_.reset();
230 SetResult(result);
231 }
232
233 std::unique_ptr<QuicHttpStream> stream_;
xunjieli8dff50b2016-07-22 14:19:06234};
235
[email protected]f702d572012-12-04 15:56:20236} // namespace
237
[email protected]24e5bc52013-09-18 15:36:58238class QuicHttpStreamPeer {
239 public:
rch08e198572017-05-09 16:56:55240 static QuicChromiumClientStream::Handle* GetQuicChromiumClientStream(
[email protected]24e5bc52013-09-18 15:36:58241 QuicHttpStream* stream) {
rch08e198572017-05-09 16:56:55242 return stream->stream_.get();
[email protected]24e5bc52013-09-18 15:36:58243 }
244};
245
David Schinazi09e9a6012019-10-03 17:37:57246class QuicHttpStreamTest : public ::testing::TestWithParam<TestParams>,
Gabriel Charette694c3c332019-08-19 14:53:05247 public WithTaskEnvironment {
rchfb47f712017-05-21 03:24:00248 public:
249 void CloseStream(QuicHttpStream* stream, int /*rv*/) { stream->Close(false); }
250
[email protected]f702d572012-12-04 15:56:20251 protected:
[email protected]1e960032013-12-20 19:00:20252 static const bool kFin = true;
253 static const bool kIncludeVersion = true;
[email protected]1e960032013-12-20 19:00:20254
[email protected]f702d572012-12-04 15:56:20255 // Holds a packet to be written to the wire, and the IO mode that should
256 // be used by the mock socket when performing the write.
257 struct PacketToWrite {
Ryan Hamilton8d9ee76e2018-05-29 23:52:52258 PacketToWrite(IoMode mode, quic::QuicReceivedPacket* packet)
rjshaded5ced072015-12-18 19:26:02259 : mode(mode), packet(packet) {}
rtenneti15656ae2016-01-23 03:05:03260 PacketToWrite(IoMode mode, int rv) : mode(mode), packet(nullptr), rv(rv) {}
[email protected]f702d572012-12-04 15:56:20261 IoMode mode;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52262 quic::QuicReceivedPacket* packet;
rtenneti15656ae2016-01-23 03:05:03263 int rv;
[email protected]f702d572012-12-04 15:56:20264 };
265
266 QuicHttpStreamTest()
David Schinazi09e9a6012019-10-03 17:37:57267 : version_(GetParam().version),
268 client_headers_include_h2_stream_dependency_(
269 GetParam().client_headers_include_h2_stream_dependency),
Nick Harpera598fc5f2019-06-21 08:46:50270 crypto_config_(
271 quic::test::crypto_test_utils::ProofVerifierForTesting()),
Victor Costan9c7302b2018-08-27 16:39:44272 read_buffer_(base::MakeRefCounted<IOBufferWithSize>(4096)),
Fan Yang32c5a112018-12-10 20:06:33273 promise_id_(GetNthServerInitiatedUnidirectionalStreamId(0)),
274 stream_id_(GetNthClientInitiatedBidirectionalStreamId(0)),
David Schinazic8281052019-01-24 06:14:17275 connection_id_(quic::test::TestConnectionId(2)),
Yixin Wang079ad542018-01-11 04:06:05276 client_maker_(version_,
alyssar2adf3ac2016-05-03 17:12:58277 connection_id_,
278 &clock_,
279 kDefaultServerHostName,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52280 quic::Perspective::IS_CLIENT,
Yixin Wang079ad542018-01-11 04:06:05281 client_headers_include_h2_stream_dependency_),
282 server_maker_(version_,
zhongyi5dbfdd42017-06-20 05:22:15283 connection_id_,
alyssar2adf3ac2016-05-03 17:12:58284 &clock_,
285 kDefaultServerHostName,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52286 quic::Perspective::IS_SERVER,
Yixin Wang079ad542018-01-11 04:06:05287 false),
ckrasic3865ee0f2016-02-29 22:04:56288 random_generator_(0),
Ryan Hamilton0d65a8c2019-06-07 00:46:02289 printer_(version_) {
Renjie Tang98b4d512020-02-08 01:24:19290 FLAGS_quic_enable_http3_grease_randomness = false;
Zhongyi Shi49f8ad2fd2019-12-13 01:20:31291 quic::QuicEnableVersion(version_);
martijn21968ea2016-02-24 18:46:20292 IPAddress ip(192, 0, 2, 33);
[email protected]f702d572012-12-04 15:56:20293 peer_addr_ = IPEndPoint(ip, 443);
294 self_addr_ = IPEndPoint(ip, 8435);
Ryan Hamilton8d9ee76e2018-05-29 23:52:52295 clock_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(20));
Ramin Halavati683bcaa92018-02-14 08:42:39296 request_.traffic_annotation =
297 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f702d572012-12-04 15:56:20298 }
299
300 ~QuicHttpStreamTest() {
Renjieba55fae2018-09-20 03:05:16301 session_->CloseSessionOnError(ERR_ABORTED, quic::QUIC_INTERNAL_ERROR,
302 quic::ConnectionCloseBehavior::SILENT_CLOSE);
[email protected]f702d572012-12-04 15:56:20303 for (size_t i = 0; i < writes_.size(); i++) {
304 delete writes_[i].packet;
305 }
306 }
307
308 // Adds a packet to the list of expected writes.
Ryan Hamilton8d9ee76e2018-05-29 23:52:52309 void AddWrite(std::unique_ptr<quic::QuicReceivedPacket> packet) {
[email protected]1e960032013-12-20 19:00:20310 writes_.push_back(PacketToWrite(SYNCHRONOUS, packet.release()));
[email protected]f702d572012-12-04 15:56:20311 }
312
rtenneti15656ae2016-01-23 03:05:03313 void AddWrite(IoMode mode, int rv) {
314 writes_.push_back(PacketToWrite(mode, rv));
315 }
316
[email protected]f702d572012-12-04 15:56:20317 // Returns the packet to be written at position |pos|.
Ryan Hamilton8d9ee76e2018-05-29 23:52:52318 quic::QuicReceivedPacket* GetWrite(size_t pos) { return writes_[pos].packet; }
[email protected]f702d572012-12-04 15:56:20319
320 bool AtEof() {
rch37de576c2015-05-17 20:28:17321 return socket_data_->AllReadDataConsumed() &&
322 socket_data_->AllWriteDataConsumed();
[email protected]f702d572012-12-04 15:56:20323 }
324
Ryan Hamilton8d9ee76e2018-05-29 23:52:52325 void ProcessPacket(std::unique_ptr<quic::QuicReceivedPacket> packet) {
Victor Vasiliev4f6fb892019-05-31 16:58:31326 connection_->ProcessUdpPacket(ToQuicSocketAddress(self_addr_),
327 ToQuicSocketAddress(peer_addr_), *packet);
[email protected]f702d572012-12-04 15:56:20328 }
329
330 // Configures the test fixture to use the list of expected writes.
331 void Initialize() {
332 mock_writes_.reset(new MockWrite[writes_.size()]);
333 for (size_t i = 0; i < writes_.size(); i++) {
rtenneti15656ae2016-01-23 03:05:03334 if (writes_[i].packet == nullptr) {
335 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].rv, i);
336 } else {
337 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].packet->data(),
338 writes_[i].packet->length());
339 }
bnc614a92d32016-04-04 13:56:07340 }
[email protected]f702d572012-12-04 15:56:20341
rtennetibe635732014-10-02 22:51:42342 socket_data_.reset(new StaticSocketDataProvider(
Ryan Sleevib8d7ea02018-05-07 20:01:01343 base::span<MockRead>(),
344 base::make_span(mock_writes_.get(), writes_.size())));
Ryan Hamilton0d65a8c2019-06-07 00:46:02345 socket_data_->set_printer(&printer_);
[email protected]f702d572012-12-04 15:56:20346
danakjad1777e2016-04-16 00:56:42347 std::unique_ptr<MockUDPClientSocket> socket(new MockUDPClientSocket(
xunjielib53b38c2016-03-24 15:54:36348 socket_data_.get(), net_log_.bound().net_log()));
[email protected]e13201d82012-12-12 05:00:32349 socket->Connect(peer_addr_);
[email protected]f702d572012-12-04 15:56:20350 runner_ = new TestTaskRunner(&clock_);
Ryan Hamilton8d9ee76e2018-05-29 23:52:52351 send_algorithm_ = new quic::test::MockSendAlgorithm();
rch7dd15702015-07-01 18:57:57352 EXPECT_CALL(*send_algorithm_, InRecovery()).WillRepeatedly(Return(false));
353 EXPECT_CALL(*send_algorithm_, InSlowStart()).WillRepeatedly(Return(false));
Victor Vasiliev7da08172019-10-14 06:04:25354 if (VersionUsesHttp3(version_.transport_version)) {
Renjie Tangaadb84b2019-08-31 01:00:23355 EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
356 .Times(testing::AtLeast(1));
357 }
Ryan Hamiltona1d1f4a2019-06-26 14:43:04358 EXPECT_CALL(*send_algorithm_, OnCongestionEvent(_, _, _, _, _))
359 .Times(AnyNumber());
rtenneti44f4a2e2015-08-07 14:00:07360 EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
Zhongyi Shica576df2019-04-12 17:43:40361 .WillRepeatedly(Return(quic::kMaxOutgoingPacketSize));
jokulik0e0a00c32016-06-13 21:51:58362 EXPECT_CALL(*send_algorithm_, PacingRate(_))
Ryan Hamilton8d9ee76e2018-05-29 23:52:52363 .WillRepeatedly(Return(quic::QuicBandwidth::Zero()));
Michael Warres74ee3ce2017-10-09 15:26:37364 EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true));
rtenneti44f4a2e2015-08-07 14:00:07365 EXPECT_CALL(*send_algorithm_, BandwidthEstimate())
Ryan Hamilton8d9ee76e2018-05-29 23:52:52366 .WillRepeatedly(Return(quic::QuicBandwidth::Zero()));
rch1e543ec2015-03-29 07:04:40367 EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(AnyNumber());
rch08cae032017-03-29 00:59:15368 EXPECT_CALL(*send_algorithm_, OnApplicationLimited(_)).Times(AnyNumber());
rch0d5bcf62017-05-24 22:48:45369 EXPECT_CALL(*send_algorithm_, GetCongestionControlType())
370 .Times(AnyNumber());
rch16c74d1d2016-04-22 06:14:07371 helper_.reset(
372 new QuicChromiumConnectionHelper(&clock_, &random_generator_));
373 alarm_factory_.reset(new QuicChromiumAlarmFactory(runner_.get(), &clock_));
374
Michael Warres74ee3ce2017-10-09 15:26:37375 connection_ = new TestQuicConnection(
Nick Harper23290b82019-05-02 00:02:56376 quic::test::SupportedVersions(version_), connection_id_, peer_addr_,
377 helper_.get(), alarm_factory_.get(),
Ryan Hamilton9edcf1a2017-11-22 05:55:17378 new QuicChromiumPacketWriter(
379 socket.get(), base::ThreadTaskRunnerHandle::Get().get()));
[email protected]f702d572012-12-04 15:56:20380 connection_->set_visitor(&visitor_);
[email protected]fee17f72013-02-03 07:47:41381 connection_->SetSendAlgorithm(send_algorithm_);
rch03b7a202016-02-05 00:54:20382
383 // Load a certificate that is valid for *.example.org
384 scoped_refptr<X509Certificate> test_cert(
385 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
386 EXPECT_TRUE(test_cert.get());
387
388 verify_details_.cert_verify_result.verified_cert = test_cert;
389 verify_details_.cert_verify_result.is_issued_by_known_root = true;
390 crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details_);
391
xunjieli84adaab2016-09-20 01:12:28392 base::TimeTicks dns_end = base::TimeTicks::Now();
393 base::TimeTicks dns_start = dns_end - base::TimeDelta::FromMilliseconds(1);
ckrasic4f9d88d2015-07-22 22:23:16394 session_.reset(new QuicChromiumClientSession(
xunjielib53b38c2016-03-24 15:54:36395 connection_, std::move(socket),
rtenneti1cd3b162015-09-29 02:58:28396 /*stream_factory=*/nullptr, &crypto_client_stream_factory_, &clock_,
Nick Harper89bc7212018-07-31 19:07:57397 &transport_security_state_, /*ssl_config_service=*/nullptr,
danakjad1777e2016-04-16 00:56:42398 base::WrapUnique(static_cast<QuicServerInfo*>(nullptr)),
Paul Jensen8e3c5d32018-02-19 17:06:33399 QuicSessionKey(kDefaultServerHostName, kDefaultServerPort,
dalyk51ab46b2019-10-15 15:14:34400 PRIVACY_MODE_DISABLED, SocketTag(),
401 NetworkIsolationKey(), false /* disable_secure_dns */),
Bence Béky1ceba552019-07-19 17:11:05402 /*require_confirmation=*/false,
403 /*max_allowed_push_id=*/0,
404 /*migrate_session_early_v2=*/false,
Zhongyi Shi757fcce2018-06-27 05:41:27405 /*migrate_session_on_network_change_v2=*/false,
406 /*default_network=*/NetworkChangeNotifier::kInvalidNetworkHandle,
Zhongyi Shie01f2db2019-02-22 19:53:23407 quic::QuicTime::Delta::FromMilliseconds(
Ryan Sleevi2e8255b2019-07-17 21:02:21408 kDefaultRetransmittableOnWireTimeout.InMilliseconds()),
Zhongyi Shiaf38c4e42019-08-29 22:49:05409 /*migrate_idle_session=*/false, /*allow_port_migration=*/false,
410 kDefaultIdleSessionMigrationPeriod, kMaxTimeOnNonDefaultNetwork,
Zhongyi Shiee760762018-08-01 00:54:29411 kMaxMigrationsToNonDefaultNetworkOnWriteError,
Zhongyi Shi8b1e43f2017-12-13 20:46:30412 kMaxMigrationsToNonDefaultNetworkOnPathDegrading,
Zhongyi Shi5f587cc2017-11-21 23:24:17413 kQuicYieldAfterPacketsRead,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52414 quic::QuicTime::Delta::FromMilliseconds(
415 kQuicYieldAfterDurationMilliseconds),
Zhongyi Shidbce7f412019-02-01 23:16:29416 /*go_away_on_path_degrading*/ false,
Yixin Wang079ad542018-01-11 04:06:05417 client_headers_include_h2_stream_dependency_, /*cert_verify_flags=*/0,
Matt Menkefca05b62019-09-20 23:15:56418 quic::test::DefaultQuicConfig(),
419 std::make_unique<TestQuicCryptoClientConfigHandle>(&crypto_config_),
Matt Menked804aaf2020-07-21 21:25:48420 "CONNECTION_UNKNOWN", dns_start, dns_end,
421 std::make_unique<quic::QuicClientPushPromiseIndex>(), nullptr,
Zhongyi Shic16b4102019-02-12 00:37:40422 base::DefaultTickClock::GetInstance(),
xunjieli84adaab2016-09-20 01:12:28423 base::ThreadTaskRunnerHandle::Get().get(),
xunjieli5fafe142016-03-23 23:32:54424 /*socket_performance_watcher=*/nullptr, net_log_.bound().net_log()));
rtennetid39bd762015-06-12 01:05:52425 session_->Initialize();
rchf0b18c8a2017-05-05 19:31:57426
Bence Béky6e243aa2019-12-13 19:01:07427 // Blackhole QPACK decoder stream instead of constructing mock writes.
428 if (VersionUsesHttp3(version_.transport_version)) {
429 session_->qpack_decoder()->set_qpack_stream_sender_delegate(
430 &noop_qpack_stream_sender_delegate_);
431 }
432
433 TestCompletionCallback callback;
rch433bf5f2017-02-14 04:10:47434 session_->CryptoConnect(callback.callback());
Ryan Hamilton6c2a2a82017-12-15 02:06:28435 stream_ = std::make_unique<QuicHttpStream>(
436 session_->CreateHandle(HostPortPair("www.example.org", 443)));
437 promised_stream_ = std::make_unique<QuicHttpStream>(
438 session_->CreateHandle(HostPortPair("www.example.org", 443)));
ckrasic3865ee0f2016-02-29 22:04:56439 push_promise_[":path"] = "/bar";
440 push_promise_[":authority"] = "www.example.org";
441 push_promise_[":version"] = "HTTP/1.1";
442 push_promise_[":method"] = "GET";
443 push_promise_[":scheme"] = "https";
444
445 promised_response_[":status"] = "200 OK";
446 promised_response_[":version"] = "HTTP/1.1";
447 promised_response_["content-type"] = "text/plain";
448
David Schinazi3f7465c2019-07-12 01:57:05449 promise_url_ =
450 quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
[email protected]6cca996b2013-01-25 07:43:36451 }
452
bnc614a92d32016-04-04 13:56:07453 void SetRequest(const string& method,
454 const string& path,
[email protected]1e960032013-12-20 19:00:20455 RequestPriority priority) {
rchcd379012017-04-12 21:53:32456 request_headers_ = client_maker_.GetRequestHeaders(method, "https", path);
[email protected]6cca996b2013-01-25 07:43:36457 }
458
bnc614a92d32016-04-04 13:56:07459 void SetResponse(const string& status, const string& body) {
alyssar2adf3ac2016-05-03 17:12:58460 response_headers_ = server_maker_.GetResponseHeaders(status);
[email protected]92bf17c2014-03-03 21:14:03461 response_data_ = body;
[email protected]6cca996b2013-01-25 07:43:36462 }
[email protected]f702d572012-12-04 15:56:20463
Ryan Hamilton8d9ee76e2018-05-29 23:52:52464 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientDataPacket(
Fan Yangac867502019-01-28 21:10:23465 uint64_t packet_number,
[email protected]e8ff26842013-03-22 21:02:05466 bool should_include_version,
[email protected]f702d572012-12-04 15:56:20467 bool fin,
Victor Vasiliev47ecb6a2020-10-14 17:22:10468 absl::string_view data) {
Ryan Hamilton7505eb92019-06-08 00:22:17469 return client_maker_.MakeDataPacket(packet_number, stream_id_,
470 should_include_version, fin, data);
alyssar2adf3ac2016-05-03 17:12:58471 }
472
Ryan Hamilton8d9ee76e2018-05-29 23:52:52473 std::unique_ptr<quic::QuicReceivedPacket> ConstructServerDataPacket(
Fan Yangac867502019-01-28 21:10:23474 uint64_t packet_number,
alyssar2adf3ac2016-05-03 17:12:58475 bool should_include_version,
476 bool fin,
Victor Vasiliev47ecb6a2020-10-14 17:22:10477 absl::string_view data) {
Ryan Hamilton7505eb92019-06-08 00:22:17478 return server_maker_.MakeDataPacket(packet_number, stream_id_,
479 should_include_version, fin, data);
ckrasic3865ee0f2016-02-29 22:04:56480 }
481
Ryan Hamilton8d9ee76e2018-05-29 23:52:52482 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23483 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52484 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56485 bool should_include_version,
486 bool fin,
487 RequestPriority request_priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02488 size_t* spdy_headers_frame_length) {
Yixin Wang7a3f1b8d2018-01-17 21:40:48489 return InnerConstructRequestHeadersPacket(
490 packet_number, stream_id, should_include_version, fin, request_priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02491 0, spdy_headers_frame_length);
Yixin Wang7a3f1b8d2018-01-17 21:40:48492 }
493
Ryan Hamilton8d9ee76e2018-05-29 23:52:52494 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23495 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52496 quic::QuicStreamId stream_id,
Yixin Wang7a3f1b8d2018-01-17 21:40:48497 bool should_include_version,
498 bool fin,
499 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52500 quic::QuicStreamId parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02501 size_t* spdy_headers_frame_length) {
Ryan Hamilton0239aac2018-05-19 00:03:13502 spdy::SpdyPriority priority =
ckrasic3865ee0f2016-02-29 22:04:56503 ConvertRequestPriorityToQuicPriority(request_priority);
alyssar2adf3ac2016-05-03 17:12:58504 return client_maker_.MakeRequestHeadersPacket(
ckrasic3865ee0f2016-02-29 22:04:56505 packet_number, stream_id, should_include_version, fin, priority,
Yixin Wang7a3f1b8d2018-01-17 21:40:48506 std::move(request_headers_), parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02507 spdy_headers_frame_length);
[email protected]f702d572012-12-04 15:56:20508 }
509
Ryan Hamilton8d9ee76e2018-05-29 23:52:52510 std::unique_ptr<quic::QuicReceivedPacket>
Yixin Wange7ecc472018-03-06 19:00:25511 ConstructRequestHeadersAndDataFramesPacket(
Fan Yangac867502019-01-28 21:10:23512 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52513 quic::QuicStreamId stream_id,
Yixin Wange7ecc472018-03-06 19:00:25514 bool should_include_version,
515 bool fin,
516 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52517 quic::QuicStreamId parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25518 size_t* spdy_headers_frame_length,
519 const std::vector<std::string>& data_writes) {
Ryan Hamilton0239aac2018-05-19 00:03:13520 spdy::SpdyPriority priority =
Yixin Wange7ecc472018-03-06 19:00:25521 ConvertRequestPriorityToQuicPriority(request_priority);
522 return client_maker_.MakeRequestHeadersAndMultipleDataFramesPacket(
523 packet_number, stream_id, should_include_version, fin, priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02524 std::move(request_headers_), parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25525 spdy_headers_frame_length, data_writes);
526 }
527
Ryan Hamilton8d9ee76e2018-05-29 23:52:52528 std::unique_ptr<quic::QuicReceivedPacket> ConstructRequestAndRstPacket(
Fan Yangac867502019-01-28 21:10:23529 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52530 quic::QuicStreamId stream_id,
Yixin Wange7ecc472018-03-06 19:00:25531 bool should_include_version,
532 bool fin,
533 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52534 quic::QuicStreamId parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25535 size_t* spdy_headers_frame_length,
Ryan Hamiltonb5d4c5a2019-06-21 22:08:41536 quic::QuicRstStreamErrorCode error_code) {
Ryan Hamilton0239aac2018-05-19 00:03:13537 spdy::SpdyPriority priority =
Yixin Wange7ecc472018-03-06 19:00:25538 ConvertRequestPriorityToQuicPriority(request_priority);
539 return client_maker_.MakeRequestHeadersAndRstPacket(
540 packet_number, stream_id, should_include_version, fin, priority,
541 std::move(request_headers_), parent_stream_id,
Ryan Hamiltonb5d4c5a2019-06-21 22:08:41542 spdy_headers_frame_length, error_code);
Yixin Wange7ecc472018-03-06 19:00:25543 }
544
Ryan Hamilton8d9ee76e2018-05-29 23:52:52545 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructResponseHeadersPacket(
Fan Yangac867502019-01-28 21:10:23546 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52547 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56548 bool fin,
549 size_t* spdy_headers_frame_length) {
alyssar2adf3ac2016-05-03 17:12:58550 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26551 packet_number, stream_id, !kIncludeVersion, fin,
Ryan Hamilton0d65a8c2019-06-07 00:46:02552 std::move(response_headers_), spdy_headers_frame_length);
[email protected]1e960032013-12-20 19:00:20553 }
554
Ryan Hamilton8d9ee76e2018-05-29 23:52:52555 std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseHeadersPacket(
Fan Yangac867502019-01-28 21:10:23556 uint64_t packet_number,
sclittlec4dc1a32015-09-24 00:15:45557 bool fin,
558 size_t* spdy_headers_frame_length) {
ckrasic3865ee0f2016-02-29 22:04:56559 return InnerConstructResponseHeadersPacket(packet_number, stream_id_, fin,
560 spdy_headers_frame_length);
[email protected]1e960032013-12-20 19:00:20561 }
562
Ryan Hamilton8d9ee76e2018-05-29 23:52:52563 std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseTrailersPacket(
Fan Yangac867502019-01-28 21:10:23564 uint64_t packet_number,
xunjieli34291fe12016-03-02 13:58:38565 bool fin,
Ryan Hamilton0239aac2018-05-19 00:03:13566 spdy::SpdyHeaderBlock trailers,
Ryan Hamilton0d65a8c2019-06-07 00:46:02567 size_t* spdy_headers_frame_length) {
alyssar2adf3ac2016-05-03 17:12:58568 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26569 packet_number, stream_id_, !kIncludeVersion, fin, std::move(trailers),
Ryan Hamilton0d65a8c2019-06-07 00:46:02570 spdy_headers_frame_length);
xunjieli34291fe12016-03-02 13:58:38571 }
572
Ryan Hamilton8d9ee76e2018-05-29 23:52:52573 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientRstStreamErrorPacket(
Fan Yangac867502019-01-28 21:10:23574 uint64_t packet_number,
maksim.sisov84e20c92016-06-23 08:49:34575 bool include_version) {
576 return client_maker_.MakeRstPacket(packet_number, include_version,
577 stream_id_,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52578 quic::QUIC_ERROR_PROCESSING_STREAM);
maksim.sisov84e20c92016-06-23 08:49:34579 }
580
Ryan Hamilton8d9ee76e2018-05-29 23:52:52581 std::unique_ptr<quic::QuicReceivedPacket> ConstructAckAndRstStreamPacket(
Fan Yangac867502019-01-28 21:10:23582 uint64_t packet_number) {
Renjie Tangcd594f32020-07-11 20:18:34583 return client_maker_.MakeAckAndRstPacket(packet_number, !kIncludeVersion,
584 stream_id_,
585 quic::QUIC_STREAM_CANCELLED, 2, 1);
[email protected]c5e1aca2014-01-30 04:03:04586 }
587
Ryan Hamilton8d9ee76e2018-05-29 23:52:52588 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientAckPacket(
Fan Yangac867502019-01-28 21:10:23589 uint64_t packet_number,
590 uint64_t largest_received,
Renjie Tangcd594f32020-07-11 20:18:34591 uint64_t smallest_received) {
alyssar2adf3ac2016-05-03 17:12:58592 return client_maker_.MakeAckPacket(packet_number, largest_received,
Renjie Tangcd594f32020-07-11 20:18:34593 smallest_received);
alyssar2adf3ac2016-05-03 17:12:58594 }
595
Ryan Hamilton8d9ee76e2018-05-29 23:52:52596 std::unique_ptr<quic::QuicReceivedPacket> ConstructServerAckPacket(
Fan Yangac867502019-01-28 21:10:23597 uint64_t packet_number,
598 uint64_t largest_received,
599 uint64_t smallest_received,
600 uint64_t least_unacked) {
alyssar2adf3ac2016-05-03 17:12:58601 return server_maker_.MakeAckPacket(packet_number, largest_received,
Bence Béky7a45d4d2020-05-08 01:59:23602 smallest_received, least_unacked);
[email protected]63534512012-12-23 18:49:00603 }
604
Ryan Hamilton0d65a8c2019-06-07 00:46:02605 std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket() {
606 return client_maker_.MakeInitialSettingsPacket(1);
fayang3bcb8b502016-12-07 21:44:37607 }
608
Renjie Tangaadb84b2019-08-31 01:00:23609 std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket(
610 int packet_number) {
611 return client_maker_.MakeInitialSettingsPacket(packet_number);
612 }
613
Victor Vasiliev076657c2019-03-12 02:46:43614 std::string ConstructDataHeader(size_t body_len) {
Nick Harperc6cb7a612020-02-24 20:03:32615 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:41616 return "";
617 }
Renjief49758b2019-01-11 23:32:41618 std::unique_ptr<char[]> buffer;
Victor Vasiliev55d997922019-10-31 19:40:57619 auto header_length =
620 quic::HttpEncoder::SerializeDataFrameHeader(body_len, &buffer);
Victor Vasiliev076657c2019-03-12 02:46:43621 return std::string(buffer.get(), header_length);
Renjief49758b2019-01-11 23:32:41622 }
623
Ryan Hamilton8d9ee76e2018-05-29 23:52:52624 void ReceivePromise(quic::QuicStreamId id) {
625 auto headers = quic::test::AsHeaderList(push_promise_);
rch08e198572017-05-09 16:56:55626 QuicChromiumClientStream::Handle* stream =
ckrasic3865ee0f2016-02-29 22:04:56627 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
ckrasic32b17dcd2016-10-31 06:15:35628 stream->OnPromiseHeaderList(id, headers.uncompressed_header_bytes(),
629 headers);
ckrasic3865ee0f2016-02-29 22:04:56630 }
631
xunjieli84adaab2016-09-20 01:12:28632 void ExpectLoadTimingValid(const LoadTimingInfo& load_timing_info,
xunjieli100937eb52016-09-15 20:09:37633 bool session_reused) {
634 EXPECT_EQ(session_reused, load_timing_info.socket_reused);
xunjieli84adaab2016-09-20 01:12:28635 if (session_reused) {
636 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
637 } else {
638 ExpectConnectTimingHasTimes(
639 load_timing_info.connect_timing,
640 CONNECT_TIMING_HAS_SSL_TIMES | CONNECT_TIMING_HAS_DNS_TIMES);
641 }
642 ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info);
xunjieli100937eb52016-09-15 20:09:37643 }
644
Fan Yang32c5a112018-12-10 20:06:33645 quic::QuicStreamId GetNthClientInitiatedBidirectionalStreamId(int n) {
Nick Harper23290b82019-05-02 00:02:56646 return quic::test::GetNthClientInitiatedBidirectionalStreamId(
647 version_.transport_version, n);
ckrasicbf2f59c2017-05-04 23:54:36648 }
649
Fan Yang32c5a112018-12-10 20:06:33650 quic::QuicStreamId GetNthServerInitiatedUnidirectionalStreamId(int n) {
Nick Harper23290b82019-05-02 00:02:56651 return quic::test::GetNthServerInitiatedUnidirectionalStreamId(
652 version_.transport_version, n);
ckrasicbf2f59c2017-05-04 23:54:36653 }
654
Ryan Hamiltona1d1f4a2019-06-26 14:43:04655 QuicFlagSaver saver_;
656
Nick Harper23290b82019-05-02 00:02:56657 const quic::ParsedQuicVersion version_;
Yixin Wang079ad542018-01-11 04:06:05658 const bool client_headers_include_h2_stream_dependency_;
659
Matt Muellerd9342e3a2019-11-26 01:41:14660 RecordingBoundTestNetLog net_log_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52661 quic::test::MockSendAlgorithm* send_algorithm_;
[email protected]f702d572012-12-04 15:56:20662 scoped_refptr<TestTaskRunner> runner_;
danakjad1777e2016-04-16 00:56:42663 std::unique_ptr<MockWrite[]> mock_writes_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52664 quic::MockClock clock_;
[email protected]f702d572012-12-04 15:56:20665 TestQuicConnection* connection_;
danakjad1777e2016-04-16 00:56:42666 std::unique_ptr<QuicChromiumConnectionHelper> helper_;
rch16c74d1d2016-04-22 06:14:07667 std::unique_ptr<QuicChromiumAlarmFactory> alarm_factory_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52668 testing::StrictMock<quic::test::MockQuicConnectionVisitor> visitor_;
rch97827ee2017-05-24 23:49:12669 std::unique_ptr<UploadDataStream> upload_data_stream_;
danakjad1777e2016-04-16 00:56:42670 std::unique_ptr<QuicHttpStream> stream_;
[email protected]5db452202014-08-19 05:22:15671 TransportSecurityState transport_security_state_;
danakjad1777e2016-04-16 00:56:42672 std::unique_ptr<QuicChromiumClientSession> session_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52673 quic::QuicCryptoClientConfig crypto_config_;
[email protected]f702d572012-12-04 15:56:20674 TestCompletionCallback callback_;
675 HttpRequestInfo request_;
676 HttpRequestHeaders headers_;
677 HttpResponseInfo response_;
678 scoped_refptr<IOBufferWithSize> read_buffer_;
Ryan Hamilton0239aac2018-05-19 00:03:13679 spdy::SpdyHeaderBlock request_headers_;
680 spdy::SpdyHeaderBlock response_headers_;
bnc614a92d32016-04-04 13:56:07681 string request_data_;
682 string response_data_;
[email protected]f702d572012-12-04 15:56:20683
ckrasic3865ee0f2016-02-29 22:04:56684 // For server push testing
danakjad1777e2016-04-16 00:56:42685 std::unique_ptr<QuicHttpStream> promised_stream_;
Ryan Hamilton0239aac2018-05-19 00:03:13686 spdy::SpdyHeaderBlock push_promise_;
687 spdy::SpdyHeaderBlock promised_response_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52688 const quic::QuicStreamId promise_id_;
ckrasic3865ee0f2016-02-29 22:04:56689 string promise_url_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52690 const quic::QuicStreamId stream_id_;
ckrasic3865ee0f2016-02-29 22:04:56691
Ryan Hamilton8d9ee76e2018-05-29 23:52:52692 const quic::QuicConnectionId connection_id_;
alyssar2adf3ac2016-05-03 17:12:58693 QuicTestPacketMaker client_maker_;
694 QuicTestPacketMaker server_maker_;
[email protected]f702d572012-12-04 15:56:20695 IPEndPoint self_addr_;
696 IPEndPoint peer_addr_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52697 quic::test::MockRandom random_generator_;
rch03b7a202016-02-05 00:54:20698 ProofVerifyDetailsChromium verify_details_;
[email protected]e8ff26842013-03-22 21:02:05699 MockCryptoClientStreamFactory crypto_client_stream_factory_;
danakjad1777e2016-04-16 00:56:42700 std::unique_ptr<StaticSocketDataProvider> socket_data_;
Ryan Hamilton0d65a8c2019-06-07 00:46:02701 QuicPacketPrinter printer_;
[email protected]f702d572012-12-04 15:56:20702 std::vector<PacketToWrite> writes_;
Bence Béky6e243aa2019-12-13 19:01:07703 quic::test::NoopQpackStreamSenderDelegate noop_qpack_stream_sender_delegate_;
[email protected]f702d572012-12-04 15:56:20704};
705
David Schinazi09e9a6012019-10-03 17:37:57706INSTANTIATE_TEST_SUITE_P(VersionIncludeStreamDependencySequence,
707 QuicHttpStreamTest,
708 ::testing::ValuesIn(GetTestParams()),
709 ::testing::PrintToStringParamName());
[email protected]1e960032013-12-20 19:00:20710
711TEST_P(QuicHttpStreamTest, RenewStreamForAuth) {
[email protected]ed3fc15d2013-03-08 18:37:44712 Initialize();
rtennetibe635732014-10-02 22:51:42713 EXPECT_EQ(nullptr, stream_->RenewStreamForAuth());
[email protected]f702d572012-12-04 15:56:20714}
715
mmenkebd84c392015-09-02 14:12:34716TEST_P(QuicHttpStreamTest, CanReuseConnection) {
[email protected]ed3fc15d2013-03-08 18:37:44717 Initialize();
mmenkebd84c392015-09-02 14:12:34718 EXPECT_FALSE(stream_->CanReuseConnection());
[email protected]f702d572012-12-04 15:56:20719}
720
jri231c2972016-03-08 19:50:11721TEST_P(QuicHttpStreamTest, DisableConnectionMigrationForStream) {
Zhongyi Shibb28b1f2018-07-18 02:41:26722 request_.load_flags |= LOAD_DISABLE_CONNECTION_MIGRATION_TO_CELLULAR;
jri231c2972016-03-08 19:50:11723 Initialize();
xunjieli5fafe142016-03-23 23:32:54724 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27725 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:54726 net_log_.bound(), callback_.callback()));
rch08e198572017-05-09 16:56:55727 QuicChromiumClientStream::Handle* client_stream =
jri231c2972016-03-08 19:50:11728 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
Zhongyi Shibb28b1f2018-07-18 02:41:26729 EXPECT_FALSE(client_stream->can_migrate_to_cellular_network());
jri231c2972016-03-08 19:50:11730}
731
[email protected]1e960032013-12-20 19:00:20732TEST_P(QuicHttpStreamTest, GetRequest) {
733 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:45734 size_t spdy_request_header_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:23735 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:25736 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:23737 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:37738 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23739 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
740 kIncludeVersion, kFin, DEFAULT_PRIORITY,
741 &spdy_request_header_frame_length));
fayang3bcb8b502016-12-07 21:44:37742
[email protected]f702d572012-12-04 15:56:20743 Initialize();
744
745 request_.method = "GET";
rchcd379012017-04-12 21:53:32746 request_.url = GURL("https://www.example.org/");
[email protected]f702d572012-12-04 15:56:20747
xunjieli100937eb52016-09-15 20:09:37748 // Make sure getting load timing from the stream early does not crash.
749 LoadTimingInfo load_timing_info;
750 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
751
xunjieli5fafe142016-03-23 23:32:54752 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27753 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:54754 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:02755 EXPECT_EQ(OK,
756 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20757
758 // Ack the request.
Renjie90e808e2019-01-24 07:24:04759 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]f702d572012-12-04 15:56:20760
robpercival214763f2016-07-01 23:27:01761 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
762 IsError(ERR_IO_PENDING));
[email protected]f702d572012-12-04 15:56:20763
bnc614a92d32016-04-04 13:56:07764 SetResponse("404 Not Found", string());
sclittlec4dc1a32015-09-24 00:15:45765 size_t spdy_response_header_frame_length;
766 ProcessPacket(ConstructResponseHeadersPacket(
767 2, kFin, &spdy_response_header_frame_length));
[email protected]f702d572012-12-04 15:56:20768
769 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:01770 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]cadac622013-06-11 16:46:36771 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:20772 EXPECT_EQ(404, response_.headers->response_code());
773 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
[email protected]6ed67432014-06-24 01:53:53774 EXPECT_FALSE(response_.response_time.is_null());
775 EXPECT_FALSE(response_.request_time.is_null());
[email protected]f702d572012-12-04 15:56:20776
777 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:02778 EXPECT_EQ(0,
779 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
780 callback_.callback()));
[email protected]f702d572012-12-04 15:56:20781 EXPECT_TRUE(stream_->IsResponseBodyComplete());
782 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:10783
xunjieli100937eb52016-09-15 20:09:37784 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
xunjieli84adaab2016-09-20 01:12:28785 ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
xunjieli100937eb52016-09-15 20:09:37786
sclittle1edeeb22015-09-02 20:46:10787 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:45788 // headers and payload.
789 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
790 stream_->GetTotalSentBytes());
791 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length),
792 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:20793}
794
xunjieli100937eb52016-09-15 20:09:37795TEST_P(QuicHttpStreamTest, LoadTimingTwoRequests) {
796 SetRequest("GET", "/", DEFAULT_PRIORITY);
797 size_t spdy_request_header_frame_length;
798
Renjie Tangaadb84b2019-08-31 01:00:23799 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:25800 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:23801 AddWrite(ConstructInitialSettingsPacket(packet_number++));
xunjieli100937eb52016-09-15 20:09:37802 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23803 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
804 kIncludeVersion, kFin, DEFAULT_PRIORITY,
805 &spdy_request_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37806
807 // SetRequest() again for second request as |request_headers_| was moved.
808 SetRequest("GET", "/", DEFAULT_PRIORITY);
809 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23810 packet_number++, GetNthClientInitiatedBidirectionalStreamId(1),
811 kIncludeVersion, kFin, DEFAULT_PRIORITY,
812 GetNthClientInitiatedBidirectionalStreamId(0),
Ryan Hamilton0d65a8c2019-06-07 00:46:02813 &spdy_request_header_frame_length));
Renjie Tangcd594f32020-07-11 20:18:34814 AddWrite(
815 ConstructClientAckPacket(packet_number++, 3, 1)); // Ack the responses.
xunjieli100937eb52016-09-15 20:09:37816
817 Initialize();
818
819 request_.method = "GET";
rchcd379012017-04-12 21:53:32820 request_.url = GURL("https://www.example.org/");
xunjieli100937eb52016-09-15 20:09:37821 // Start first request.
822 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27823 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli100937eb52016-09-15 20:09:37824 net_log_.bound(), callback_.callback()));
825 EXPECT_EQ(OK,
826 stream_->SendRequest(headers_, &response_, callback_.callback()));
827
828 // Start a second request.
Ryan Hamilton6c2a2a82017-12-15 02:06:28829 QuicHttpStream stream2(
830 session_->CreateHandle(HostPortPair("www.example.org", 443)));
xunjieli100937eb52016-09-15 20:09:37831 TestCompletionCallback callback2;
832 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27833 stream2.InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli100937eb52016-09-15 20:09:37834 net_log_.bound(), callback2.callback()));
835 EXPECT_EQ(OK,
836 stream2.SendRequest(headers_, &response_, callback2.callback()));
837
838 // Ack both requests.
Renjie90e808e2019-01-24 07:24:04839 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
xunjieli100937eb52016-09-15 20:09:37840
841 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
842 IsError(ERR_IO_PENDING));
843 size_t spdy_response_header_frame_length;
844 SetResponse("200 OK", string());
845 ProcessPacket(InnerConstructResponseHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33846 2, GetNthClientInitiatedBidirectionalStreamId(0), kFin,
ckrasicbf2f59c2017-05-04 23:54:36847 &spdy_response_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37848
849 // Now that the headers have been processed, the callback will return.
850 EXPECT_THAT(callback_.WaitForResult(), IsOk());
851 EXPECT_EQ(200, response_.headers->response_code());
852
853 // There is no body, so this should return immediately.
854 EXPECT_EQ(0,
855 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
856 callback_.callback()));
857 EXPECT_TRUE(stream_->IsResponseBodyComplete());
858
859 LoadTimingInfo load_timing_info;
860 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
xunjieli84adaab2016-09-20 01:12:28861 ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
xunjieli100937eb52016-09-15 20:09:37862
863 // SetResponse() again for second request as |response_headers_| was moved.
864 SetResponse("200 OK", string());
865 EXPECT_THAT(stream2.ReadResponseHeaders(callback2.callback()),
866 IsError(ERR_IO_PENDING));
867
868 ProcessPacket(InnerConstructResponseHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33869 3, GetNthClientInitiatedBidirectionalStreamId(1), kFin,
ckrasicbf2f59c2017-05-04 23:54:36870 &spdy_response_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37871
872 EXPECT_THAT(callback2.WaitForResult(), IsOk());
873
874 // There is no body, so this should return immediately.
875 EXPECT_EQ(0,
876 stream2.ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
877 callback2.callback()));
878 EXPECT_TRUE(stream2.IsResponseBodyComplete());
879
880 LoadTimingInfo load_timing_info2;
881 EXPECT_TRUE(stream2.GetLoadTimingInfo(&load_timing_info2));
xunjieli84adaab2016-09-20 01:12:28882 ExpectLoadTimingValid(load_timing_info2, /*session_reused=*/true);
xunjieli100937eb52016-09-15 20:09:37883}
884
xunjieli34291fe12016-03-02 13:58:38885// QuicHttpStream does not currently support trailers. It should ignore
886// trailers upon receiving them.
887TEST_P(QuicHttpStreamTest, GetRequestWithTrailers) {
888 SetRequest("GET", "/", DEFAULT_PRIORITY);
889 size_t spdy_request_header_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:23890 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:25891 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:23892 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:37893 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23894 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
895 kIncludeVersion, kFin, DEFAULT_PRIORITY,
896 &spdy_request_header_frame_length));
Renjie Tangcd594f32020-07-11 20:18:34897 AddWrite(
898 ConstructClientAckPacket(packet_number++, 3, 1)); // Ack the data packet.
xunjieli34291fe12016-03-02 13:58:38899
900 Initialize();
901
902 request_.method = "GET";
rchcd379012017-04-12 21:53:32903 request_.url = GURL("https://www.example.org/");
xunjieli34291fe12016-03-02 13:58:38904
xunjieli5fafe142016-03-23 23:32:54905 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27906 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:54907 net_log_.bound(), callback_.callback()));
908
xunjieli34291fe12016-03-02 13:58:38909 EXPECT_EQ(OK,
910 stream_->SendRequest(headers_, &response_, callback_.callback()));
xunjieli34291fe12016-03-02 13:58:38911 // Ack the request.
Renjie90e808e2019-01-24 07:24:04912 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
xunjieli34291fe12016-03-02 13:58:38913
robpercival214763f2016-07-01 23:27:01914 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
915 IsError(ERR_IO_PENDING));
xunjieli34291fe12016-03-02 13:58:38916
bnc614a92d32016-04-04 13:56:07917 SetResponse("200 OK", string());
xunjieli34291fe12016-03-02 13:58:38918
919 // Send the response headers.
920 size_t spdy_response_header_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:02921 ProcessPacket(ConstructResponseHeadersPacket(
922 2, !kFin, &spdy_response_header_frame_length));
xunjieli34291fe12016-03-02 13:58:38923 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:01924 EXPECT_THAT(callback_.WaitForResult(), IsOk());
xunjieli34291fe12016-03-02 13:58:38925 ASSERT_TRUE(response_.headers.get());
926 EXPECT_EQ(200, response_.headers->response_code());
927 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
928 EXPECT_FALSE(response_.response_time.is_null());
929 EXPECT_FALSE(response_.request_time.is_null());
930
931 // Send the response body.
932 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:43933 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:17934 ProcessPacket(
935 ConstructServerDataPacket(3, false, !kFin, header + kResponseBody));
Ryan Hamilton0239aac2018-05-19 00:03:13936 spdy::SpdyHeaderBlock trailers;
xunjieli34291fe12016-03-02 13:58:38937 size_t spdy_trailers_frame_length;
938 trailers["foo"] = "bar";
Victor Vasiliev7da08172019-10-14 06:04:25939 if (!quic::VersionUsesHttp3(version_.transport_version)) {
Ryan Hamiltona1d1f4a2019-06-26 14:43:04940 trailers[quic::kFinalOffsetHeaderKey] =
941 base::NumberToString(strlen(kResponseBody) + header.length());
942 }
Ryan Hamilton0d65a8c2019-06-07 00:46:02943 ProcessPacket(ConstructResponseTrailersPacket(4, kFin, std::move(trailers),
944 &spdy_trailers_frame_length));
xunjieli34291fe12016-03-02 13:58:38945
946 // Make sure trailers are processed.
fdoray92e35a72016-06-10 15:54:55947 base::RunLoop().RunUntilIdle();
xunjieli34291fe12016-03-02 13:58:38948
949 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
950 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
951 callback_.callback()));
952 EXPECT_TRUE(stream_->IsResponseBodyComplete());
953
954 EXPECT_EQ(OK,
955 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
956 callback_.callback()));
957
958 EXPECT_TRUE(stream_->IsResponseBodyComplete());
959 EXPECT_TRUE(AtEof());
960
961 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
962 // headers and payload.
963 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
964 stream_->GetTotalSentBytes());
Renjief49758b2019-01-11 23:32:41965 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length +
966 strlen(kResponseBody) + header.length() +
967 +spdy_trailers_frame_length),
968 stream_->GetTotalReceivedBytes());
xunjieli5fafe142016-03-23 23:32:54969 // Check that NetLog was filled as expected.
Eric Roman79cc7552019-07-19 02:17:54970 auto entries = net_log_.GetEntries();
xunjieli5fafe142016-03-23 23:32:54971 size_t pos = ExpectLogContainsSomewhere(
972 entries, /*min_offset=*/0,
mikecirone8b85c432016-09-08 19:11:00973 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
974 NetLogEventPhase::NONE);
xunjieli5fafe142016-03-23 23:32:54975 pos = ExpectLogContainsSomewhere(
976 entries, /*min_offset=*/pos,
mikecirone8b85c432016-09-08 19:11:00977 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
978 NetLogEventPhase::NONE);
xunjieli5fafe142016-03-23 23:32:54979 ExpectLogContainsSomewhere(
980 entries, /*min_offset=*/pos,
mikecirone8b85c432016-09-08 19:11:00981 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
982 NetLogEventPhase::NONE);
xunjieli34291fe12016-03-02 13:58:38983}
984
Bence Béky6c2c78f2020-08-28 16:49:06985TEST_P(QuicHttpStreamTest, ElideHeadersInNetLog) {
986 Initialize();
987
988 // QuicHttp3Logger is only used with HTTP/3.
989 if (!VersionUsesHttp3(version_.transport_version)) {
990 return;
991 }
992
993 net_log_.SetObserverCaptureMode(NetLogCaptureMode::kDefault);
994
Bence Békye0d3747d2020-08-28 23:16:40995 // Send first request.
Bence Béky6c2c78f2020-08-28 16:49:06996 SetRequest("GET", "/", DEFAULT_PRIORITY);
997 request_.method = "GET";
998 request_.url = GURL("https://www.example.org/");
999 headers_.SetHeader(HttpRequestHeaders::kCookie, "secret");
1000
1001 size_t spdy_request_header_frame_length;
Bence Békye0d3747d2020-08-28 23:16:401002 int outgoing_packet_number = 1;
1003 AddWrite(ConstructInitialSettingsPacket(outgoing_packet_number++));
Bence Béky6c2c78f2020-08-28 16:49:061004 AddWrite(InnerConstructRequestHeadersPacket(
Bence Békye0d3747d2020-08-28 23:16:401005 outgoing_packet_number++, stream_id_, kIncludeVersion, kFin,
1006 DEFAULT_PRIORITY, &spdy_request_header_frame_length));
Bence Béky6c2c78f2020-08-28 16:49:061007
1008 EXPECT_THAT(stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
1009 net_log_.bound(), callback_.callback()),
1010 IsOk());
1011 EXPECT_THAT(stream_->SendRequest(headers_, &response_, callback_.callback()),
1012 IsOk());
Bence Békye0d3747d2020-08-28 23:16:401013 int incoming_packet_number = 1;
1014 ProcessPacket(ConstructServerAckPacket(incoming_packet_number++, 1, 1,
1015 1)); // Ack the request.
Bence Béky6c2c78f2020-08-28 16:49:061016
Bence Békye0d3747d2020-08-28 23:16:401017 // Process first response.
Bence Béky6c2c78f2020-08-28 16:49:061018 SetResponse("200 OK", string());
1019 response_headers_["set-cookie"] = "secret";
1020 size_t spdy_response_header_frame_length;
1021 ProcessPacket(ConstructResponseHeadersPacket(
Bence Békye0d3747d2020-08-28 23:16:401022 incoming_packet_number++, kFin, &spdy_response_header_frame_length));
Bence Béky6c2c78f2020-08-28 16:49:061023 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
Bence Béky6c2c78f2020-08-28 16:49:061024
1025 ASSERT_TRUE(response_.headers.get());
1026 EXPECT_EQ(200, response_.headers->response_code());
1027 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1028 EXPECT_TRUE(response_.headers->HasHeaderValue("set-cookie", "secret"));
1029
Bence Békye0d3747d2020-08-28 23:16:401030 net_log_.SetObserverCaptureMode(NetLogCaptureMode::kIncludeSensitive);
Bence Béky6c2c78f2020-08-28 16:49:061031
Bence Békye0d3747d2020-08-28 23:16:401032 // Send second request.
1033 quic::QuicStreamId stream_id = GetNthClientInitiatedBidirectionalStreamId(1);
1034 request_.url = GURL("https://www.example.org/foo");
Bence Béky6c2c78f2020-08-28 16:49:061035
Bence Békye0d3747d2020-08-28 23:16:401036 AddWrite(InnerConstructRequestHeadersPacket(
1037 outgoing_packet_number++, stream_id, kIncludeVersion, kFin,
1038 DEFAULT_PRIORITY, &spdy_request_header_frame_length));
Bence Béky6c2c78f2020-08-28 16:49:061039
Bence Békye0d3747d2020-08-28 23:16:401040 auto stream = std::make_unique<QuicHttpStream>(
1041 session_->CreateHandle(HostPortPair("www.example.org/foo", 443)));
1042 EXPECT_THAT(stream->InitializeStream(&request_, true, DEFAULT_PRIORITY,
1043 net_log_.bound(), callback_.callback()),
1044 IsOk());
1045 EXPECT_THAT(stream->SendRequest(headers_, &response_, callback_.callback()),
1046 IsOk());
1047 ProcessPacket(ConstructServerAckPacket(incoming_packet_number++, 1, 1,
1048 1)); // Ack the request.
Bence Béky6c2c78f2020-08-28 16:49:061049
Bence Békye0d3747d2020-08-28 23:16:401050 // Process second response.
1051 SetResponse("200 OK", string());
1052 response_headers_["set-cookie"] = "secret";
1053 ProcessPacket(InnerConstructResponseHeadersPacket(
1054 incoming_packet_number++, stream_id, kFin,
1055 &spdy_response_header_frame_length));
1056 EXPECT_THAT(stream->ReadResponseHeaders(callback_.callback()), IsOk());
Bence Béky6c2c78f2020-08-28 16:49:061057
Bence Békye0d3747d2020-08-28 23:16:401058 ASSERT_TRUE(response_.headers.get());
1059 EXPECT_EQ(200, response_.headers->response_code());
1060 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1061 EXPECT_TRUE(response_.headers->HasHeaderValue("set-cookie", "secret"));
1062
1063 EXPECT_TRUE(AtEof());
1064
1065 // Check that sensitive header value were stripped
1066 // for the first transaction (logged with NetLogCaptureMode::kDefault)
1067 // but not for the second (logged with NetLogCaptureMode::kIncludeSensitive).
1068 auto entries =
1069 net_log_.GetEntriesWithType(NetLogEventType::HTTP3_HEADERS_SENT);
1070 ASSERT_EQ(2u, entries.size());
1071 EXPECT_TRUE(
1072 CheckHeader(entries[0].params, "cookie", "[6 bytes were stripped]"));
1073 EXPECT_TRUE(CheckHeader(entries[1].params, "cookie", "secret"));
1074
1075 entries = net_log_.GetEntriesWithType(NetLogEventType::HTTP3_HEADERS_DECODED);
1076 ASSERT_EQ(2u, entries.size());
1077 EXPECT_TRUE(
1078 CheckHeader(entries[0].params, "set-cookie", "[6 bytes were stripped]"));
1079 EXPECT_TRUE(CheckHeader(entries[1].params, "set-cookie", "secret"));
Bence Béky6c2c78f2020-08-28 16:49:061080}
1081
[email protected]3e7dca62013-09-10 16:14:231082// Regression test for http://crbug.com/288128
[email protected]1e960032013-12-20 19:00:201083TEST_P(QuicHttpStreamTest, GetRequestLargeResponse) {
1084 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451085 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231086 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251087 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231088 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371089 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231090 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1091 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1092 &spdy_request_headers_frame_length));
[email protected]3e7dca62013-09-10 16:14:231093 Initialize();
1094
1095 request_.method = "GET";
rchcd379012017-04-12 21:53:321096 request_.url = GURL("https://www.example.org/");
[email protected]3e7dca62013-09-10 16:14:231097
xunjieli5fafe142016-03-23 23:32:541098 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271099 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541100 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021101 EXPECT_EQ(OK,
1102 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:231103
1104 // Ack the request.
Renjie90e808e2019-01-24 07:24:041105 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]3e7dca62013-09-10 16:14:231106
robpercival214763f2016-07-01 23:27:011107 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1108 IsError(ERR_IO_PENDING));
[email protected]3e7dca62013-09-10 16:14:231109
bnc086b39e12016-06-24 13:05:261110 response_headers_[":status"] = "200 OK";
1111 response_headers_[":version"] = "HTTP/1.1";
1112 response_headers_["content-type"] = "text/plain";
1113 response_headers_["big6"] = string(1000, 'x'); // Lots of x's.
[email protected]3e7dca62013-09-10 16:14:231114
sclittlec4dc1a32015-09-24 00:15:451115 size_t spdy_response_headers_frame_length;
1116 ProcessPacket(ConstructResponseHeadersPacket(
1117 2, kFin, &spdy_response_headers_frame_length));
[email protected]3e7dca62013-09-10 16:14:231118
1119 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:011120 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]3e7dca62013-09-10 16:14:231121 ASSERT_TRUE(response_.headers.get());
1122 EXPECT_EQ(200, response_.headers->response_code());
1123 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1124
1125 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:021126 EXPECT_EQ(0,
1127 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1128 callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:231129 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1130 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101131
1132 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451133 // headers and payload.
1134 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1135 stream_->GetTotalSentBytes());
1136 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length),
1137 stream_->GetTotalReceivedBytes());
[email protected]3e7dca62013-09-10 16:14:231138}
1139
rchf9f103cbc2014-08-30 05:28:041140// Regression test for http://crbug.com/409101
1141TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendRequest) {
1142 SetRequest("GET", "/", DEFAULT_PRIORITY);
1143 Initialize();
1144
1145 request_.method = "GET";
rchcd379012017-04-12 21:53:321146 request_.url = GURL("https://www.example.org/");
rchf9f103cbc2014-08-30 05:28:041147
xunjieli5fafe142016-03-23 23:32:541148 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271149 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541150 net_log_.bound(), callback_.callback()));
rchf9f103cbc2014-08-30 05:28:041151
jri78ec06a2016-03-31 18:19:401152 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521153 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rchf9f103cbc2014-08-30 05:28:041154
1155 EXPECT_EQ(ERR_CONNECTION_CLOSED,
rjshaded5ced072015-12-18 19:26:021156 stream_->SendRequest(headers_, &response_, callback_.callback()));
sclittle1edeeb22015-09-02 20:46:101157
1158 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1159 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rchf9f103cbc2014-08-30 05:28:041160}
1161
rch03b7a202016-02-05 00:54:201162// Regression test for http://crbug.com/584441
1163TEST_P(QuicHttpStreamTest, GetSSLInfoAfterSessionClosed) {
1164 SetRequest("GET", "/", DEFAULT_PRIORITY);
1165 Initialize();
1166
1167 request_.method = "GET";
rchcd379012017-04-12 21:53:321168 request_.url = GURL("https://www.example.org/");
rch03b7a202016-02-05 00:54:201169
xunjieli5fafe142016-03-23 23:32:541170 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271171 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541172 net_log_.bound(), callback_.callback()));
rch03b7a202016-02-05 00:54:201173
1174 SSLInfo ssl_info;
rch11565e02016-02-09 20:13:471175 EXPECT_FALSE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:201176 stream_->GetSSLInfo(&ssl_info);
rch11565e02016-02-09 20:13:471177 EXPECT_TRUE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:201178
jri78ec06a2016-03-31 18:19:401179 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521180 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rch03b7a202016-02-05 00:54:201181
rch11565e02016-02-09 20:13:471182 SSLInfo ssl_info2;
1183 stream_->GetSSLInfo(&ssl_info2);
1184 EXPECT_TRUE(ssl_info2.is_valid());
rch03b7a202016-02-05 00:54:201185}
1186
rchcd379012017-04-12 21:53:321187TEST_P(QuicHttpStreamTest, GetAlternativeService) {
1188 SetRequest("GET", "/", DEFAULT_PRIORITY);
1189 Initialize();
1190
1191 request_.method = "GET";
1192 request_.url = GURL("https://www.example.org/");
1193
1194 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271195 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
rchcd379012017-04-12 21:53:321196 net_log_.bound(), callback_.callback()));
1197
1198 AlternativeService alternative_service;
1199 EXPECT_TRUE(stream_->GetAlternativeService(&alternative_service));
1200 EXPECT_EQ(AlternativeService(kProtoQUIC, "www.example.org", 443),
1201 alternative_service);
1202
1203 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521204 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rchcd379012017-04-12 21:53:321205
1206 AlternativeService alternative_service2;
1207 EXPECT_TRUE(stream_->GetAlternativeService(&alternative_service2));
1208 EXPECT_EQ(AlternativeService(kProtoQUIC, "www.example.org", 443),
1209 alternative_service2);
1210}
1211
zhongyica364fbb2015-12-12 03:39:121212TEST_P(QuicHttpStreamTest, LogGranularQuicConnectionError) {
1213 SetRequest("GET", "/", DEFAULT_PRIORITY);
1214 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231215 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251216 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231217 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371218 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231219 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1220 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1221 &spdy_request_headers_frame_length));
fayang3bcb8b502016-12-07 21:44:371222 AddWrite(ConstructAckAndRstStreamPacket(3));
zhongyica364fbb2015-12-12 03:39:121223 Initialize();
1224
1225 request_.method = "GET";
rchcd379012017-04-12 21:53:321226 request_.url = GURL("https://www.example.org/");
zhongyica364fbb2015-12-12 03:39:121227
xunjieli5fafe142016-03-23 23:32:541228 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271229 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541230 net_log_.bound(), callback_.callback()));
zhongyica364fbb2015-12-12 03:39:121231 EXPECT_EQ(OK,
1232 stream_->SendRequest(headers_, &response_, callback_.callback()));
1233
1234 // Ack the request.
Renjie90e808e2019-01-24 07:24:041235 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011236 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1237 IsError(ERR_IO_PENDING));
zhongyica364fbb2015-12-12 03:39:121238
Ryan Hamilton8d9ee76e2018-05-29 23:52:521239 quic::QuicConnectionCloseFrame frame;
Zhongyi Shica576df2019-04-12 17:43:401240 frame.quic_error_code = quic::QUIC_PEER_GOING_AWAY;
rch1c5b74a2016-06-23 22:10:551241 session_->connection()->OnConnectionCloseFrame(frame);
zhongyica364fbb2015-12-12 03:39:121242
1243 NetErrorDetails details;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521244 EXPECT_EQ(quic::QUIC_NO_ERROR, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121245 stream_->PopulateNetErrorDetails(&details);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521246 EXPECT_EQ(quic::QUIC_PEER_GOING_AWAY, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121247}
1248
Ryan Hamiltone316e482017-08-17 02:48:531249TEST_P(QuicHttpStreamTest, LogGranularQuicErrorIfHandshakeNotConfirmed) {
rch617e0652017-04-26 17:57:511250 // By default the test setup defaults handshake to be confirmed. Manually set
1251 // it to be not confirmed.
rch617e0652017-04-26 17:57:511252 crypto_client_stream_factory_.set_handshake_mode(
Ryan Hamilton9835e662018-08-02 05:36:271253 MockCryptoClientStream::ZERO_RTT);
rch617e0652017-04-26 17:57:511254
zhongyica364fbb2015-12-12 03:39:121255 SetRequest("GET", "/", DEFAULT_PRIORITY);
1256 size_t spdy_request_headers_frame_length;
Michael Warres167db3e2019-03-01 21:38:031257 client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
Nick Harper057264a82019-09-12 23:33:491258 client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
1259 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251260 if (VersionUsesHttp3(version_.transport_version))
Nick Harper057264a82019-09-12 23:33:491261 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371262 AddWrite(InnerConstructRequestHeadersPacket(
Nick Harper057264a82019-09-12 23:33:491263 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1264 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1265 &spdy_request_headers_frame_length));
zhongyica364fbb2015-12-12 03:39:121266 Initialize();
1267
1268 request_.method = "GET";
rchcd379012017-04-12 21:53:321269 request_.url = GURL("https://www.example.org/");
zhongyica364fbb2015-12-12 03:39:121270
xunjieli5fafe142016-03-23 23:32:541271 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271272 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541273 net_log_.bound(), callback_.callback()));
zhongyica364fbb2015-12-12 03:39:121274 EXPECT_EQ(OK,
1275 stream_->SendRequest(headers_, &response_, callback_.callback()));
1276
1277 // Ack the request.
Renjie90e808e2019-01-24 07:24:041278 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011279 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1280 IsError(ERR_IO_PENDING));
zhongyica364fbb2015-12-12 03:39:121281
Ryan Hamilton8d9ee76e2018-05-29 23:52:521282 quic::QuicConnectionCloseFrame frame;
Zhongyi Shica576df2019-04-12 17:43:401283 frame.quic_error_code = quic::QUIC_PEER_GOING_AWAY;
rch1c5b74a2016-06-23 22:10:551284 session_->connection()->OnConnectionCloseFrame(frame);
zhongyica364fbb2015-12-12 03:39:121285
1286 NetErrorDetails details;
zhongyica364fbb2015-12-12 03:39:121287 stream_->PopulateNetErrorDetails(&details);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521288 EXPECT_EQ(quic::QUIC_PEER_GOING_AWAY, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121289}
1290
rch11a114a2014-09-04 23:41:591291// Regression test for http://crbug.com/409871
1292TEST_P(QuicHttpStreamTest, SessionClosedBeforeReadResponseHeaders) {
1293 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451294 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231295 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251296 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231297 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371298 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231299 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1300 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1301 &spdy_request_headers_frame_length));
rch11a114a2014-09-04 23:41:591302 Initialize();
1303
1304 request_.method = "GET";
rchcd379012017-04-12 21:53:321305 request_.url = GURL("https://www.example.org/");
rch11a114a2014-09-04 23:41:591306
xunjieli5fafe142016-03-23 23:32:541307 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271308 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541309 net_log_.bound(), callback_.callback()));
rch11a114a2014-09-04 23:41:591310
rjshaded5ced072015-12-18 19:26:021311 EXPECT_EQ(OK,
1312 stream_->SendRequest(headers_, &response_, callback_.callback()));
rch11a114a2014-09-04 23:41:591313
jri78ec06a2016-03-31 18:19:401314 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521315 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rch11a114a2014-09-04 23:41:591316
1317 EXPECT_NE(OK, stream_->ReadResponseHeaders(callback_.callback()));
sclittle1edeeb22015-09-02 20:46:101318
1319 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451320 // headers and payload.
1321 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1322 stream_->GetTotalSentBytes());
sclittle1edeeb22015-09-02 20:46:101323 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rch11a114a2014-09-04 23:41:591324}
1325
[email protected]1e960032013-12-20 19:00:201326TEST_P(QuicHttpStreamTest, SendPostRequest) {
1327 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451328 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231329 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251330 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231331 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Yixin Wange7ecc472018-03-06 19:00:251332
Victor Vasiliev076657c2019-03-12 02:46:431333 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:321334 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411335 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231336 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1337 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1338 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411339 } else {
1340 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231341 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1342 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1343 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411344 }
Yixin Wange7ecc472018-03-06 19:00:251345
Renjie Tangcd594f32020-07-11 20:18:341346 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]f702d572012-12-04 15:56:201347
1348 Initialize();
1349
danakjad1777e2016-04-16 00:56:421350 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:191351 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
ricea2deef682016-09-09 08:04:071352 kUploadData, strlen(kUploadData)));
rch97827ee2017-05-24 23:49:121353 upload_data_stream_ =
Jeremy Roman0579ed62017-08-29 15:56:191354 std::make_unique<ElementsUploadDataStream>(std::move(element_readers), 0);
[email protected]f702d572012-12-04 15:56:201355 request_.method = "POST";
rchcd379012017-04-12 21:53:321356 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121357 request_.upload_data_stream = upload_data_stream_.get();
Bence Békyd8a21fc32018-06-27 18:29:581358 ASSERT_THAT(request_.upload_data_stream->Init(CompletionOnceCallback(),
tfarina42834112016-09-22 13:38:201359 NetLogWithSource()),
1360 IsOk());
[email protected]f702d572012-12-04 15:56:201361
xunjieli5fafe142016-03-23 23:32:541362 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271363 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541364 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021365 EXPECT_EQ(OK,
1366 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:201367
1368 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041369 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]f702d572012-12-04 15:56:201370
1371 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071372 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451373 size_t spdy_response_headers_frame_length;
1374 ProcessPacket(ConstructResponseHeadersPacket(
1375 2, !kFin, &spdy_response_headers_frame_length));
[email protected]f702d572012-12-04 15:56:201376
rchfb47f712017-05-21 03:24:001377 // The headers have already arrived.
1378 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]cadac622013-06-11 16:46:361379 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:201380 EXPECT_EQ(200, response_.headers->response_code());
1381 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1382
1383 // Send the response body.
1384 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431385 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:411386 ProcessPacket(
Ryan Hamilton7505eb92019-06-08 00:22:171387 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
[email protected]f702d572012-12-04 15:56:201388 // Since the body has already arrived, this should return immediately.
1389 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
1390 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1391 callback_.callback()));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291392 EXPECT_EQ(0,
1393 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1394 callback_.callback()));
1395
1396 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1397 EXPECT_TRUE(AtEof());
1398
1399 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
1400 // headers and payload.
1401 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411402 strlen(kUploadData) + header.length()),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291403 stream_->GetTotalSentBytes());
1404 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411405 strlen(kResponseBody) + header2.length()),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291406 stream_->GetTotalReceivedBytes());
1407}
1408
1409TEST_P(QuicHttpStreamTest, SendPostRequestAndReceiveSoloFin) {
1410 SetRequest("POST", "/", DEFAULT_PRIORITY);
1411 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231412 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251413 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231414 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431415 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:321416 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411417 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231418 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1419 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1420 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411421 } else {
1422 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231423 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1424 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1425 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411426 }
1427
Renjie Tangcd594f32020-07-11 20:18:341428 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291429
1430 Initialize();
1431
1432 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:191433 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
Ryan Hamilton2ef0a9c2017-07-25 03:18:291434 kUploadData, strlen(kUploadData)));
1435 upload_data_stream_ =
Jeremy Roman0579ed62017-08-29 15:56:191436 std::make_unique<ElementsUploadDataStream>(std::move(element_readers), 0);
Ryan Hamilton2ef0a9c2017-07-25 03:18:291437 request_.method = "POST";
1438 request_.url = GURL("https://www.example.org/");
1439 request_.upload_data_stream = upload_data_stream_.get();
Bence Békyd8a21fc32018-06-27 18:29:581440 ASSERT_THAT(request_.upload_data_stream->Init(CompletionOnceCallback(),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291441 NetLogWithSource()),
1442 IsOk());
1443
1444 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271445 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
Ryan Hamilton2ef0a9c2017-07-25 03:18:291446 net_log_.bound(), callback_.callback()));
1447 EXPECT_EQ(OK,
1448 stream_->SendRequest(headers_, &response_, callback_.callback()));
1449
1450 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041451 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291452
1453 // Send the response headers (but not the body).
1454 SetResponse("200 OK", string());
1455 size_t spdy_response_headers_frame_length;
1456 ProcessPacket(ConstructResponseHeadersPacket(
1457 2, !kFin, &spdy_response_headers_frame_length));
1458
1459 // The headers have already arrived.
1460 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
1461 ASSERT_TRUE(response_.headers.get());
1462 EXPECT_EQ(200, response_.headers->response_code());
1463 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1464
1465 // Send the response body.
1466 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431467 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:411468 ProcessPacket(
Ryan Hamilton7505eb92019-06-08 00:22:171469 ConstructServerDataPacket(3, false, !kFin, header2 + kResponseBody));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291470 // Since the body has already arrived, this should return immediately.
1471 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
1472 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1473 callback_.callback()));
Ryan Hamilton7505eb92019-06-08 00:22:171474 ProcessPacket(ConstructServerDataPacket(4, false, kFin, ""));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291475 EXPECT_EQ(0,
1476 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1477 callback_.callback()));
[email protected]f702d572012-12-04 15:56:201478
1479 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1480 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101481
1482 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451483 // headers and payload.
1484 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411485 strlen(kUploadData) + header.length()),
sclittle1edeeb22015-09-02 20:46:101486 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451487 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411488 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101489 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:201490}
1491
[email protected]1e960032013-12-20 19:00:201492TEST_P(QuicHttpStreamTest, SendChunkedPostRequest) {
1493 SetRequest("POST", "/", DEFAULT_PRIORITY);
[email protected]c9e49a02013-02-26 05:56:471494 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:451495 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231496 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251497 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231498 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431499 std::string header = ConstructDataHeader(chunk_size);
Nick Harperc6cb7a612020-02-24 20:03:321500 if (version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411501 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231502 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1503 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1504 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjie Tangd5133972019-12-06 00:20:281505 AddWrite(ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin,
1506 {header + kUploadData}));
Renjief49758b2019-01-11 23:32:411507 } else {
1508 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231509 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1510 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1511 &spdy_request_headers_frame_length, {kUploadData}));
1512 AddWrite(ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin,
1513 kUploadData));
Renjief49758b2019-01-11 23:32:411514 }
1515
Renjie Tangcd594f32020-07-11 20:18:341516 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]c9e49a02013-02-26 05:56:471517 Initialize();
1518
Jeremy Roman0579ed62017-08-29 15:56:191519 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121520 auto* chunked_upload_stream =
1521 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1522 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
[email protected]c9e49a02013-02-26 05:56:471523
1524 request_.method = "POST";
rchcd379012017-04-12 21:53:321525 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121526 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071527 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201528 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]c9e49a02013-02-26 05:56:471529
xunjieli5fafe142016-03-23 23:32:541530 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271531 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541532 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021533 ASSERT_EQ(ERR_IO_PENDING,
1534 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]c9e49a02013-02-26 05:56:471535
rch97827ee2017-05-24 23:49:121536 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
robpercival214763f2016-07-01 23:27:011537 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]c9e49a02013-02-26 05:56:471538
1539 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041540 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]c9e49a02013-02-26 05:56:471541
1542 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071543 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451544 size_t spdy_response_headers_frame_length;
1545 ProcessPacket(ConstructResponseHeadersPacket(
1546 2, !kFin, &spdy_response_headers_frame_length));
[email protected]c9e49a02013-02-26 05:56:471547
rchfb47f712017-05-21 03:24:001548 // The headers have already arrived.
1549 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]cadac622013-06-11 16:46:361550 ASSERT_TRUE(response_.headers.get());
[email protected]c9e49a02013-02-26 05:56:471551 EXPECT_EQ(200, response_.headers->response_code());
1552 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1553
1554 // Send the response body.
1555 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431556 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171557 ProcessPacket(
1558 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
[email protected]c9e49a02013-02-26 05:56:471559
1560 // Since the body has already arrived, this should return immediately.
1561 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1562 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1563 callback_.callback()));
1564
1565 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1566 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101567
1568 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451569 // headers and payload.
1570 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411571 strlen(kUploadData) * 2 + header.length() * 2),
sclittle1edeeb22015-09-02 20:46:101572 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451573 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411574 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101575 stream_->GetTotalReceivedBytes());
[email protected]c9e49a02013-02-26 05:56:471576}
1577
[email protected]16ba7742014-08-22 00:57:251578TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithFinalEmptyDataPacket) {
1579 SetRequest("POST", "/", DEFAULT_PRIORITY);
1580 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:451581 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231582 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251583 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231584 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431585 std::string header = ConstructDataHeader(chunk_size);
Renjief49758b2019-01-11 23:32:411586
Nick Harperc6cb7a612020-02-24 20:03:321587 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411588 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231589 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1590 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1591 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411592 } else {
1593 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231594 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1595 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1596 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411597 }
Renjie Tangaadb84b2019-08-31 01:00:231598 AddWrite(
1599 ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin, ""));
Renjie Tangcd594f32020-07-11 20:18:341600 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]16ba7742014-08-22 00:57:251601 Initialize();
1602
Jeremy Roman0579ed62017-08-29 15:56:191603 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121604 auto* chunked_upload_stream =
1605 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1606 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
[email protected]16ba7742014-08-22 00:57:251607
1608 request_.method = "POST";
rchcd379012017-04-12 21:53:321609 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121610 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071611 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201612 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]16ba7742014-08-22 00:57:251613
xunjieli5fafe142016-03-23 23:32:541614 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271615 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541616 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021617 ASSERT_EQ(ERR_IO_PENDING,
1618 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251619
rch97827ee2017-05-24 23:49:121620 chunked_upload_stream->AppendData(nullptr, 0, true);
robpercival214763f2016-07-01 23:27:011621 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]16ba7742014-08-22 00:57:251622
Renjie90e808e2019-01-24 07:24:041623 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]16ba7742014-08-22 00:57:251624
1625 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071626 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451627 size_t spdy_response_headers_frame_length;
1628 ProcessPacket(ConstructResponseHeadersPacket(
1629 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251630
rchfb47f712017-05-21 03:24:001631 // The headers have already arrived.
1632 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]16ba7742014-08-22 00:57:251633 ASSERT_TRUE(response_.headers.get());
1634 EXPECT_EQ(200, response_.headers->response_code());
1635 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1636
1637 // Send the response body.
1638 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431639 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171640 ProcessPacket(
1641 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
[email protected]16ba7742014-08-22 00:57:251642
rchb27683c2015-07-29 23:53:501643 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251644 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1645 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1646 callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251647 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1648 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101649
1650 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451651 // headers and payload.
1652 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411653 strlen(kUploadData) + header.length()),
sclittle1edeeb22015-09-02 20:46:101654 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451655 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411656 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101657 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251658}
1659
1660TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithOneEmptyDataPacket) {
1661 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451662 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231663 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251664 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231665 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371666 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231667 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1668 kIncludeVersion, !kFin, DEFAULT_PRIORITY,
1669 &spdy_request_headers_frame_length));
1670 AddWrite(
1671 ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin, ""));
Renjie Tangcd594f32020-07-11 20:18:341672 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]16ba7742014-08-22 00:57:251673 Initialize();
1674
Jeremy Roman0579ed62017-08-29 15:56:191675 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121676 auto* chunked_upload_stream =
1677 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
[email protected]16ba7742014-08-22 00:57:251678
1679 request_.method = "POST";
rchcd379012017-04-12 21:53:321680 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121681 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071682 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201683 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]16ba7742014-08-22 00:57:251684
xunjieli5fafe142016-03-23 23:32:541685 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271686 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541687 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021688 ASSERT_EQ(ERR_IO_PENDING,
1689 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251690
rch97827ee2017-05-24 23:49:121691 chunked_upload_stream->AppendData(nullptr, 0, true);
robpercival214763f2016-07-01 23:27:011692 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]16ba7742014-08-22 00:57:251693
Renjie90e808e2019-01-24 07:24:041694 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]16ba7742014-08-22 00:57:251695
1696 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071697 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451698 size_t spdy_response_headers_frame_length;
1699 ProcessPacket(ConstructResponseHeadersPacket(
1700 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251701
rchfb47f712017-05-21 03:24:001702 // The headers have already arrived.
1703 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]16ba7742014-08-22 00:57:251704 ASSERT_TRUE(response_.headers.get());
1705 EXPECT_EQ(200, response_.headers->response_code());
1706 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1707
1708 // Send the response body.
1709 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431710 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171711 ProcessPacket(
1712 ConstructServerDataPacket(3, false, kFin, header + kResponseBody));
[email protected]16ba7742014-08-22 00:57:251713
rchb27683c2015-07-29 23:53:501714 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251715 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1716 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1717 callback_.callback()));
1718
1719 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1720 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101721
1722 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451723 // headers and payload.
1724 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1725 stream_->GetTotalSentBytes());
1726 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411727 strlen(kResponseBody) + header.length()),
sclittle1edeeb22015-09-02 20:46:101728 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251729}
1730
Bence Békye3c6f122020-05-08 01:09:471731TEST_P(QuicHttpStreamTest, SendChunkedPostRequestAbortedByResetStream) {
1732 SetRequest("POST", "/", DEFAULT_PRIORITY);
1733 size_t chunk_size = strlen(kUploadData);
1734 size_t spdy_request_headers_frame_length;
1735 int packet_number = 1;
1736
1737 if (version_.UsesHttp3()) {
1738 AddWrite(ConstructInitialSettingsPacket(packet_number++));
1739 }
1740
1741 std::string header = ConstructDataHeader(chunk_size);
1742 if (version_.HasIetfQuicFrames()) {
1743 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1744 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1745 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1746 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjie Tangcd594f32020-07-11 20:18:341747 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
1748 AddWrite(client_maker_.MakeAckAndRstPacket(
1749 packet_number++,
1750 /* include_version = */ true, stream_id_, quic::QUIC_STREAM_NO_ERROR, 4,
1751 1,
1752 /* include_stop_sending_if_v99 = */ false));
Bence Békye3c6f122020-05-08 01:09:471753 } else {
1754 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1755 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1756 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1757 &spdy_request_headers_frame_length, {kUploadData}));
Renjie Tangcd594f32020-07-11 20:18:341758 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
Bence Békye3c6f122020-05-08 01:09:471759 AddWrite(client_maker_.MakeAckAndRstPacket(
1760 packet_number++,
1761 /* include_version = */ false, stream_id_,
Renjie Tangcd594f32020-07-11 20:18:341762 quic::QUIC_RST_ACKNOWLEDGEMENT, 4, 1,
Bence Békye3c6f122020-05-08 01:09:471763 /* include_stop_sending_if_v99 = */ false));
1764 }
1765
1766 Initialize();
1767
1768 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
1769 auto* chunked_upload_stream =
1770 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1771 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
1772
1773 request_.method = "POST";
1774 request_.url = GURL("https://www.example.org/");
1775 request_.upload_data_stream = upload_data_stream_.get();
1776 ASSERT_THAT(request_.upload_data_stream->Init(
1777 TestCompletionCallback().callback(), NetLogWithSource()),
1778 IsOk());
1779 ASSERT_THAT(stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1780 net_log_.bound(), callback_.callback()),
1781 IsOk());
1782 ASSERT_THAT(stream_->SendRequest(headers_, &response_, callback_.callback()),
1783 IsError(ERR_IO_PENDING));
1784
1785 // Ack both packets in the request.
1786 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
1787
1788 // Send the response headers (but not the body).
1789 SetResponse("200 OK", string());
1790 size_t spdy_response_headers_frame_length;
1791 ProcessPacket(ConstructResponseHeadersPacket(
1792 2, !kFin, &spdy_response_headers_frame_length));
1793
1794 // Send the response body.
1795 const char kResponseBody[] = "Hello world!";
1796 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
1797 ProcessPacket(
1798 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
1799
1800 // Server resets stream with H3_NO_ERROR before request body is complete.
1801 ProcessPacket(server_maker_.MakeRstPacket(4, /* include_version = */ false,
1802 stream_id_,
1803 quic::QUIC_STREAM_NO_ERROR));
1804
1805 // Finish feeding request body to QuicHttpStream. Data will be discarded.
1806 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1807 EXPECT_THAT(callback_.WaitForResult(), IsOk());
1808
1809 // Verify response.
1810 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
1811 ASSERT_TRUE(response_.headers.get());
1812 EXPECT_EQ(200, response_.headers->response_code());
1813 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1814 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1815 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1816 callback_.callback()));
1817 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1818 EXPECT_TRUE(AtEof());
1819
1820 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
1821 // headers and payload.
1822 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
1823 strlen(kUploadData) + header.length()),
1824 stream_->GetTotalSentBytes());
1825 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1826 strlen(kResponseBody) + header2.length()),
1827 stream_->GetTotalReceivedBytes());
1828}
1829
[email protected]1e960032013-12-20 19:00:201830TEST_P(QuicHttpStreamTest, DestroyedEarly) {
1831 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451832 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231833 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251834 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231835 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371836 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231837 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1838 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1839 &spdy_request_headers_frame_length));
1840 AddWrite(ConstructAckAndRstStreamPacket(packet_number++));
[email protected]63534512012-12-23 18:49:001841 Initialize();
1842
1843 request_.method = "GET";
rchcd379012017-04-12 21:53:321844 request_.url = GURL("https://www.example.org/");
[email protected]63534512012-12-23 18:49:001845
xunjieli5fafe142016-03-23 23:32:541846 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271847 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541848 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021849 EXPECT_EQ(OK,
1850 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]63534512012-12-23 18:49:001851
1852 // Ack the request.
Renjie90e808e2019-01-24 07:24:041853 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
rchfb47f712017-05-21 03:24:001854 EXPECT_THAT(stream_->ReadResponseHeaders(
Yannic Bonenberger3c96beb2019-09-03 20:41:371855 base::BindOnce(&QuicHttpStreamTest::CloseStream,
1856 base::Unretained(this), stream_.get())),
robpercival214763f2016-07-01 23:27:011857 IsError(ERR_IO_PENDING));
[email protected]63534512012-12-23 18:49:001858
1859 // Send the response with a body.
[email protected]1e960032013-12-20 19:00:201860 SetResponse("404 OK", "hello world!");
[email protected]63534512012-12-23 18:49:001861 // In the course of processing this packet, the QuicHttpStream close itself.
rchfb47f712017-05-21 03:24:001862 size_t response_size = 0;
rch1bcfddf22017-06-03 00:26:291863 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin, &response_size));
[email protected]63534512012-12-23 18:49:001864
fdoray92e35a72016-06-10 15:54:551865 base::RunLoop().RunUntilIdle();
rchb27683c2015-07-29 23:53:501866
[email protected]63534512012-12-23 18:49:001867 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101868
1869 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451870 // headers and payload.
1871 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1872 stream_->GetTotalSentBytes());
rchfb47f712017-05-21 03:24:001873 // The stream was closed after receiving the headers.
1874 EXPECT_EQ(static_cast<int64_t>(response_size),
1875 stream_->GetTotalReceivedBytes());
[email protected]63534512012-12-23 18:49:001876}
1877
[email protected]1e960032013-12-20 19:00:201878TEST_P(QuicHttpStreamTest, Priority) {
1879 SetRequest("GET", "/", MEDIUM);
sclittlec4dc1a32015-09-24 00:15:451880 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231881 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251882 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231883 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371884 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231885 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1886 kIncludeVersion, kFin, MEDIUM, &spdy_request_headers_frame_length));
[email protected]24e5bc52013-09-18 15:36:581887 Initialize();
1888
1889 request_.method = "GET";
rchcd379012017-04-12 21:53:321890 request_.url = GURL("https://www.example.org/");
[email protected]24e5bc52013-09-18 15:36:581891
Steven Valdezb4ff0412018-01-18 22:39:271892 EXPECT_EQ(OK,
1893 stream_->InitializeStream(&request_, true, MEDIUM, net_log_.bound(),
1894 callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581895
rjshaded5ced072015-12-18 19:26:021896 EXPECT_EQ(OK,
1897 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581898
[email protected]24e5bc52013-09-18 15:36:581899 // Ack the request.
Renjie90e808e2019-01-24 07:24:041900 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011901 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1902 IsError(ERR_IO_PENDING));
[email protected]24e5bc52013-09-18 15:36:581903
1904 // Send the response with a body.
[email protected]1e960032013-12-20 19:00:201905 SetResponse("404 OK", "hello world!");
rchfb47f712017-05-21 03:24:001906 size_t response_size = 0;
1907 ProcessPacket(ConstructResponseHeadersPacket(2, kFin, &response_size));
[email protected]24e5bc52013-09-18 15:36:581908
rchfb47f712017-05-21 03:24:001909 EXPECT_EQ(OK, callback_.WaitForResult());
rchb27683c2015-07-29 23:53:501910
[email protected]24e5bc52013-09-18 15:36:581911 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101912
1913 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451914 // headers and payload.
1915 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1916 stream_->GetTotalSentBytes());
rchfb47f712017-05-21 03:24:001917 EXPECT_EQ(static_cast<int64_t>(response_size),
1918 stream_->GetTotalReceivedBytes());
[email protected]24e5bc52013-09-18 15:36:581919}
1920
xunjieli8dff50b2016-07-22 14:19:061921TEST_P(QuicHttpStreamTest, SessionClosedDuringDoLoop) {
1922 SetRequest("POST", "/", DEFAULT_PRIORITY);
1923 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231924 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251925 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231926 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431927 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:321928 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411929 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231930 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1931 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1932 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411933 } else {
1934 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231935 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1936 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1937 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411938 }
1939
xunjieli8dff50b2016-07-22 14:19:061940 // Second data write will result in a synchronous failure which will close
1941 // the session.
1942 AddWrite(SYNCHRONOUS, ERR_FAILED);
1943 Initialize();
1944
Jeremy Roman0579ed62017-08-29 15:56:191945 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121946 auto* chunked_upload_stream =
1947 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
xunjieli8dff50b2016-07-22 14:19:061948
1949 request_.method = "POST";
rchcd379012017-04-12 21:53:321950 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121951 request_.upload_data_stream = upload_data_stream_.get();
xunjieli8dff50b2016-07-22 14:19:061952 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201953 TestCompletionCallback().callback(), NetLogWithSource()));
xunjieli8dff50b2016-07-22 14:19:061954
1955 size_t chunk_size = strlen(kUploadData);
rch97827ee2017-05-24 23:49:121956 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
xunjieli8dff50b2016-07-22 14:19:061957 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271958 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli8dff50b2016-07-22 14:19:061959 net_log_.bound(), callback_.callback()));
1960 QuicHttpStream* stream = stream_.get();
1961 DeleteStreamCallback delete_stream_callback(std::move(stream_));
1962 // SendRequest() completes asynchronously after the final chunk is added.
Yixin Wange7ecc472018-03-06 19:00:251963 // Error does not surface yet since packet write is triggered by a packet
1964 // flusher that tries to bundle request body writes.
xunjieli8dff50b2016-07-22 14:19:061965 ASSERT_EQ(ERR_IO_PENDING,
1966 stream->SendRequest(headers_, &response_, callback_.callback()));
rch97827ee2017-05-24 23:49:121967 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
xunjieli8dff50b2016-07-22 14:19:061968 int rv = callback_.WaitForResult();
Yixin Wange7ecc472018-03-06 19:00:251969 EXPECT_EQ(OK, rv);
1970 // Error will be surfaced once an attempt to read the response occurs.
1971 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1972 stream->ReadResponseHeaders(callback_.callback()));
xunjieli8dff50b2016-07-22 14:19:061973}
1974
rtenneti15656ae2016-01-23 03:05:031975TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersComplete) {
1976 SetRequest("POST", "/", DEFAULT_PRIORITY);
Victor Vasiliev7da08172019-10-14 06:04:251977 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231978 AddWrite(ConstructInitialSettingsPacket());
rtenneti15656ae2016-01-23 03:05:031979 AddWrite(SYNCHRONOUS, ERR_FAILED);
1980 Initialize();
1981
Jeremy Roman0579ed62017-08-29 15:56:191982 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
Yixin Wange7ecc472018-03-06 19:00:251983 auto* chunked_upload_stream =
1984 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
rtenneti15656ae2016-01-23 03:05:031985
1986 request_.method = "POST";
rchcd379012017-04-12 21:53:321987 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121988 request_.upload_data_stream = upload_data_stream_.get();
rtenneti15656ae2016-01-23 03:05:031989 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201990 TestCompletionCallback().callback(), NetLogWithSource()));
rtenneti15656ae2016-01-23 03:05:031991
xunjieli5fafe142016-03-23 23:32:541992 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271993 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541994 net_log_.bound(), callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:251995 ASSERT_EQ(ERR_IO_PENDING,
rtenneti15656ae2016-01-23 03:05:031996 stream_->SendRequest(headers_, &response_, callback_.callback()));
mmenkeffff3642017-06-15 17:37:241997
Yixin Wange7ecc472018-03-06 19:00:251998 // Error will be surfaced once |upload_data_stream| triggers the next write.
1999 size_t chunk_size = strlen(kUploadData);
2000 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2001 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR, callback_.WaitForResult());
2002
2003 EXPECT_LE(0, stream_->GetTotalSentBytes());
2004 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2005}
2006
2007TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersCompleteReadResponse) {
2008 SetRequest("POST", "/", DEFAULT_PRIORITY);
Victor Vasiliev7da08172019-10-14 06:04:252009 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232010 AddWrite(ConstructInitialSettingsPacket());
Yixin Wange7ecc472018-03-06 19:00:252011 AddWrite(SYNCHRONOUS, ERR_FAILED);
2012 Initialize();
2013
2014 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
2015 auto* chunked_upload_stream =
2016 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
2017
2018 request_.method = "POST";
2019 request_.url = GURL("https://www.example.org/");
2020 request_.upload_data_stream = upload_data_stream_.get();
2021
2022 size_t chunk_size = strlen(kUploadData);
2023 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2024
2025 ASSERT_EQ(OK, request_.upload_data_stream->Init(
2026 TestCompletionCallback().callback(), NetLogWithSource()));
2027
2028 ASSERT_EQ(OK,
2029 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
2030 net_log_.bound(), callback_.callback()));
2031 ASSERT_EQ(OK,
2032 stream_->SendRequest(headers_, &response_, callback_.callback()));
2033
2034 // Error will be surfaced once an attempt to read the response occurs.
2035 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
2036 stream_->ReadResponseHeaders(callback_.callback()));
2037
mmenkeffff3642017-06-15 17:37:242038 EXPECT_LE(0, stream_->GetTotalSentBytes());
2039 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rtenneti15656ae2016-01-23 03:05:032040}
2041
2042TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBodyComplete) {
2043 SetRequest("POST", "/", DEFAULT_PRIORITY);
2044 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232045 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252046 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232047 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:372048 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:232049 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2050 kIncludeVersion, !kFin, DEFAULT_PRIORITY,
2051 &spdy_request_headers_frame_length));
rtenneti15656ae2016-01-23 03:05:032052 AddWrite(SYNCHRONOUS, ERR_FAILED);
2053 Initialize();
2054
Jeremy Roman0579ed62017-08-29 15:56:192055 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:122056 auto* chunked_upload_stream =
2057 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
rtenneti15656ae2016-01-23 03:05:032058
2059 request_.method = "POST";
rchcd379012017-04-12 21:53:322060 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122061 request_.upload_data_stream = upload_data_stream_.get();
rtenneti15656ae2016-01-23 03:05:032062 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202063 TestCompletionCallback().callback(), NetLogWithSource()));
rtenneti15656ae2016-01-23 03:05:032064
xunjieli5fafe142016-03-23 23:32:542065 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272066 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542067 net_log_.bound(), callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252068 ASSERT_EQ(ERR_IO_PENDING,
rtenneti15656ae2016-01-23 03:05:032069 stream_->SendRequest(headers_, &response_, callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252070
2071 size_t chunk_size = strlen(kUploadData);
2072 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2073 // Error does not surface yet since packet write is triggered by a packet
2074 // flusher that tries to bundle request body writes.
2075 ASSERT_EQ(OK, callback_.WaitForResult());
2076 // Error will be surfaced once an attempt to read the response occurs.
2077 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
2078 stream_->ReadResponseHeaders(callback_.callback()));
2079
2080 EXPECT_LE(0, stream_->GetTotalSentBytes());
2081 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2082}
2083
2084TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBundledBodyComplete) {
2085 SetRequest("POST", "/", DEFAULT_PRIORITY);
2086 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232087 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252088 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232089 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:432090 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:322091 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:412092 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:232093 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2094 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
2095 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:412096 } else {
2097 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:232098 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2099 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
2100 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:412101 }
2102
Yixin Wange7ecc472018-03-06 19:00:252103 AddWrite(SYNCHRONOUS, ERR_FAILED);
2104 Initialize();
2105
2106 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
2107 auto* chunked_upload_stream =
2108 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
2109
2110 request_.method = "POST";
2111 request_.url = GURL("https://www.example.org/");
2112 request_.upload_data_stream = upload_data_stream_.get();
2113
2114 size_t chunk_size = strlen(kUploadData);
2115 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
2116
2117 ASSERT_EQ(OK, request_.upload_data_stream->Init(
2118 TestCompletionCallback().callback(), NetLogWithSource()));
2119
2120 ASSERT_EQ(OK,
2121 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
2122 net_log_.bound(), callback_.callback()));
2123 ASSERT_EQ(ERR_IO_PENDING,
2124 stream_->SendRequest(headers_, &response_, callback_.callback()));
2125
2126 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2127
2128 // Error does not surface yet since packet write is triggered by a packet
2129 // flusher that tries to bundle request body writes.
2130 ASSERT_EQ(OK, callback_.WaitForResult());
2131 // Error will be surfaced once an attempt to read the response occurs.
2132 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
2133 stream_->ReadResponseHeaders(callback_.callback()));
2134
2135 EXPECT_LE(0, stream_->GetTotalSentBytes());
2136 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rtenneti15656ae2016-01-23 03:05:032137}
2138
ckrasic3865ee0f2016-02-29 22:04:562139TEST_P(QuicHttpStreamTest, ServerPushGetRequest) {
2140 SetRequest("GET", "/", DEFAULT_PRIORITY);
2141 Initialize();
2142
2143 // Initialize the first stream, for receiving the promise on.
2144 request_.method = "GET";
rchcd379012017-04-12 21:53:322145 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562146
xunjieli5fafe142016-03-23 23:32:542147 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272148 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542149 net_log_.bound(), callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232150 ASSERT_EQ(OK,
2151 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562152
2153 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2154 // packet, but does it matter?
2155 ReceivePromise(promise_id_);
2156 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2157
2158 request_.url = GURL(promise_url_);
2159
2160 // Make the second stream that will exercise the first step of the
2161 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272162 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2163 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2164 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562165
2166 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252167 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562168 size_t spdy_response_headers_frame_length;
2169 ProcessPacket(InnerConstructResponseHeadersPacket(
2170 1, promise_id_, false, &spdy_response_headers_frame_length));
2171
2172 // Receive the promised response body.
2173 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432174 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172175 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2176 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562177
2178 // Now sending a matching request will have successful rendezvous
2179 // with the promised stream.
Ryan Hamiltona1d1f4a2019-06-26 14:43:042180 ASSERT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
ckrasic3865ee0f2016-02-29 22:04:562181 callback_.callback()));
2182
2183 EXPECT_EQ(
2184 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2185 ->id(),
2186 promise_id_);
2187
2188 // The headers will be immediately available.
robpercival214763f2016-07-01 23:27:012189 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2190 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562191
2192 // As will be the body.
2193 EXPECT_EQ(
2194 static_cast<int>(strlen(kResponseBody)),
2195 promised_stream_->ReadResponseBody(
2196 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2197 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2198 EXPECT_TRUE(AtEof());
2199
ckrasic3865ee0f2016-02-29 22:04:562200 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2201 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412202 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562203 promised_stream_->GetTotalReceivedBytes());
2204}
2205
2206TEST_P(QuicHttpStreamTest, ServerPushGetRequestSlowResponse) {
2207 SetRequest("GET", "/", DEFAULT_PRIORITY);
2208 Initialize();
2209
2210 // Initialize the first stream, for receiving the promise on.
2211 request_.method = "GET";
rchcd379012017-04-12 21:53:322212 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562213
xunjieli5fafe142016-03-23 23:32:542214 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272215 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542216 net_log_.bound(), callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232217 ASSERT_EQ(OK,
2218 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562219
2220 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2221 // packet, but does it matter?
2222 ReceivePromise(promise_id_);
2223 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2224
2225 request_.url = GURL(promise_url_);
2226
2227 // Make the second stream that will exercise the first step of the
2228 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272229 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2230 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2231 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562232
2233 // Now sending a matching request will rendezvous with the promised
2234 // stream, but pending secondary validation.
2235 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2236 headers_, &response_, callback_.callback()));
2237
2238 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252239 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562240 size_t spdy_response_headers_frame_length;
2241 ProcessPacket(InnerConstructResponseHeadersPacket(
2242 1, promise_id_, false, &spdy_response_headers_frame_length));
2243
2244 // Receive the promised response body.
2245 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432246 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172247 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2248 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562249
fdoray92e35a72016-06-10 15:54:552250 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562251
2252 // Rendezvous should have succeeded now, so the promised stream
2253 // should point at our push stream, and we should be able read
2254 // headers and data from it.
robpercival214763f2016-07-01 23:27:012255 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562256
2257 EXPECT_EQ(
2258 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2259 ->id(),
2260 promise_id_);
2261
robpercival214763f2016-07-01 23:27:012262 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2263 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562264
2265 EXPECT_EQ(
2266 static_cast<int>(strlen(kResponseBody)),
2267 promised_stream_->ReadResponseBody(
2268 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2269
2270 // Callback should return
2271 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2272 EXPECT_TRUE(AtEof());
2273
ckrasic3865ee0f2016-02-29 22:04:562274 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2275 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412276 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562277 promised_stream_->GetTotalReceivedBytes());
2278}
2279
ckrasic2c63f9b2016-08-16 23:54:072280// Verify fix for crbug.com/637349
2281TEST_P(QuicHttpStreamTest, ServerPushCancelHttpStreamBeforeResponse) {
2282 SetRequest("GET", "/", DEFAULT_PRIORITY);
2283 Initialize();
2284
2285 // Initialize the first stream, for receiving the promise on.
2286 request_.method = "GET";
rchcd379012017-04-12 21:53:322287 request_.url = GURL("https://www.example.org/");
ckrasic2c63f9b2016-08-16 23:54:072288
2289 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272290 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
ckrasic2c63f9b2016-08-16 23:54:072291 net_log_.bound(), callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232292 ASSERT_EQ(OK,
2293 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic2c63f9b2016-08-16 23:54:072294
2295 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2296 // packet, but does it matter?
2297 ReceivePromise(promise_id_);
2298 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2299
2300 request_.url = GURL(promise_url_);
2301
2302 // Make the second stream that will exercise the first step of the
2303 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272304 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2305 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2306 callback_.callback()));
ckrasic2c63f9b2016-08-16 23:54:072307
2308 // Now sending a matching request will rendezvous with the promised
2309 // stream, but pending secondary validation.
2310 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2311 headers_, &response_, callback_.callback()));
2312
2313 base::RunLoop().RunUntilIdle();
2314
2315 // Cause of FinalValidation() crash as per bug.
2316 promised_stream_.reset();
2317
2318 // Receive the promised response headers.
2319 response_headers_ = promised_response_.Clone();
2320 size_t spdy_response_headers_frame_length;
2321 ProcessPacket(InnerConstructResponseHeadersPacket(
2322 1, promise_id_, false, &spdy_response_headers_frame_length));
2323}
2324
ckrasic3865ee0f2016-02-29 22:04:562325TEST_P(QuicHttpStreamTest, ServerPushCrossOriginOK) {
2326 SetRequest("GET", "/", DEFAULT_PRIORITY);
2327 Initialize();
2328
2329 // Initialize the first stream, for receiving the promise on.
2330 request_.method = "GET";
rchcd379012017-04-12 21:53:322331 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562332
xunjieli5fafe142016-03-23 23:32:542333 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272334 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542335 net_log_.bound(), callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232336 ASSERT_EQ(OK,
2337 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562338
2339 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2340 // packet, but does it matter?
2341
2342 push_promise_[":authority"] = "mail.example.org";
David Schinazi3f7465c2019-07-12 01:57:052343 promise_url_ =
2344 quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
ckrasic3865ee0f2016-02-29 22:04:562345
2346 ReceivePromise(promise_id_);
2347 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2348
2349 request_.url = GURL(promise_url_);
2350
2351 // Make the second stream that will exercise the first step of the
2352 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272353 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2354 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2355 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562356
2357 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252358 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562359 size_t spdy_response_headers_frame_length;
2360 ProcessPacket(InnerConstructResponseHeadersPacket(
2361 1, promise_id_, false, &spdy_response_headers_frame_length));
2362
2363 // Receive the promised response body.
2364 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432365 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172366 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2367 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562368
2369 // Now sending a matching request will have successful rendezvous
2370 // with the promised stream.
2371 EXPECT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
2372 callback_.callback()));
2373
2374 EXPECT_EQ(
2375 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2376 ->id(),
2377 promise_id_);
2378
2379 // The headers will be immediately available.
robpercival214763f2016-07-01 23:27:012380 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2381 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562382
2383 // As will be the body.
2384 EXPECT_EQ(
2385 static_cast<int>(strlen(kResponseBody)),
2386 promised_stream_->ReadResponseBody(
2387 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2388 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2389 EXPECT_TRUE(AtEof());
2390
ckrasic3865ee0f2016-02-29 22:04:562391 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2392 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412393 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562394 promised_stream_->GetTotalReceivedBytes());
2395}
2396
2397TEST_P(QuicHttpStreamTest, ServerPushCrossOriginFail) {
2398 SetRequest("GET", "/", DEFAULT_PRIORITY);
2399 Initialize();
2400
2401 // Initialize the first stream, for receiving the promise on.
2402 request_.method = "GET";
rchcd379012017-04-12 21:53:322403 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562404
xunjieli5fafe142016-03-23 23:32:542405 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272406 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542407 net_log_.bound(), callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232408 ASSERT_EQ(OK,
2409 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562410
2411 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2412 // packet, but does it matter?
2413 push_promise_[":authority"] = "www.notexample.org";
David Schinazi3f7465c2019-07-12 01:57:052414 promise_url_ =
2415 quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
ckrasic3865ee0f2016-02-29 22:04:562416
2417 ReceivePromise(promise_id_);
2418 // The promise will have been rejected because the cert doesn't
2419 // match.
2420 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
2421}
2422
2423TEST_P(QuicHttpStreamTest, ServerPushVaryCheckOK) {
2424 SetRequest("GET", "/", DEFAULT_PRIORITY);
2425 Initialize();
2426
2427 // Initialize the first stream, for receiving the promise on.
2428 request_.method = "GET";
rchcd379012017-04-12 21:53:322429 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562430
xunjieli5fafe142016-03-23 23:32:542431 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272432 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542433 net_log_.bound(), callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232434 ASSERT_EQ(OK,
2435 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562436
2437 push_promise_["accept-encoding"] = "gzip";
ckrasic3865ee0f2016-02-29 22:04:562438
2439 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2440 // packet, but does it matter?
2441 ReceivePromise(promise_id_);
2442 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2443
2444 request_.url = GURL(promise_url_);
2445
2446 // Make the second stream that will exercise the first step of the
2447 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272448 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2449 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2450 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562451
2452 headers_.SetHeader("accept-encoding", "gzip");
2453
2454 // Now sending a matching request will rendezvous with the promised
2455 // stream, but pending secondary validation.
2456 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2457 headers_, &response_, callback_.callback()));
2458
2459 // Receive the promised response headers.
2460 promised_response_["vary"] = "accept-encoding";
bnc94893a72016-06-30 13:45:252461 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562462 size_t spdy_response_headers_frame_length;
2463 ProcessPacket(InnerConstructResponseHeadersPacket(
2464 1, promise_id_, false, &spdy_response_headers_frame_length));
2465
2466 // Receive the promised response body.
2467 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432468 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172469 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2470 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562471
fdoray92e35a72016-06-10 15:54:552472 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562473
2474 // Rendezvous should have succeeded now, so the promised stream
2475 // should point at our push stream, and we should be able read
2476 // headers and data from it.
robpercival214763f2016-07-01 23:27:012477 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562478
2479 EXPECT_EQ(
2480 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2481 ->id(),
2482 promise_id_);
2483
robpercival214763f2016-07-01 23:27:012484 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2485 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562486
2487 EXPECT_EQ(
2488 static_cast<int>(strlen(kResponseBody)),
2489 promised_stream_->ReadResponseBody(
2490 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2491
2492 // Callback should return
2493 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2494 EXPECT_TRUE(AtEof());
2495
ckrasic3865ee0f2016-02-29 22:04:562496 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2497 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412498 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562499 promised_stream_->GetTotalReceivedBytes());
2500}
2501
2502TEST_P(QuicHttpStreamTest, ServerPushVaryCheckFail) {
2503 SetRequest("GET", "/", DEFAULT_PRIORITY);
2504 request_headers_[":scheme"] = "https";
2505 request_headers_[":path"] = "/bar";
2506 request_headers_["accept-encoding"] = "sdch";
2507
ckrasic3865ee0f2016-02-29 22:04:562508 Initialize();
2509
2510 // Initialize the first stream, for receiving the promise on.
2511 request_.method = "GET";
rchcd379012017-04-12 21:53:322512 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562513
xunjieli5fafe142016-03-23 23:32:542514 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272515 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542516 net_log_.bound(), callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232517 ASSERT_EQ(OK,
2518 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562519
2520 push_promise_["accept-encoding"] = "gzip";
ckrasic3865ee0f2016-02-29 22:04:562521
2522 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2523 // packet, but does it matter?
2524 ReceivePromise(promise_id_);
2525 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2526
2527 request_.url = GURL(promise_url_);
2528
2529 // Make the second stream that will exercise the first step of the
2530 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272531 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2532 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2533 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562534
2535 headers_.SetHeader("accept-encoding", "sdch");
2536
2537 // Now sending a matching request will rendezvous with the promised
2538 // stream, but pending secondary validation.
2539 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2540 headers_, &response_, callback_.callback()));
2541
2542 // Receive the promised response headers.
2543 promised_response_["vary"] = "accept-encoding";
bnc94893a72016-06-30 13:45:252544 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562545 size_t spdy_response_headers_frame_length;
2546 ProcessPacket(InnerConstructResponseHeadersPacket(
2547 1, promise_id_, false, &spdy_response_headers_frame_length));
2548
fdoray92e35a72016-06-10 15:54:552549 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562550
2551 // Rendezvous should have failed due to vary mismatch, so the
2552 // promised stream should have been aborted, and instead we have a
2553 // new, regular client initiated stream.
robpercival214763f2016-07-01 23:27:012554 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562555
2556 // Not a server-initiated stream.
2557 EXPECT_NE(
2558 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2559 ->id(),
2560 promise_id_);
2561
2562 // Instead, a new client-initiated stream.
2563 EXPECT_EQ(
2564 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2565 ->id(),
Nick Harper23290b82019-05-02 00:02:562566 stream_id_ + quic::QuicUtils::StreamIdDelta(version_.transport_version));
ckrasic3865ee0f2016-02-29 22:04:562567
2568 // After rendezvous failure, the push stream has been cancelled.
2569 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
2570
2571 // The rest of the test verifies that the retried as
2572 // client-initiated version of |promised_stream_| works as intended.
2573
2574 // Ack the request.
Renjie90e808e2019-01-24 07:24:042575 ProcessPacket(ConstructServerAckPacket(2, 1, 1, 1));
ckrasic3865ee0f2016-02-29 22:04:562576
bnc614a92d32016-04-04 13:56:072577 SetResponse("404 Not Found", string());
ckrasic3865ee0f2016-02-29 22:04:562578 size_t spdy_response_header_frame_length;
2579 ProcessPacket(InnerConstructResponseHeadersPacket(
Nick Harper23290b82019-05-02 00:02:562580 3,
2581 stream_id_ + quic::QuicUtils::StreamIdDelta(version_.transport_version),
2582 kFin, &spdy_response_header_frame_length));
ckrasic3865ee0f2016-02-29 22:04:562583
fdoray92e35a72016-06-10 15:54:552584 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562585
robpercival214763f2016-07-01 23:27:012586 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2587 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562588 ASSERT_TRUE(response_.headers.get());
2589 EXPECT_EQ(404, response_.headers->response_code());
2590 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
2591 EXPECT_FALSE(response_.response_time.is_null());
2592 EXPECT_FALSE(response_.request_time.is_null());
2593
2594 // There is no body, so this should return immediately.
2595 EXPECT_EQ(
2596 0, promised_stream_->ReadResponseBody(
2597 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2598 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2599
2600 stream_->Close(true);
2601
2602 EXPECT_TRUE(AtEof());
ckrasic3865ee0f2016-02-29 22:04:562603}
2604
maksim.sisov84e20c92016-06-23 08:49:342605TEST_P(QuicHttpStreamTest, DataReadErrorSynchronous) {
2606 SetRequest("POST", "/", DEFAULT_PRIORITY);
2607 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232608 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252609 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232610 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Yixin Wange7ecc472018-03-06 19:00:252611 AddWrite(ConstructRequestAndRstPacket(
Renjie Tangaadb84b2019-08-31 01:00:232612 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2613 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
2614 &spdy_request_headers_frame_length, quic::QUIC_ERROR_PROCESSING_STREAM));
maksim.sisov84e20c92016-06-23 08:49:342615
2616 Initialize();
2617
Jeremy Roman0579ed62017-08-29 15:56:192618 upload_data_stream_ = std::make_unique<ReadErrorUploadDataStream>(
maksim.sisov84e20c92016-06-23 08:49:342619 ReadErrorUploadDataStream::FailureMode::SYNC);
2620 request_.method = "POST";
rchcd379012017-04-12 21:53:322621 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122622 request_.upload_data_stream = upload_data_stream_.get();
maksim.sisov84e20c92016-06-23 08:49:342623 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202624 TestCompletionCallback().callback(), NetLogWithSource()));
maksim.sisov84e20c92016-06-23 08:49:342625
2626 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272627 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
maksim.sisov84e20c92016-06-23 08:49:342628 net_log_.bound(), callback_.callback()));
2629
2630 int result = stream_->SendRequest(headers_, &response_, callback_.callback());
robpercival214763f2016-07-01 23:27:012631 EXPECT_THAT(result, IsError(ERR_FAILED));
maksim.sisov84e20c92016-06-23 08:49:342632
2633 EXPECT_TRUE(AtEof());
2634
2635 // QuicHttpStream::GetTotalSent/ReceivedBytes includes only headers.
2636 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
2637 stream_->GetTotalSentBytes());
2638 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2639}
2640
2641TEST_P(QuicHttpStreamTest, DataReadErrorAsynchronous) {
2642 SetRequest("POST", "/", DEFAULT_PRIORITY);
2643 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232644 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252645 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232646 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:372647 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:232648 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2649 kIncludeVersion, !kFin, DEFAULT_PRIORITY,
2650 &spdy_request_headers_frame_length));
2651 AddWrite(
2652 ConstructClientRstStreamErrorPacket(packet_number++, !kIncludeVersion));
maksim.sisov84e20c92016-06-23 08:49:342653
2654 Initialize();
2655
Jeremy Roman0579ed62017-08-29 15:56:192656 upload_data_stream_ = std::make_unique<ReadErrorUploadDataStream>(
maksim.sisov84e20c92016-06-23 08:49:342657 ReadErrorUploadDataStream::FailureMode::ASYNC);
2658 request_.method = "POST";
rchcd379012017-04-12 21:53:322659 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122660 request_.upload_data_stream = upload_data_stream_.get();
maksim.sisov84e20c92016-06-23 08:49:342661 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202662 TestCompletionCallback().callback(), NetLogWithSource()));
maksim.sisov84e20c92016-06-23 08:49:342663
2664 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272665 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
maksim.sisov84e20c92016-06-23 08:49:342666 net_log_.bound(), callback_.callback()));
2667
2668 int result = stream_->SendRequest(headers_, &response_, callback_.callback());
2669
Renjie90e808e2019-01-24 07:24:042670 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
maksim.sisov84e20c92016-06-23 08:49:342671 SetResponse("200 OK", string());
2672
robpercival214763f2016-07-01 23:27:012673 EXPECT_THAT(result, IsError(ERR_IO_PENDING));
2674 EXPECT_THAT(callback_.GetResult(result), IsError(ERR_FAILED));
maksim.sisov84e20c92016-06-23 08:49:342675
2676 EXPECT_TRUE(AtEof());
2677
2678 // QuicHttpStream::GetTotalSent/ReceivedBytes includes only headers.
2679 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
2680 stream_->GetTotalSentBytes());
2681 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2682}
2683
[email protected]f702d572012-12-04 15:56:202684} // namespace test
[email protected]f702d572012-12-04 15:56:202685} // namespace net