blob: 348030f2504f24677f0683e7848e257700a0aea5 [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"
Bence Béky97ec688c2021-03-16 13:48:5018#include "base/test/metrics/histogram_tester.h"
gabf767595f2016-05-11 18:50:3519#include "base/threading/thread_task_runner_handle.h"
Zhongyi Shic16b4102019-02-12 00:37:4020#include "base/time/default_tick_clock.h"
xunjieli84adaab2016-09-20 01:12:2821#include "base/time/time.h"
mmenkecbc2b712014-10-09 20:29:0722#include "net/base/chunked_upload_data_stream.h"
23#include "net/base/elements_upload_data_stream.h"
David Benjamin0288768a2019-07-22 15:00:2624#include "net/base/load_flags.h"
xunjieli84adaab2016-09-20 01:12:2825#include "net/base/load_timing_info.h"
26#include "net/base/load_timing_info_test_util.h"
[email protected]f702d572012-12-04 15:56:2027#include "net/base/net_errors.h"
28#include "net/base/test_completion_callback.h"
[email protected]b2d26cfd2012-12-11 10:36:0629#include "net/base/upload_bytes_element_reader.h"
Ben Schwartz3ff4dc1e62021-04-27 21:15:2330#include "net/dns/public/secure_dns_policy.h"
[email protected]f702d572012-12-04 15:56:2031#include "net/http/http_response_headers.h"
[email protected]5db452202014-08-19 05:22:1532#include "net/http/transport_security_state.h"
mikecirone8b85c432016-09-08 19:11:0033#include "net/log/net_log_event_type.h"
xunjieli5fafe142016-03-23 23:32:5434#include "net/log/test_net_log.h"
35#include "net/log/test_net_log_util.h"
Victor Vasiliev4f6fb892019-05-31 16:58:3136#include "net/quic/address_utils.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0837#include "net/quic/crypto/proof_verifier_chromium.h"
38#include "net/quic/mock_crypto_client_stream_factory.h"
Ryan Hamiltona1d1f4a2019-06-26 14:43:0439#include "net/quic/platform/impl/quic_test_impl.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0840#include "net/quic/quic_chromium_alarm_factory.h"
41#include "net/quic/quic_chromium_connection_helper.h"
42#include "net/quic/quic_chromium_packet_reader.h"
43#include "net/quic/quic_chromium_packet_writer.h"
Matt Menkefca05b62019-09-20 23:15:5644#include "net/quic/quic_crypto_client_config_handle.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0845#include "net/quic/quic_http_utils.h"
46#include "net/quic/quic_server_info.h"
47#include "net/quic/quic_stream_factory.h"
48#include "net/quic/quic_test_packet_maker.h"
Ryan Hamilton0d65a8c2019-06-07 00:46:0249#include "net/quic/quic_test_packet_printer.h"
Matt Menkefca05b62019-09-20 23:15:5650#include "net/quic/test_quic_crypto_client_config_handle.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0851#include "net/quic/test_task_runner.h"
tbansalca83c002016-04-28 20:56:2852#include "net/socket/socket_performance_watcher.h"
[email protected]f702d572012-12-04 15:56:2053#include "net/socket/socket_test_util.h"
Bence Béky94658bf2018-05-11 19:22:5854#include "net/spdy/spdy_http_utils.h"
rch03b7a202016-02-05 00:54:2055#include "net/test/cert_test_util.h"
robpercival214763f2016-07-01 23:27:0156#include "net/test/gtest_util.h"
rsleevia69c79a2016-06-22 03:28:4357#include "net/test/test_data_directory.h"
Gabriel Charettec7108742019-08-23 03:31:4058#include "net/test/test_with_task_environment.h"
Victor Vasiliev6bb59d22019-03-08 21:34:5159#include "net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.h"
60#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
61#include "net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h"
62#include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
David Schinazi3f7465c2019-07-12 01:57:0563#include "net/third_party/quiche/src/quic/core/http/spdy_server_push_utils.h"
Victor Vasiliev6bb59d22019-03-08 21:34:5164#include "net/third_party/quiche/src/quic/core/quic_connection.h"
65#include "net/third_party/quiche/src/quic/core/quic_utils.h"
66#include "net/third_party/quiche/src/quic/core/quic_write_blocked_list.h"
Ryan Hamiltona1d1f4a2019-06-26 14:43:0467#include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h"
68#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
Victor Vasiliev6bb59d22019-03-08 21:34:5169#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
70#include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
71#include "net/third_party/quiche/src/quic/test_tools/mock_random.h"
Bence Béky6e243aa2019-12-13 19:01:0772#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h"
Victor Vasiliev6bb59d22019-03-08 21:34:5173#include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
74#include "net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h"
75#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
Victor Vasiliev27cc7712019-01-24 11:50:1476#include "net/third_party/quiche/src/spdy/core/spdy_frame_builder.h"
77#include "net/third_party/quiche/src/spdy/core/spdy_framer.h"
78#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
Ramin Halavati683bcaa92018-02-14 08:42:3979#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
[email protected]f702d572012-12-04 15:56:2080#include "testing/gmock/include/gmock/gmock.h"
81#include "testing/gtest/include/gtest/gtest.h"
82
bnc614a92d32016-04-04 13:56:0783using std::string;
[email protected]f702d572012-12-04 15:56:2084using testing::_;
[email protected]06ff5152013-08-29 01:03:0585using testing::AnyNumber;
86using testing::Return;
[email protected]f702d572012-12-04 15:56:2087
88namespace net {
[email protected]f702d572012-12-04 15:56:2089namespace test {
[email protected]f702d572012-12-04 15:56:2090namespace {
91
[email protected]16ba7742014-08-22 00:57:2592const char kUploadData[] = "Really nifty data!";
rch9ae5b3b2016-02-11 00:36:2993const char kDefaultServerHostName[] = "www.example.org";
rchcd379012017-04-12 21:53:3294const uint16_t kDefaultServerPort = 443;
[email protected]f702d572012-12-04 15:56:2095
David Schinazi09e9a6012019-10-03 17:37:5796struct TestParams {
97 quic::ParsedQuicVersion version;
98 bool client_headers_include_h2_stream_dependency;
99};
100
101// Used by ::testing::PrintToStringParamName().
102std::string PrintToString(const TestParams& p) {
Victor Vasiliev62c09dc2020-11-06 18:18:29103 return base::StrCat(
104 {ParsedQuicVersionToString(p.version), "_",
105 (p.client_headers_include_h2_stream_dependency ? "" : "No"),
106 "Dependency"});
David Schinazi09e9a6012019-10-03 17:37:57107}
108
109std::vector<TestParams> GetTestParams() {
110 std::vector<TestParams> params;
111 quic::ParsedQuicVersionVector all_supported_versions =
112 quic::AllSupportedVersions();
113 for (const auto& version : all_supported_versions) {
114 params.push_back(TestParams{version, false});
115 params.push_back(TestParams{version, true});
116 }
117 return params;
118}
119
Bence Békye0d3747d2020-08-28 23:16:40120// Returns true if |params| is a dict, has an entry with key "headers", that
121// entry is a list of strings, which when interpreted as colon-separated
122// key-value pairs has exactly one entry with |key| and that entry has value
123// |expected_value|.
124bool CheckHeader(const base::Value& params,
125 base::StringPiece key,
126 base::StringPiece expected_value) {
127 if (!params.is_dict()) {
128 return false;
129 }
130 const base::Value* headers = params.FindListKey("headers");
131 if (!headers) {
132 return false;
133 }
134
135 std::string header_prefix = base::StrCat({key, ": "});
136 std::string expected_header = base::StrCat({header_prefix, expected_value});
137
138 auto header_list = headers->GetList();
139 auto header_it = header_list.begin();
140 bool header_found = false;
141 while (header_it != header_list.end()) {
142 if (!header_it->is_string()) {
143 return false;
144 }
145 const std::string& header = header_it->GetString();
146 if (base::StartsWith(header, header_prefix)) {
147 if (header_found) {
148 return false;
149 }
150 if (header != expected_header) {
151 return false;
152 }
153 header_found = true;
154 }
155 ++header_it;
156 }
157 return header_found;
158}
159
Ryan Hamilton8d9ee76e2018-05-29 23:52:52160class TestQuicConnection : public quic::QuicConnection {
[email protected]f702d572012-12-04 15:56:20161 public:
Ryan Hamilton8d9ee76e2018-05-29 23:52:52162 TestQuicConnection(const quic::ParsedQuicVersionVector& versions,
163 quic::QuicConnectionId connection_id,
[email protected]f702d572012-12-04 15:56:20164 IPEndPoint address,
rch12fef552016-01-15 16:26:31165 QuicChromiumConnectionHelper* helper,
rch16c74d1d2016-04-22 06:14:07166 QuicChromiumAlarmFactory* alarm_factory,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52167 quic::QuicPacketWriter* writer)
Victor Vasiliev4f6fb892019-05-31 16:58:31168 : quic::QuicConnection(connection_id,
Nick Harperd049f192020-10-02 02:56:10169 quic::QuicSocketAddress(),
Victor Vasiliev4f6fb892019-05-31 16:58:31170 ToQuicSocketAddress(address),
171 helper,
172 alarm_factory,
173 writer,
174 true /* owns_writer */,
175 quic::Perspective::IS_CLIENT,
176 versions) {}
[email protected]f702d572012-12-04 15:56:20177
Ryan Hamilton8d9ee76e2018-05-29 23:52:52178 void SetSendAlgorithm(quic::SendAlgorithmInterface* send_algorithm) {
179 quic::test::QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
[email protected]f702d572012-12-04 15:56:20180 }
181};
182
maksim.sisov84e20c92016-06-23 08:49:34183// UploadDataStream that always returns errors on data read.
184class ReadErrorUploadDataStream : public UploadDataStream {
185 public:
186 enum class FailureMode { SYNC, ASYNC };
187
188 explicit ReadErrorUploadDataStream(FailureMode mode)
Jeremy Romand54000b22019-07-08 18:40:16189 : UploadDataStream(true, 0), async_(mode) {}
maksim.sisov84e20c92016-06-23 08:49:34190 ~ReadErrorUploadDataStream() override {}
191
192 private:
193 void CompleteRead() { UploadDataStream::OnReadCompleted(ERR_FAILED); }
194
195 // UploadDataStream implementation:
tfarina42834112016-09-22 13:38:20196 int InitInternal(const NetLogWithSource& net_log) override { return OK; }
maksim.sisov84e20c92016-06-23 08:49:34197
198 int ReadInternal(IOBuffer* buf, int buf_len) override {
199 if (async_ == FailureMode::ASYNC) {
200 base::ThreadTaskRunnerHandle::Get()->PostTask(
kylecharf4fe5172019-02-15 18:53:49201 FROM_HERE, base::BindOnce(&ReadErrorUploadDataStream::CompleteRead,
202 weak_factory_.GetWeakPtr()));
maksim.sisov84e20c92016-06-23 08:49:34203 return ERR_IO_PENDING;
204 }
205 return ERR_FAILED;
206 }
207
208 void ResetInternal() override {}
209
210 const FailureMode async_;
211
Jeremy Romand54000b22019-07-08 18:40:16212 base::WeakPtrFactory<ReadErrorUploadDataStream> weak_factory_{this};
maksim.sisov84e20c92016-06-23 08:49:34213
214 DISALLOW_COPY_AND_ASSIGN(ReadErrorUploadDataStream);
215};
216
Bence Béky8ddc2492018-06-13 01:02:04217// A helper class that will delete |stream| when the callback is invoked.
xunjieli8dff50b2016-07-22 14:19:06218class DeleteStreamCallback : public TestCompletionCallbackBase {
219 public:
Bence Béky8ddc2492018-06-13 01:02:04220 explicit DeleteStreamCallback(std::unique_ptr<QuicHttpStream> stream)
221 : stream_(std::move(stream)) {}
xunjieli8dff50b2016-07-22 14:19:06222
Bence Béky8ddc2492018-06-13 01:02:04223 CompletionOnceCallback callback() {
224 return base::BindOnce(&DeleteStreamCallback::DeleteStream,
225 base::Unretained(this));
226 }
xunjieli8dff50b2016-07-22 14:19:06227
228 private:
229 void DeleteStream(int result) {
230 stream_.reset();
231 SetResult(result);
232 }
233
234 std::unique_ptr<QuicHttpStream> stream_;
xunjieli8dff50b2016-07-22 14:19:06235};
236
[email protected]f702d572012-12-04 15:56:20237} // namespace
238
[email protected]24e5bc52013-09-18 15:36:58239class QuicHttpStreamPeer {
240 public:
rch08e198572017-05-09 16:56:55241 static QuicChromiumClientStream::Handle* GetQuicChromiumClientStream(
[email protected]24e5bc52013-09-18 15:36:58242 QuicHttpStream* stream) {
rch08e198572017-05-09 16:56:55243 return stream->stream_.get();
[email protected]24e5bc52013-09-18 15:36:58244 }
245};
246
David Schinazi09e9a6012019-10-03 17:37:57247class QuicHttpStreamTest : public ::testing::TestWithParam<TestParams>,
Gabriel Charette694c3c332019-08-19 14:53:05248 public WithTaskEnvironment {
rchfb47f712017-05-21 03:24:00249 public:
250 void CloseStream(QuicHttpStream* stream, int /*rv*/) { stream->Close(false); }
251
[email protected]f702d572012-12-04 15:56:20252 protected:
[email protected]1e960032013-12-20 19:00:20253 static const bool kFin = true;
254 static const bool kIncludeVersion = true;
[email protected]1e960032013-12-20 19:00:20255
[email protected]f702d572012-12-04 15:56:20256 // Holds a packet to be written to the wire, and the IO mode that should
257 // be used by the mock socket when performing the write.
258 struct PacketToWrite {
Ryan Hamilton8d9ee76e2018-05-29 23:52:52259 PacketToWrite(IoMode mode, quic::QuicReceivedPacket* packet)
rjshaded5ced072015-12-18 19:26:02260 : mode(mode), packet(packet) {}
rtenneti15656ae2016-01-23 03:05:03261 PacketToWrite(IoMode mode, int rv) : mode(mode), packet(nullptr), rv(rv) {}
[email protected]f702d572012-12-04 15:56:20262 IoMode mode;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52263 quic::QuicReceivedPacket* packet;
rtenneti15656ae2016-01-23 03:05:03264 int rv;
[email protected]f702d572012-12-04 15:56:20265 };
266
267 QuicHttpStreamTest()
David Schinazi09e9a6012019-10-03 17:37:57268 : version_(GetParam().version),
269 client_headers_include_h2_stream_dependency_(
270 GetParam().client_headers_include_h2_stream_dependency),
Nick Harpera598fc5f2019-06-21 08:46:50271 crypto_config_(
272 quic::test::crypto_test_utils::ProofVerifierForTesting()),
Victor Costan9c7302b2018-08-27 16:39:44273 read_buffer_(base::MakeRefCounted<IOBufferWithSize>(4096)),
Fan Yang32c5a112018-12-10 20:06:33274 promise_id_(GetNthServerInitiatedUnidirectionalStreamId(0)),
275 stream_id_(GetNthClientInitiatedBidirectionalStreamId(0)),
David Schinazic8281052019-01-24 06:14:17276 connection_id_(quic::test::TestConnectionId(2)),
Yixin Wang079ad542018-01-11 04:06:05277 client_maker_(version_,
alyssar2adf3ac2016-05-03 17:12:58278 connection_id_,
279 &clock_,
280 kDefaultServerHostName,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52281 quic::Perspective::IS_CLIENT,
Yixin Wang079ad542018-01-11 04:06:05282 client_headers_include_h2_stream_dependency_),
283 server_maker_(version_,
zhongyi5dbfdd42017-06-20 05:22:15284 connection_id_,
alyssar2adf3ac2016-05-03 17:12:58285 &clock_,
286 kDefaultServerHostName,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52287 quic::Perspective::IS_SERVER,
Yixin Wang079ad542018-01-11 04:06:05288 false),
ckrasic3865ee0f2016-02-29 22:04:56289 random_generator_(0),
Ryan Hamilton0d65a8c2019-06-07 00:46:02290 printer_(version_) {
Renjie Tang98b4d512020-02-08 01:24:19291 FLAGS_quic_enable_http3_grease_randomness = false;
Zhongyi Shi49f8ad2fd2019-12-13 01:20:31292 quic::QuicEnableVersion(version_);
martijn21968ea2016-02-24 18:46:20293 IPAddress ip(192, 0, 2, 33);
[email protected]f702d572012-12-04 15:56:20294 peer_addr_ = IPEndPoint(ip, 443);
295 self_addr_ = IPEndPoint(ip, 8435);
Ryan Hamilton8d9ee76e2018-05-29 23:52:52296 clock_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(20));
Ramin Halavati683bcaa92018-02-14 08:42:39297 request_.traffic_annotation =
298 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f702d572012-12-04 15:56:20299 }
300
301 ~QuicHttpStreamTest() {
Renjieba55fae2018-09-20 03:05:16302 session_->CloseSessionOnError(ERR_ABORTED, quic::QUIC_INTERNAL_ERROR,
303 quic::ConnectionCloseBehavior::SILENT_CLOSE);
[email protected]f702d572012-12-04 15:56:20304 for (size_t i = 0; i < writes_.size(); i++) {
305 delete writes_[i].packet;
306 }
307 }
308
309 // Adds a packet to the list of expected writes.
Ryan Hamilton8d9ee76e2018-05-29 23:52:52310 void AddWrite(std::unique_ptr<quic::QuicReceivedPacket> packet) {
[email protected]1e960032013-12-20 19:00:20311 writes_.push_back(PacketToWrite(SYNCHRONOUS, packet.release()));
[email protected]f702d572012-12-04 15:56:20312 }
313
rtenneti15656ae2016-01-23 03:05:03314 void AddWrite(IoMode mode, int rv) {
315 writes_.push_back(PacketToWrite(mode, rv));
316 }
317
[email protected]f702d572012-12-04 15:56:20318 // Returns the packet to be written at position |pos|.
Ryan Hamilton8d9ee76e2018-05-29 23:52:52319 quic::QuicReceivedPacket* GetWrite(size_t pos) { return writes_[pos].packet; }
[email protected]f702d572012-12-04 15:56:20320
321 bool AtEof() {
rch37de576c2015-05-17 20:28:17322 return socket_data_->AllReadDataConsumed() &&
323 socket_data_->AllWriteDataConsumed();
[email protected]f702d572012-12-04 15:56:20324 }
325
Ryan Hamilton8d9ee76e2018-05-29 23:52:52326 void ProcessPacket(std::unique_ptr<quic::QuicReceivedPacket> packet) {
Victor Vasiliev4f6fb892019-05-31 16:58:31327 connection_->ProcessUdpPacket(ToQuicSocketAddress(self_addr_),
328 ToQuicSocketAddress(peer_addr_), *packet);
[email protected]f702d572012-12-04 15:56:20329 }
330
331 // Configures the test fixture to use the list of expected writes.
332 void Initialize() {
Renjie Tang6ff9a9b2021-02-03 22:11:09333 mock_writes_ = std::make_unique<MockWrite[]>(writes_.size());
[email protected]f702d572012-12-04 15:56:20334 for (size_t i = 0; i < writes_.size(); i++) {
rtenneti15656ae2016-01-23 03:05:03335 if (writes_[i].packet == nullptr) {
336 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].rv, i);
337 } else {
338 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].packet->data(),
339 writes_[i].packet->length());
340 }
bnc614a92d32016-04-04 13:56:07341 }
[email protected]f702d572012-12-04 15:56:20342
Renjie Tang6ff9a9b2021-02-03 22:11:09343 socket_data_ = std::make_unique<StaticSocketDataProvider>(
Ryan Sleevib8d7ea02018-05-07 20:01:01344 base::span<MockRead>(),
Renjie Tang6ff9a9b2021-02-03 22:11:09345 base::make_span(mock_writes_.get(), writes_.size()));
Ryan Hamilton0d65a8c2019-06-07 00:46:02346 socket_data_->set_printer(&printer_);
[email protected]f702d572012-12-04 15:56:20347
danakjad1777e2016-04-16 00:56:42348 std::unique_ptr<MockUDPClientSocket> socket(new MockUDPClientSocket(
xunjielib53b38c2016-03-24 15:54:36349 socket_data_.get(), net_log_.bound().net_log()));
[email protected]e13201d82012-12-12 05:00:32350 socket->Connect(peer_addr_);
[email protected]f702d572012-12-04 15:56:20351 runner_ = new TestTaskRunner(&clock_);
Ryan Hamilton8d9ee76e2018-05-29 23:52:52352 send_algorithm_ = new quic::test::MockSendAlgorithm();
rch7dd15702015-07-01 18:57:57353 EXPECT_CALL(*send_algorithm_, InRecovery()).WillRepeatedly(Return(false));
354 EXPECT_CALL(*send_algorithm_, InSlowStart()).WillRepeatedly(Return(false));
Victor Vasiliev7da08172019-10-14 06:04:25355 if (VersionUsesHttp3(version_.transport_version)) {
Renjie Tangaadb84b2019-08-31 01:00:23356 EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
357 .Times(testing::AtLeast(1));
358 }
Ryan Hamiltona1d1f4a2019-06-26 14:43:04359 EXPECT_CALL(*send_algorithm_, OnCongestionEvent(_, _, _, _, _))
360 .Times(AnyNumber());
rtenneti44f4a2e2015-08-07 14:00:07361 EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
Zhongyi Shica576df2019-04-12 17:43:40362 .WillRepeatedly(Return(quic::kMaxOutgoingPacketSize));
jokulik0e0a00c32016-06-13 21:51:58363 EXPECT_CALL(*send_algorithm_, PacingRate(_))
Ryan Hamilton8d9ee76e2018-05-29 23:52:52364 .WillRepeatedly(Return(quic::QuicBandwidth::Zero()));
Michael Warres74ee3ce2017-10-09 15:26:37365 EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true));
rtenneti44f4a2e2015-08-07 14:00:07366 EXPECT_CALL(*send_algorithm_, BandwidthEstimate())
Ryan Hamilton8d9ee76e2018-05-29 23:52:52367 .WillRepeatedly(Return(quic::QuicBandwidth::Zero()));
rch1e543ec2015-03-29 07:04:40368 EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(AnyNumber());
rch08cae032017-03-29 00:59:15369 EXPECT_CALL(*send_algorithm_, OnApplicationLimited(_)).Times(AnyNumber());
rch0d5bcf62017-05-24 22:48:45370 EXPECT_CALL(*send_algorithm_, GetCongestionControlType())
371 .Times(AnyNumber());
Renjie Tang6ff9a9b2021-02-03 22:11:09372 helper_ = std::make_unique<QuicChromiumConnectionHelper>(
373 &clock_, &random_generator_);
374 alarm_factory_ =
375 std::make_unique<QuicChromiumAlarmFactory>(runner_.get(), &clock_);
rch16c74d1d2016-04-22 06:14:07376
Michael Warres74ee3ce2017-10-09 15:26:37377 connection_ = new TestQuicConnection(
Nick Harper23290b82019-05-02 00:02:56378 quic::test::SupportedVersions(version_), connection_id_, peer_addr_,
379 helper_.get(), alarm_factory_.get(),
Ryan Hamilton9edcf1a2017-11-22 05:55:17380 new QuicChromiumPacketWriter(
381 socket.get(), base::ThreadTaskRunnerHandle::Get().get()));
[email protected]f702d572012-12-04 15:56:20382 connection_->set_visitor(&visitor_);
[email protected]fee17f72013-02-03 07:47:41383 connection_->SetSendAlgorithm(send_algorithm_);
rch03b7a202016-02-05 00:54:20384
385 // Load a certificate that is valid for *.example.org
386 scoped_refptr<X509Certificate> test_cert(
387 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
388 EXPECT_TRUE(test_cert.get());
389
390 verify_details_.cert_verify_result.verified_cert = test_cert;
391 verify_details_.cert_verify_result.is_issued_by_known_root = true;
392 crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details_);
393
xunjieli84adaab2016-09-20 01:12:28394 base::TimeTicks dns_end = base::TimeTicks::Now();
395 base::TimeTicks dns_start = dns_end - base::TimeDelta::FromMilliseconds(1);
Renjie Tang6ff9a9b2021-02-03 22:11:09396 session_ = std::make_unique<QuicChromiumClientSession>(
xunjielib53b38c2016-03-24 15:54:36397 connection_, std::move(socket),
rtenneti1cd3b162015-09-29 02:58:28398 /*stream_factory=*/nullptr, &crypto_client_stream_factory_, &clock_,
Nick Harper89bc7212018-07-31 19:07:57399 &transport_security_state_, /*ssl_config_service=*/nullptr,
danakjad1777e2016-04-16 00:56:42400 base::WrapUnique(static_cast<QuicServerInfo*>(nullptr)),
Paul Jensen8e3c5d32018-02-19 17:06:33401 QuicSessionKey(kDefaultServerHostName, kDefaultServerPort,
dalyk51ab46b2019-10-15 15:14:34402 PRIVACY_MODE_DISABLED, SocketTag(),
Ben Schwartz3ff4dc1e62021-04-27 21:15:23403 NetworkIsolationKey(), SecureDnsPolicy::kAllow),
Bence Béky1ceba552019-07-19 17:11:05404 /*require_confirmation=*/false,
Bence Béky1ceba552019-07-19 17:11:05405 /*migrate_session_early_v2=*/false,
Zhongyi Shi757fcce2018-06-27 05:41:27406 /*migrate_session_on_network_change_v2=*/false,
407 /*default_network=*/NetworkChangeNotifier::kInvalidNetworkHandle,
Zhongyi Shie01f2db2019-02-22 19:53:23408 quic::QuicTime::Delta::FromMilliseconds(
Ryan Sleevi2e8255b2019-07-17 21:02:21409 kDefaultRetransmittableOnWireTimeout.InMilliseconds()),
Zhongyi Shiaf38c4e42019-08-29 22:49:05410 /*migrate_idle_session=*/false, /*allow_port_migration=*/false,
411 kDefaultIdleSessionMigrationPeriod, kMaxTimeOnNonDefaultNetwork,
Zhongyi Shiee760762018-08-01 00:54:29412 kMaxMigrationsToNonDefaultNetworkOnWriteError,
Zhongyi Shi8b1e43f2017-12-13 20:46:30413 kMaxMigrationsToNonDefaultNetworkOnPathDegrading,
Zhongyi Shi5f587cc2017-11-21 23:24:17414 kQuicYieldAfterPacketsRead,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52415 quic::QuicTime::Delta::FromMilliseconds(
416 kQuicYieldAfterDurationMilliseconds),
Zhongyi Shidbce7f412019-02-01 23:16:29417 /*go_away_on_path_degrading*/ false,
Yixin Wang079ad542018-01-11 04:06:05418 client_headers_include_h2_stream_dependency_, /*cert_verify_flags=*/0,
Matt Menkefca05b62019-09-20 23:15:56419 quic::test::DefaultQuicConfig(),
420 std::make_unique<TestQuicCryptoClientConfigHandle>(&crypto_config_),
Matt Menked804aaf2020-07-21 21:25:48421 "CONNECTION_UNKNOWN", dns_start, dns_end,
422 std::make_unique<quic::QuicClientPushPromiseIndex>(), nullptr,
Zhongyi Shic16b4102019-02-12 00:37:40423 base::DefaultTickClock::GetInstance(),
xunjieli84adaab2016-09-20 01:12:28424 base::ThreadTaskRunnerHandle::Get().get(),
Renjie Tang6ff9a9b2021-02-03 22:11:09425 /*socket_performance_watcher=*/nullptr, net_log_.bound().net_log());
rtennetid39bd762015-06-12 01:05:52426 session_->Initialize();
rchf0b18c8a2017-05-05 19:31:57427
Bence Béky6e243aa2019-12-13 19:01:07428 // Blackhole QPACK decoder stream instead of constructing mock writes.
429 if (VersionUsesHttp3(version_.transport_version)) {
430 session_->qpack_decoder()->set_qpack_stream_sender_delegate(
431 &noop_qpack_stream_sender_delegate_);
432 }
433
434 TestCompletionCallback callback;
rch433bf5f2017-02-14 04:10:47435 session_->CryptoConnect(callback.callback());
Ryan Hamilton6c2a2a82017-12-15 02:06:28436 stream_ = std::make_unique<QuicHttpStream>(
Cammie Smith Barnes0f38aff2021-03-02 23:14:35437 session_->CreateHandle(HostPortPair("www.example.org", 443)),
438 std::vector<std::string>() /* dns_aliases */);
Ryan Hamilton6c2a2a82017-12-15 02:06:28439 promised_stream_ = std::make_unique<QuicHttpStream>(
Cammie Smith Barnes0f38aff2021-03-02 23:14:35440 session_->CreateHandle(HostPortPair("www.example.org", 443)),
441 std::vector<std::string>() /* dns_aliases */);
ckrasic3865ee0f2016-02-29 22:04:56442 push_promise_[":path"] = "/bar";
443 push_promise_[":authority"] = "www.example.org";
444 push_promise_[":version"] = "HTTP/1.1";
445 push_promise_[":method"] = "GET";
446 push_promise_[":scheme"] = "https";
447
Kenichi Ishibashif8634ab2021-03-16 23:41:28448 promised_response_[":status"] = "200";
ckrasic3865ee0f2016-02-29 22:04:56449 promised_response_[":version"] = "HTTP/1.1";
450 promised_response_["content-type"] = "text/plain";
451
David Schinazi3f7465c2019-07-12 01:57:05452 promise_url_ =
453 quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
[email protected]6cca996b2013-01-25 07:43:36454 }
455
bnc614a92d32016-04-04 13:56:07456 void SetRequest(const string& method,
457 const string& path,
[email protected]1e960032013-12-20 19:00:20458 RequestPriority priority) {
rchcd379012017-04-12 21:53:32459 request_headers_ = client_maker_.GetRequestHeaders(method, "https", path);
[email protected]6cca996b2013-01-25 07:43:36460 }
461
bnc614a92d32016-04-04 13:56:07462 void SetResponse(const string& status, const string& body) {
alyssar2adf3ac2016-05-03 17:12:58463 response_headers_ = server_maker_.GetResponseHeaders(status);
[email protected]92bf17c2014-03-03 21:14:03464 response_data_ = body;
[email protected]6cca996b2013-01-25 07:43:36465 }
[email protected]f702d572012-12-04 15:56:20466
Ryan Hamilton8d9ee76e2018-05-29 23:52:52467 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientDataPacket(
Fan Yangac867502019-01-28 21:10:23468 uint64_t packet_number,
[email protected]e8ff26842013-03-22 21:02:05469 bool should_include_version,
[email protected]f702d572012-12-04 15:56:20470 bool fin,
Victor Vasiliev47ecb6a2020-10-14 17:22:10471 absl::string_view data) {
Ryan Hamilton7505eb92019-06-08 00:22:17472 return client_maker_.MakeDataPacket(packet_number, stream_id_,
473 should_include_version, fin, data);
alyssar2adf3ac2016-05-03 17:12:58474 }
475
Ryan Hamilton8d9ee76e2018-05-29 23:52:52476 std::unique_ptr<quic::QuicReceivedPacket> ConstructServerDataPacket(
Fan Yangac867502019-01-28 21:10:23477 uint64_t packet_number,
alyssar2adf3ac2016-05-03 17:12:58478 bool should_include_version,
479 bool fin,
Victor Vasiliev47ecb6a2020-10-14 17:22:10480 absl::string_view data) {
Ryan Hamilton7505eb92019-06-08 00:22:17481 return server_maker_.MakeDataPacket(packet_number, stream_id_,
482 should_include_version, fin, data);
ckrasic3865ee0f2016-02-29 22:04:56483 }
484
Ryan Hamilton8d9ee76e2018-05-29 23:52:52485 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23486 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52487 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56488 bool should_include_version,
489 bool fin,
490 RequestPriority request_priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02491 size_t* spdy_headers_frame_length) {
Yixin Wang7a3f1b8d2018-01-17 21:40:48492 return InnerConstructRequestHeadersPacket(
493 packet_number, stream_id, should_include_version, fin, request_priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02494 0, spdy_headers_frame_length);
Yixin Wang7a3f1b8d2018-01-17 21:40:48495 }
496
Ryan Hamilton8d9ee76e2018-05-29 23:52:52497 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23498 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52499 quic::QuicStreamId stream_id,
Yixin Wang7a3f1b8d2018-01-17 21:40:48500 bool should_include_version,
501 bool fin,
502 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52503 quic::QuicStreamId parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02504 size_t* spdy_headers_frame_length) {
Ryan Hamilton0239aac2018-05-19 00:03:13505 spdy::SpdyPriority priority =
ckrasic3865ee0f2016-02-29 22:04:56506 ConvertRequestPriorityToQuicPriority(request_priority);
alyssar2adf3ac2016-05-03 17:12:58507 return client_maker_.MakeRequestHeadersPacket(
ckrasic3865ee0f2016-02-29 22:04:56508 packet_number, stream_id, should_include_version, fin, priority,
Yixin Wang7a3f1b8d2018-01-17 21:40:48509 std::move(request_headers_), parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02510 spdy_headers_frame_length);
[email protected]f702d572012-12-04 15:56:20511 }
512
Ryan Hamilton8d9ee76e2018-05-29 23:52:52513 std::unique_ptr<quic::QuicReceivedPacket>
Yixin Wange7ecc472018-03-06 19:00:25514 ConstructRequestHeadersAndDataFramesPacket(
Fan Yangac867502019-01-28 21:10:23515 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52516 quic::QuicStreamId stream_id,
Yixin Wange7ecc472018-03-06 19:00:25517 bool should_include_version,
518 bool fin,
519 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52520 quic::QuicStreamId parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25521 size_t* spdy_headers_frame_length,
522 const std::vector<std::string>& data_writes) {
Ryan Hamilton0239aac2018-05-19 00:03:13523 spdy::SpdyPriority priority =
Yixin Wange7ecc472018-03-06 19:00:25524 ConvertRequestPriorityToQuicPriority(request_priority);
525 return client_maker_.MakeRequestHeadersAndMultipleDataFramesPacket(
526 packet_number, stream_id, should_include_version, fin, priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02527 std::move(request_headers_), parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25528 spdy_headers_frame_length, data_writes);
529 }
530
Ryan Hamilton8d9ee76e2018-05-29 23:52:52531 std::unique_ptr<quic::QuicReceivedPacket> ConstructRequestAndRstPacket(
Fan Yangac867502019-01-28 21:10:23532 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52533 quic::QuicStreamId stream_id,
Yixin Wange7ecc472018-03-06 19:00:25534 bool should_include_version,
535 bool fin,
536 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52537 quic::QuicStreamId parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25538 size_t* spdy_headers_frame_length,
Ryan Hamiltonb5d4c5a2019-06-21 22:08:41539 quic::QuicRstStreamErrorCode error_code) {
Ryan Hamilton0239aac2018-05-19 00:03:13540 spdy::SpdyPriority priority =
Yixin Wange7ecc472018-03-06 19:00:25541 ConvertRequestPriorityToQuicPriority(request_priority);
542 return client_maker_.MakeRequestHeadersAndRstPacket(
543 packet_number, stream_id, should_include_version, fin, priority,
544 std::move(request_headers_), parent_stream_id,
Ryan Hamiltonb5d4c5a2019-06-21 22:08:41545 spdy_headers_frame_length, error_code);
Yixin Wange7ecc472018-03-06 19:00:25546 }
547
Ryan Hamilton8d9ee76e2018-05-29 23:52:52548 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructResponseHeadersPacket(
Fan Yangac867502019-01-28 21:10:23549 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52550 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56551 bool fin,
552 size_t* spdy_headers_frame_length) {
alyssar2adf3ac2016-05-03 17:12:58553 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26554 packet_number, stream_id, !kIncludeVersion, fin,
Ryan Hamilton0d65a8c2019-06-07 00:46:02555 std::move(response_headers_), spdy_headers_frame_length);
[email protected]1e960032013-12-20 19:00:20556 }
557
Ryan Hamilton8d9ee76e2018-05-29 23:52:52558 std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseHeadersPacket(
Fan Yangac867502019-01-28 21:10:23559 uint64_t packet_number,
sclittlec4dc1a32015-09-24 00:15:45560 bool fin,
561 size_t* spdy_headers_frame_length) {
ckrasic3865ee0f2016-02-29 22:04:56562 return InnerConstructResponseHeadersPacket(packet_number, stream_id_, fin,
563 spdy_headers_frame_length);
[email protected]1e960032013-12-20 19:00:20564 }
565
Ryan Hamilton8d9ee76e2018-05-29 23:52:52566 std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseTrailersPacket(
Fan Yangac867502019-01-28 21:10:23567 uint64_t packet_number,
xunjieli34291fe12016-03-02 13:58:38568 bool fin,
Bence Béky4c325e52020-10-22 20:48:01569 spdy::Http2HeaderBlock trailers,
Ryan Hamilton0d65a8c2019-06-07 00:46:02570 size_t* spdy_headers_frame_length) {
alyssar2adf3ac2016-05-03 17:12:58571 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26572 packet_number, stream_id_, !kIncludeVersion, fin, std::move(trailers),
Ryan Hamilton0d65a8c2019-06-07 00:46:02573 spdy_headers_frame_length);
xunjieli34291fe12016-03-02 13:58:38574 }
575
Ryan Hamilton8d9ee76e2018-05-29 23:52:52576 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientRstStreamErrorPacket(
Fan Yangac867502019-01-28 21:10:23577 uint64_t packet_number,
maksim.sisov84e20c92016-06-23 08:49:34578 bool include_version) {
579 return client_maker_.MakeRstPacket(packet_number, include_version,
580 stream_id_,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52581 quic::QUIC_ERROR_PROCESSING_STREAM);
maksim.sisov84e20c92016-06-23 08:49:34582 }
583
Ryan Hamilton8d9ee76e2018-05-29 23:52:52584 std::unique_ptr<quic::QuicReceivedPacket> ConstructAckAndRstStreamPacket(
Fan Yangac867502019-01-28 21:10:23585 uint64_t packet_number) {
Renjie Tangcd594f32020-07-11 20:18:34586 return client_maker_.MakeAckAndRstPacket(packet_number, !kIncludeVersion,
587 stream_id_,
588 quic::QUIC_STREAM_CANCELLED, 2, 1);
[email protected]c5e1aca2014-01-30 04:03:04589 }
590
Ryan Hamilton8d9ee76e2018-05-29 23:52:52591 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientAckPacket(
Fan Yangac867502019-01-28 21:10:23592 uint64_t packet_number,
593 uint64_t largest_received,
Renjie Tangcd594f32020-07-11 20:18:34594 uint64_t smallest_received) {
alyssar2adf3ac2016-05-03 17:12:58595 return client_maker_.MakeAckPacket(packet_number, largest_received,
Renjie Tangcd594f32020-07-11 20:18:34596 smallest_received);
alyssar2adf3ac2016-05-03 17:12:58597 }
598
Ryan Hamilton8d9ee76e2018-05-29 23:52:52599 std::unique_ptr<quic::QuicReceivedPacket> ConstructServerAckPacket(
Fan Yangac867502019-01-28 21:10:23600 uint64_t packet_number,
601 uint64_t largest_received,
602 uint64_t smallest_received,
603 uint64_t least_unacked) {
alyssar2adf3ac2016-05-03 17:12:58604 return server_maker_.MakeAckPacket(packet_number, largest_received,
Bence Béky7a45d4d2020-05-08 01:59:23605 smallest_received, least_unacked);
[email protected]63534512012-12-23 18:49:00606 }
607
Ryan Hamilton0d65a8c2019-06-07 00:46:02608 std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket() {
609 return client_maker_.MakeInitialSettingsPacket(1);
fayang3bcb8b502016-12-07 21:44:37610 }
611
Renjie Tangaadb84b2019-08-31 01:00:23612 std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket(
613 int packet_number) {
614 return client_maker_.MakeInitialSettingsPacket(packet_number);
615 }
616
Victor Vasiliev076657c2019-03-12 02:46:43617 std::string ConstructDataHeader(size_t body_len) {
Nick Harperc6cb7a612020-02-24 20:03:32618 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:41619 return "";
620 }
Renjief49758b2019-01-11 23:32:41621 std::unique_ptr<char[]> buffer;
Victor Vasiliev55d997922019-10-31 19:40:57622 auto header_length =
623 quic::HttpEncoder::SerializeDataFrameHeader(body_len, &buffer);
Victor Vasiliev076657c2019-03-12 02:46:43624 return std::string(buffer.get(), header_length);
Renjief49758b2019-01-11 23:32:41625 }
626
Ryan Hamilton8d9ee76e2018-05-29 23:52:52627 void ReceivePromise(quic::QuicStreamId id) {
628 auto headers = quic::test::AsHeaderList(push_promise_);
rch08e198572017-05-09 16:56:55629 QuicChromiumClientStream::Handle* stream =
ckrasic3865ee0f2016-02-29 22:04:56630 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
ckrasic32b17dcd2016-10-31 06:15:35631 stream->OnPromiseHeaderList(id, headers.uncompressed_header_bytes(),
632 headers);
ckrasic3865ee0f2016-02-29 22:04:56633 }
634
xunjieli84adaab2016-09-20 01:12:28635 void ExpectLoadTimingValid(const LoadTimingInfo& load_timing_info,
xunjieli100937eb52016-09-15 20:09:37636 bool session_reused) {
637 EXPECT_EQ(session_reused, load_timing_info.socket_reused);
xunjieli84adaab2016-09-20 01:12:28638 if (session_reused) {
639 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
640 } else {
641 ExpectConnectTimingHasTimes(
642 load_timing_info.connect_timing,
643 CONNECT_TIMING_HAS_SSL_TIMES | CONNECT_TIMING_HAS_DNS_TIMES);
644 }
645 ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info);
xunjieli100937eb52016-09-15 20:09:37646 }
647
Fan Yang32c5a112018-12-10 20:06:33648 quic::QuicStreamId GetNthClientInitiatedBidirectionalStreamId(int n) {
Nick Harper23290b82019-05-02 00:02:56649 return quic::test::GetNthClientInitiatedBidirectionalStreamId(
650 version_.transport_version, n);
ckrasicbf2f59c2017-05-04 23:54:36651 }
652
Fan Yang32c5a112018-12-10 20:06:33653 quic::QuicStreamId GetNthServerInitiatedUnidirectionalStreamId(int n) {
Nick Harper23290b82019-05-02 00:02:56654 return quic::test::GetNthServerInitiatedUnidirectionalStreamId(
655 version_.transport_version, n);
ckrasicbf2f59c2017-05-04 23:54:36656 }
657
Ryan Hamiltona1d1f4a2019-06-26 14:43:04658 QuicFlagSaver saver_;
659
Nick Harper23290b82019-05-02 00:02:56660 const quic::ParsedQuicVersion version_;
Yixin Wang079ad542018-01-11 04:06:05661 const bool client_headers_include_h2_stream_dependency_;
662
Matt Muellerd9342e3a2019-11-26 01:41:14663 RecordingBoundTestNetLog net_log_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52664 quic::test::MockSendAlgorithm* send_algorithm_;
[email protected]f702d572012-12-04 15:56:20665 scoped_refptr<TestTaskRunner> runner_;
danakjad1777e2016-04-16 00:56:42666 std::unique_ptr<MockWrite[]> mock_writes_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52667 quic::MockClock clock_;
[email protected]f702d572012-12-04 15:56:20668 TestQuicConnection* connection_;
danakjad1777e2016-04-16 00:56:42669 std::unique_ptr<QuicChromiumConnectionHelper> helper_;
rch16c74d1d2016-04-22 06:14:07670 std::unique_ptr<QuicChromiumAlarmFactory> alarm_factory_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52671 testing::StrictMock<quic::test::MockQuicConnectionVisitor> visitor_;
rch97827ee2017-05-24 23:49:12672 std::unique_ptr<UploadDataStream> upload_data_stream_;
danakjad1777e2016-04-16 00:56:42673 std::unique_ptr<QuicHttpStream> stream_;
[email protected]5db452202014-08-19 05:22:15674 TransportSecurityState transport_security_state_;
danakjad1777e2016-04-16 00:56:42675 std::unique_ptr<QuicChromiumClientSession> session_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52676 quic::QuicCryptoClientConfig crypto_config_;
[email protected]f702d572012-12-04 15:56:20677 TestCompletionCallback callback_;
678 HttpRequestInfo request_;
679 HttpRequestHeaders headers_;
680 HttpResponseInfo response_;
681 scoped_refptr<IOBufferWithSize> read_buffer_;
Bence Béky4c325e52020-10-22 20:48:01682 spdy::Http2HeaderBlock request_headers_;
683 spdy::Http2HeaderBlock response_headers_;
bnc614a92d32016-04-04 13:56:07684 string request_data_;
685 string response_data_;
[email protected]f702d572012-12-04 15:56:20686
ckrasic3865ee0f2016-02-29 22:04:56687 // For server push testing
danakjad1777e2016-04-16 00:56:42688 std::unique_ptr<QuicHttpStream> promised_stream_;
Bence Béky4c325e52020-10-22 20:48:01689 spdy::Http2HeaderBlock push_promise_;
690 spdy::Http2HeaderBlock promised_response_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52691 const quic::QuicStreamId promise_id_;
ckrasic3865ee0f2016-02-29 22:04:56692 string promise_url_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52693 const quic::QuicStreamId stream_id_;
ckrasic3865ee0f2016-02-29 22:04:56694
Ryan Hamilton8d9ee76e2018-05-29 23:52:52695 const quic::QuicConnectionId connection_id_;
alyssar2adf3ac2016-05-03 17:12:58696 QuicTestPacketMaker client_maker_;
697 QuicTestPacketMaker server_maker_;
[email protected]f702d572012-12-04 15:56:20698 IPEndPoint self_addr_;
699 IPEndPoint peer_addr_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52700 quic::test::MockRandom random_generator_;
rch03b7a202016-02-05 00:54:20701 ProofVerifyDetailsChromium verify_details_;
[email protected]e8ff26842013-03-22 21:02:05702 MockCryptoClientStreamFactory crypto_client_stream_factory_;
danakjad1777e2016-04-16 00:56:42703 std::unique_ptr<StaticSocketDataProvider> socket_data_;
Ryan Hamilton0d65a8c2019-06-07 00:46:02704 QuicPacketPrinter printer_;
[email protected]f702d572012-12-04 15:56:20705 std::vector<PacketToWrite> writes_;
Bence Béky6e243aa2019-12-13 19:01:07706 quic::test::NoopQpackStreamSenderDelegate noop_qpack_stream_sender_delegate_;
[email protected]f702d572012-12-04 15:56:20707};
708
David Schinazi09e9a6012019-10-03 17:37:57709INSTANTIATE_TEST_SUITE_P(VersionIncludeStreamDependencySequence,
710 QuicHttpStreamTest,
711 ::testing::ValuesIn(GetTestParams()),
712 ::testing::PrintToStringParamName());
[email protected]1e960032013-12-20 19:00:20713
714TEST_P(QuicHttpStreamTest, RenewStreamForAuth) {
[email protected]ed3fc15d2013-03-08 18:37:44715 Initialize();
rtennetibe635732014-10-02 22:51:42716 EXPECT_EQ(nullptr, stream_->RenewStreamForAuth());
[email protected]f702d572012-12-04 15:56:20717}
718
mmenkebd84c392015-09-02 14:12:34719TEST_P(QuicHttpStreamTest, CanReuseConnection) {
[email protected]ed3fc15d2013-03-08 18:37:44720 Initialize();
mmenkebd84c392015-09-02 14:12:34721 EXPECT_FALSE(stream_->CanReuseConnection());
[email protected]f702d572012-12-04 15:56:20722}
723
jri231c2972016-03-08 19:50:11724TEST_P(QuicHttpStreamTest, DisableConnectionMigrationForStream) {
Zhongyi Shibb28b1f2018-07-18 02:41:26725 request_.load_flags |= LOAD_DISABLE_CONNECTION_MIGRATION_TO_CELLULAR;
jri231c2972016-03-08 19:50:11726 Initialize();
xunjieli5fafe142016-03-23 23:32:54727 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27728 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:54729 net_log_.bound(), callback_.callback()));
rch08e198572017-05-09 16:56:55730 QuicChromiumClientStream::Handle* client_stream =
jri231c2972016-03-08 19:50:11731 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
Zhongyi Shibb28b1f2018-07-18 02:41:26732 EXPECT_FALSE(client_stream->can_migrate_to_cellular_network());
jri231c2972016-03-08 19:50:11733}
734
[email protected]1e960032013-12-20 19:00:20735TEST_P(QuicHttpStreamTest, GetRequest) {
736 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:45737 size_t spdy_request_header_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:23738 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:25739 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:23740 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:37741 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23742 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
743 kIncludeVersion, kFin, DEFAULT_PRIORITY,
744 &spdy_request_header_frame_length));
fayang3bcb8b502016-12-07 21:44:37745
[email protected]f702d572012-12-04 15:56:20746 Initialize();
747
748 request_.method = "GET";
rchcd379012017-04-12 21:53:32749 request_.url = GURL("https://www.example.org/");
[email protected]f702d572012-12-04 15:56:20750
xunjieli100937eb52016-09-15 20:09:37751 // Make sure getting load timing from the stream early does not crash.
752 LoadTimingInfo load_timing_info;
753 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
754
xunjieli5fafe142016-03-23 23:32:54755 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27756 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:54757 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:02758 EXPECT_EQ(OK,
759 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20760
761 // Ack the request.
Renjie90e808e2019-01-24 07:24:04762 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]f702d572012-12-04 15:56:20763
robpercival214763f2016-07-01 23:27:01764 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
765 IsError(ERR_IO_PENDING));
[email protected]f702d572012-12-04 15:56:20766
Kenichi Ishibashif8634ab2021-03-16 23:41:28767 SetResponse("404", string());
sclittlec4dc1a32015-09-24 00:15:45768 size_t spdy_response_header_frame_length;
769 ProcessPacket(ConstructResponseHeadersPacket(
770 2, kFin, &spdy_response_header_frame_length));
[email protected]f702d572012-12-04 15:56:20771
772 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:01773 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]cadac622013-06-11 16:46:36774 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:20775 EXPECT_EQ(404, response_.headers->response_code());
776 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
[email protected]6ed67432014-06-24 01:53:53777 EXPECT_FALSE(response_.response_time.is_null());
778 EXPECT_FALSE(response_.request_time.is_null());
[email protected]f702d572012-12-04 15:56:20779
780 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:02781 EXPECT_EQ(0,
782 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
783 callback_.callback()));
[email protected]f702d572012-12-04 15:56:20784 EXPECT_TRUE(stream_->IsResponseBodyComplete());
785 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:10786
xunjieli100937eb52016-09-15 20:09:37787 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
xunjieli84adaab2016-09-20 01:12:28788 ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
xunjieli100937eb52016-09-15 20:09:37789
sclittle1edeeb22015-09-02 20:46:10790 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:45791 // headers and payload.
792 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
793 stream_->GetTotalSentBytes());
794 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length),
795 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:20796}
797
xunjieli100937eb52016-09-15 20:09:37798TEST_P(QuicHttpStreamTest, LoadTimingTwoRequests) {
799 SetRequest("GET", "/", DEFAULT_PRIORITY);
800 size_t spdy_request_header_frame_length;
801
Renjie Tangaadb84b2019-08-31 01:00:23802 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:25803 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:23804 AddWrite(ConstructInitialSettingsPacket(packet_number++));
xunjieli100937eb52016-09-15 20:09:37805 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23806 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
807 kIncludeVersion, kFin, DEFAULT_PRIORITY,
808 &spdy_request_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37809
810 // SetRequest() again for second request as |request_headers_| was moved.
811 SetRequest("GET", "/", DEFAULT_PRIORITY);
812 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23813 packet_number++, GetNthClientInitiatedBidirectionalStreamId(1),
814 kIncludeVersion, kFin, DEFAULT_PRIORITY,
815 GetNthClientInitiatedBidirectionalStreamId(0),
Ryan Hamilton0d65a8c2019-06-07 00:46:02816 &spdy_request_header_frame_length));
Renjie Tangcd594f32020-07-11 20:18:34817 AddWrite(
818 ConstructClientAckPacket(packet_number++, 3, 1)); // Ack the responses.
xunjieli100937eb52016-09-15 20:09:37819
820 Initialize();
821
822 request_.method = "GET";
rchcd379012017-04-12 21:53:32823 request_.url = GURL("https://www.example.org/");
xunjieli100937eb52016-09-15 20:09:37824 // Start first request.
825 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27826 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli100937eb52016-09-15 20:09:37827 net_log_.bound(), callback_.callback()));
828 EXPECT_EQ(OK,
829 stream_->SendRequest(headers_, &response_, callback_.callback()));
830
831 // Start a second request.
Ryan Hamilton6c2a2a82017-12-15 02:06:28832 QuicHttpStream stream2(
Cammie Smith Barnes0f38aff2021-03-02 23:14:35833 session_->CreateHandle(HostPortPair("www.example.org", 443)),
834 {} /* dns_aliases */);
xunjieli100937eb52016-09-15 20:09:37835 TestCompletionCallback callback2;
836 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27837 stream2.InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli100937eb52016-09-15 20:09:37838 net_log_.bound(), callback2.callback()));
839 EXPECT_EQ(OK,
840 stream2.SendRequest(headers_, &response_, callback2.callback()));
841
842 // Ack both requests.
Renjie90e808e2019-01-24 07:24:04843 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
xunjieli100937eb52016-09-15 20:09:37844
845 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
846 IsError(ERR_IO_PENDING));
847 size_t spdy_response_header_frame_length;
Kenichi Ishibashif8634ab2021-03-16 23:41:28848 SetResponse("200", string());
xunjieli100937eb52016-09-15 20:09:37849 ProcessPacket(InnerConstructResponseHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33850 2, GetNthClientInitiatedBidirectionalStreamId(0), kFin,
ckrasicbf2f59c2017-05-04 23:54:36851 &spdy_response_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37852
853 // Now that the headers have been processed, the callback will return.
854 EXPECT_THAT(callback_.WaitForResult(), IsOk());
855 EXPECT_EQ(200, response_.headers->response_code());
856
857 // There is no body, so this should return immediately.
858 EXPECT_EQ(0,
859 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
860 callback_.callback()));
861 EXPECT_TRUE(stream_->IsResponseBodyComplete());
862
863 LoadTimingInfo load_timing_info;
864 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
xunjieli84adaab2016-09-20 01:12:28865 ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
xunjieli100937eb52016-09-15 20:09:37866
867 // SetResponse() again for second request as |response_headers_| was moved.
Kenichi Ishibashif8634ab2021-03-16 23:41:28868 SetResponse("200", string());
xunjieli100937eb52016-09-15 20:09:37869 EXPECT_THAT(stream2.ReadResponseHeaders(callback2.callback()),
870 IsError(ERR_IO_PENDING));
871
872 ProcessPacket(InnerConstructResponseHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33873 3, GetNthClientInitiatedBidirectionalStreamId(1), kFin,
ckrasicbf2f59c2017-05-04 23:54:36874 &spdy_response_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37875
876 EXPECT_THAT(callback2.WaitForResult(), IsOk());
877
878 // There is no body, so this should return immediately.
879 EXPECT_EQ(0,
880 stream2.ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
881 callback2.callback()));
882 EXPECT_TRUE(stream2.IsResponseBodyComplete());
883
884 LoadTimingInfo load_timing_info2;
885 EXPECT_TRUE(stream2.GetLoadTimingInfo(&load_timing_info2));
xunjieli84adaab2016-09-20 01:12:28886 ExpectLoadTimingValid(load_timing_info2, /*session_reused=*/true);
xunjieli100937eb52016-09-15 20:09:37887}
888
xunjieli34291fe12016-03-02 13:58:38889// QuicHttpStream does not currently support trailers. It should ignore
890// trailers upon receiving them.
891TEST_P(QuicHttpStreamTest, GetRequestWithTrailers) {
892 SetRequest("GET", "/", DEFAULT_PRIORITY);
893 size_t spdy_request_header_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:23894 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:25895 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:23896 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:37897 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23898 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
899 kIncludeVersion, kFin, DEFAULT_PRIORITY,
900 &spdy_request_header_frame_length));
Renjie Tangcd594f32020-07-11 20:18:34901 AddWrite(
902 ConstructClientAckPacket(packet_number++, 3, 1)); // Ack the data packet.
xunjieli34291fe12016-03-02 13:58:38903
904 Initialize();
905
906 request_.method = "GET";
rchcd379012017-04-12 21:53:32907 request_.url = GURL("https://www.example.org/");
xunjieli34291fe12016-03-02 13:58:38908
xunjieli5fafe142016-03-23 23:32:54909 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27910 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:54911 net_log_.bound(), callback_.callback()));
912
xunjieli34291fe12016-03-02 13:58:38913 EXPECT_EQ(OK,
914 stream_->SendRequest(headers_, &response_, callback_.callback()));
xunjieli34291fe12016-03-02 13:58:38915 // Ack the request.
Renjie90e808e2019-01-24 07:24:04916 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
xunjieli34291fe12016-03-02 13:58:38917
robpercival214763f2016-07-01 23:27:01918 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
919 IsError(ERR_IO_PENDING));
xunjieli34291fe12016-03-02 13:58:38920
Kenichi Ishibashif8634ab2021-03-16 23:41:28921 SetResponse("200", string());
xunjieli34291fe12016-03-02 13:58:38922
923 // Send the response headers.
924 size_t spdy_response_header_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:02925 ProcessPacket(ConstructResponseHeadersPacket(
926 2, !kFin, &spdy_response_header_frame_length));
xunjieli34291fe12016-03-02 13:58:38927 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:01928 EXPECT_THAT(callback_.WaitForResult(), IsOk());
xunjieli34291fe12016-03-02 13:58:38929 ASSERT_TRUE(response_.headers.get());
930 EXPECT_EQ(200, response_.headers->response_code());
931 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
932 EXPECT_FALSE(response_.response_time.is_null());
933 EXPECT_FALSE(response_.request_time.is_null());
934
935 // Send the response body.
936 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:43937 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:17938 ProcessPacket(
939 ConstructServerDataPacket(3, false, !kFin, header + kResponseBody));
Bence Béky4c325e52020-10-22 20:48:01940 spdy::Http2HeaderBlock trailers;
xunjieli34291fe12016-03-02 13:58:38941 size_t spdy_trailers_frame_length;
942 trailers["foo"] = "bar";
Victor Vasiliev7da08172019-10-14 06:04:25943 if (!quic::VersionUsesHttp3(version_.transport_version)) {
Ryan Hamiltona1d1f4a2019-06-26 14:43:04944 trailers[quic::kFinalOffsetHeaderKey] =
945 base::NumberToString(strlen(kResponseBody) + header.length());
946 }
Ryan Hamilton0d65a8c2019-06-07 00:46:02947 ProcessPacket(ConstructResponseTrailersPacket(4, kFin, std::move(trailers),
948 &spdy_trailers_frame_length));
xunjieli34291fe12016-03-02 13:58:38949
950 // Make sure trailers are processed.
fdoray92e35a72016-06-10 15:54:55951 base::RunLoop().RunUntilIdle();
xunjieli34291fe12016-03-02 13:58:38952
953 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
954 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
955 callback_.callback()));
956 EXPECT_TRUE(stream_->IsResponseBodyComplete());
957
958 EXPECT_EQ(OK,
959 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
960 callback_.callback()));
961
962 EXPECT_TRUE(stream_->IsResponseBodyComplete());
963 EXPECT_TRUE(AtEof());
964
965 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
966 // headers and payload.
967 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
968 stream_->GetTotalSentBytes());
Renjief49758b2019-01-11 23:32:41969 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length +
970 strlen(kResponseBody) + header.length() +
971 +spdy_trailers_frame_length),
972 stream_->GetTotalReceivedBytes());
xunjieli5fafe142016-03-23 23:32:54973 // Check that NetLog was filled as expected.
Eric Roman79cc7552019-07-19 02:17:54974 auto entries = net_log_.GetEntries();
xunjieli5fafe142016-03-23 23:32:54975 size_t pos = ExpectLogContainsSomewhere(
976 entries, /*min_offset=*/0,
mikecirone8b85c432016-09-08 19:11:00977 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
978 NetLogEventPhase::NONE);
xunjieli5fafe142016-03-23 23:32:54979 pos = ExpectLogContainsSomewhere(
980 entries, /*min_offset=*/pos,
mikecirone8b85c432016-09-08 19:11:00981 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
982 NetLogEventPhase::NONE);
xunjieli5fafe142016-03-23 23:32:54983 ExpectLogContainsSomewhere(
984 entries, /*min_offset=*/pos,
mikecirone8b85c432016-09-08 19:11:00985 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
986 NetLogEventPhase::NONE);
xunjieli34291fe12016-03-02 13:58:38987}
988
Bence Béky6c2c78f2020-08-28 16:49:06989TEST_P(QuicHttpStreamTest, ElideHeadersInNetLog) {
990 Initialize();
991
992 // QuicHttp3Logger is only used with HTTP/3.
993 if (!VersionUsesHttp3(version_.transport_version)) {
994 return;
995 }
996
997 net_log_.SetObserverCaptureMode(NetLogCaptureMode::kDefault);
998
Bence Békye0d3747d2020-08-28 23:16:40999 // Send first request.
Bence Béky6c2c78f2020-08-28 16:49:061000 SetRequest("GET", "/", DEFAULT_PRIORITY);
1001 request_.method = "GET";
1002 request_.url = GURL("https://www.example.org/");
1003 headers_.SetHeader(HttpRequestHeaders::kCookie, "secret");
1004
1005 size_t spdy_request_header_frame_length;
Bence Békye0d3747d2020-08-28 23:16:401006 int outgoing_packet_number = 1;
1007 AddWrite(ConstructInitialSettingsPacket(outgoing_packet_number++));
Bence Béky6c2c78f2020-08-28 16:49:061008 AddWrite(InnerConstructRequestHeadersPacket(
Bence Békye0d3747d2020-08-28 23:16:401009 outgoing_packet_number++, stream_id_, kIncludeVersion, kFin,
1010 DEFAULT_PRIORITY, &spdy_request_header_frame_length));
Bence Béky6c2c78f2020-08-28 16:49:061011
1012 EXPECT_THAT(stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
1013 net_log_.bound(), callback_.callback()),
1014 IsOk());
1015 EXPECT_THAT(stream_->SendRequest(headers_, &response_, callback_.callback()),
1016 IsOk());
Bence Békye0d3747d2020-08-28 23:16:401017 int incoming_packet_number = 1;
1018 ProcessPacket(ConstructServerAckPacket(incoming_packet_number++, 1, 1,
1019 1)); // Ack the request.
Bence Béky6c2c78f2020-08-28 16:49:061020
Bence Békye0d3747d2020-08-28 23:16:401021 // Process first response.
Kenichi Ishibashif8634ab2021-03-16 23:41:281022 SetResponse("200", string());
Bence Béky6c2c78f2020-08-28 16:49:061023 response_headers_["set-cookie"] = "secret";
1024 size_t spdy_response_header_frame_length;
1025 ProcessPacket(ConstructResponseHeadersPacket(
Bence Békye0d3747d2020-08-28 23:16:401026 incoming_packet_number++, kFin, &spdy_response_header_frame_length));
Bence Béky6c2c78f2020-08-28 16:49:061027 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
Bence Béky6c2c78f2020-08-28 16:49:061028
1029 ASSERT_TRUE(response_.headers.get());
1030 EXPECT_EQ(200, response_.headers->response_code());
1031 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1032 EXPECT_TRUE(response_.headers->HasHeaderValue("set-cookie", "secret"));
1033
Bence Békye0d3747d2020-08-28 23:16:401034 net_log_.SetObserverCaptureMode(NetLogCaptureMode::kIncludeSensitive);
Bence Béky6c2c78f2020-08-28 16:49:061035
Bence Békye0d3747d2020-08-28 23:16:401036 // Send second request.
1037 quic::QuicStreamId stream_id = GetNthClientInitiatedBidirectionalStreamId(1);
1038 request_.url = GURL("https://www.example.org/foo");
Bence Béky6c2c78f2020-08-28 16:49:061039
Bence Békye0d3747d2020-08-28 23:16:401040 AddWrite(InnerConstructRequestHeadersPacket(
1041 outgoing_packet_number++, stream_id, kIncludeVersion, kFin,
1042 DEFAULT_PRIORITY, &spdy_request_header_frame_length));
Bence Béky6c2c78f2020-08-28 16:49:061043
Bence Békye0d3747d2020-08-28 23:16:401044 auto stream = std::make_unique<QuicHttpStream>(
Cammie Smith Barnes0f38aff2021-03-02 23:14:351045 session_->CreateHandle(HostPortPair("www.example.org/foo", 443)),
1046 std::vector<std::string>() /* dns_aliases */);
Bence Békye0d3747d2020-08-28 23:16:401047 EXPECT_THAT(stream->InitializeStream(&request_, true, DEFAULT_PRIORITY,
1048 net_log_.bound(), callback_.callback()),
1049 IsOk());
1050 EXPECT_THAT(stream->SendRequest(headers_, &response_, callback_.callback()),
1051 IsOk());
1052 ProcessPacket(ConstructServerAckPacket(incoming_packet_number++, 1, 1,
1053 1)); // Ack the request.
Bence Béky6c2c78f2020-08-28 16:49:061054
Bence Békye0d3747d2020-08-28 23:16:401055 // Process second response.
Kenichi Ishibashif8634ab2021-03-16 23:41:281056 SetResponse("200", string());
Bence Békye0d3747d2020-08-28 23:16:401057 response_headers_["set-cookie"] = "secret";
1058 ProcessPacket(InnerConstructResponseHeadersPacket(
1059 incoming_packet_number++, stream_id, kFin,
1060 &spdy_response_header_frame_length));
1061 EXPECT_THAT(stream->ReadResponseHeaders(callback_.callback()), IsOk());
Bence Béky6c2c78f2020-08-28 16:49:061062
Bence Békye0d3747d2020-08-28 23:16:401063 ASSERT_TRUE(response_.headers.get());
1064 EXPECT_EQ(200, response_.headers->response_code());
1065 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1066 EXPECT_TRUE(response_.headers->HasHeaderValue("set-cookie", "secret"));
1067
1068 EXPECT_TRUE(AtEof());
1069
1070 // Check that sensitive header value were stripped
1071 // for the first transaction (logged with NetLogCaptureMode::kDefault)
1072 // but not for the second (logged with NetLogCaptureMode::kIncludeSensitive).
1073 auto entries =
1074 net_log_.GetEntriesWithType(NetLogEventType::HTTP3_HEADERS_SENT);
1075 ASSERT_EQ(2u, entries.size());
1076 EXPECT_TRUE(
1077 CheckHeader(entries[0].params, "cookie", "[6 bytes were stripped]"));
1078 EXPECT_TRUE(CheckHeader(entries[1].params, "cookie", "secret"));
1079
1080 entries = net_log_.GetEntriesWithType(NetLogEventType::HTTP3_HEADERS_DECODED);
1081 ASSERT_EQ(2u, entries.size());
1082 EXPECT_TRUE(
1083 CheckHeader(entries[0].params, "set-cookie", "[6 bytes were stripped]"));
1084 EXPECT_TRUE(CheckHeader(entries[1].params, "set-cookie", "secret"));
Bence Béky6c2c78f2020-08-28 16:49:061085}
1086
[email protected]3e7dca62013-09-10 16:14:231087// Regression test for http://crbug.com/288128
[email protected]1e960032013-12-20 19:00:201088TEST_P(QuicHttpStreamTest, GetRequestLargeResponse) {
1089 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451090 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231091 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251092 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231093 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371094 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231095 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1096 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1097 &spdy_request_headers_frame_length));
[email protected]3e7dca62013-09-10 16:14:231098 Initialize();
1099
1100 request_.method = "GET";
rchcd379012017-04-12 21:53:321101 request_.url = GURL("https://www.example.org/");
[email protected]3e7dca62013-09-10 16:14:231102
xunjieli5fafe142016-03-23 23:32:541103 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271104 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541105 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021106 EXPECT_EQ(OK,
1107 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:231108
1109 // Ack the request.
Renjie90e808e2019-01-24 07:24:041110 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]3e7dca62013-09-10 16:14:231111
robpercival214763f2016-07-01 23:27:011112 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1113 IsError(ERR_IO_PENDING));
[email protected]3e7dca62013-09-10 16:14:231114
Kenichi Ishibashif8634ab2021-03-16 23:41:281115 response_headers_[":status"] = "200";
bnc086b39e12016-06-24 13:05:261116 response_headers_[":version"] = "HTTP/1.1";
1117 response_headers_["content-type"] = "text/plain";
1118 response_headers_["big6"] = string(1000, 'x'); // Lots of x's.
[email protected]3e7dca62013-09-10 16:14:231119
sclittlec4dc1a32015-09-24 00:15:451120 size_t spdy_response_headers_frame_length;
1121 ProcessPacket(ConstructResponseHeadersPacket(
1122 2, kFin, &spdy_response_headers_frame_length));
[email protected]3e7dca62013-09-10 16:14:231123
1124 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:011125 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]3e7dca62013-09-10 16:14:231126 ASSERT_TRUE(response_.headers.get());
1127 EXPECT_EQ(200, response_.headers->response_code());
1128 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1129
1130 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:021131 EXPECT_EQ(0,
1132 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1133 callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:231134 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1135 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101136
1137 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451138 // headers and payload.
1139 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1140 stream_->GetTotalSentBytes());
1141 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length),
1142 stream_->GetTotalReceivedBytes());
[email protected]3e7dca62013-09-10 16:14:231143}
1144
rchf9f103cbc2014-08-30 05:28:041145// Regression test for http://crbug.com/409101
1146TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendRequest) {
1147 SetRequest("GET", "/", DEFAULT_PRIORITY);
1148 Initialize();
1149
1150 request_.method = "GET";
rchcd379012017-04-12 21:53:321151 request_.url = GURL("https://www.example.org/");
rchf9f103cbc2014-08-30 05:28:041152
xunjieli5fafe142016-03-23 23:32:541153 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271154 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541155 net_log_.bound(), callback_.callback()));
rchf9f103cbc2014-08-30 05:28:041156
jri78ec06a2016-03-31 18:19:401157 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521158 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rchf9f103cbc2014-08-30 05:28:041159
1160 EXPECT_EQ(ERR_CONNECTION_CLOSED,
rjshaded5ced072015-12-18 19:26:021161 stream_->SendRequest(headers_, &response_, callback_.callback()));
sclittle1edeeb22015-09-02 20:46:101162
1163 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1164 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rchf9f103cbc2014-08-30 05:28:041165}
1166
rch03b7a202016-02-05 00:54:201167// Regression test for http://crbug.com/584441
1168TEST_P(QuicHttpStreamTest, GetSSLInfoAfterSessionClosed) {
1169 SetRequest("GET", "/", DEFAULT_PRIORITY);
1170 Initialize();
1171
1172 request_.method = "GET";
rchcd379012017-04-12 21:53:321173 request_.url = GURL("https://www.example.org/");
rch03b7a202016-02-05 00:54:201174
xunjieli5fafe142016-03-23 23:32:541175 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271176 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541177 net_log_.bound(), callback_.callback()));
rch03b7a202016-02-05 00:54:201178
1179 SSLInfo ssl_info;
rch11565e02016-02-09 20:13:471180 EXPECT_FALSE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:201181 stream_->GetSSLInfo(&ssl_info);
rch11565e02016-02-09 20:13:471182 EXPECT_TRUE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:201183
jri78ec06a2016-03-31 18:19:401184 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521185 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rch03b7a202016-02-05 00:54:201186
rch11565e02016-02-09 20:13:471187 SSLInfo ssl_info2;
1188 stream_->GetSSLInfo(&ssl_info2);
1189 EXPECT_TRUE(ssl_info2.is_valid());
rch03b7a202016-02-05 00:54:201190}
1191
rchcd379012017-04-12 21:53:321192TEST_P(QuicHttpStreamTest, GetAlternativeService) {
1193 SetRequest("GET", "/", DEFAULT_PRIORITY);
1194 Initialize();
1195
1196 request_.method = "GET";
1197 request_.url = GURL("https://www.example.org/");
1198
1199 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271200 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
rchcd379012017-04-12 21:53:321201 net_log_.bound(), callback_.callback()));
1202
1203 AlternativeService alternative_service;
1204 EXPECT_TRUE(stream_->GetAlternativeService(&alternative_service));
1205 EXPECT_EQ(AlternativeService(kProtoQUIC, "www.example.org", 443),
1206 alternative_service);
1207
1208 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521209 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rchcd379012017-04-12 21:53:321210
1211 AlternativeService alternative_service2;
1212 EXPECT_TRUE(stream_->GetAlternativeService(&alternative_service2));
1213 EXPECT_EQ(AlternativeService(kProtoQUIC, "www.example.org", 443),
1214 alternative_service2);
1215}
1216
zhongyica364fbb2015-12-12 03:39:121217TEST_P(QuicHttpStreamTest, LogGranularQuicConnectionError) {
1218 SetRequest("GET", "/", DEFAULT_PRIORITY);
1219 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231220 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251221 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231222 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371223 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231224 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1225 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1226 &spdy_request_headers_frame_length));
fayang3bcb8b502016-12-07 21:44:371227 AddWrite(ConstructAckAndRstStreamPacket(3));
zhongyica364fbb2015-12-12 03:39:121228 Initialize();
1229
1230 request_.method = "GET";
rchcd379012017-04-12 21:53:321231 request_.url = GURL("https://www.example.org/");
zhongyica364fbb2015-12-12 03:39:121232
xunjieli5fafe142016-03-23 23:32:541233 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271234 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541235 net_log_.bound(), callback_.callback()));
zhongyica364fbb2015-12-12 03:39:121236 EXPECT_EQ(OK,
1237 stream_->SendRequest(headers_, &response_, callback_.callback()));
1238
1239 // Ack the request.
Renjie90e808e2019-01-24 07:24:041240 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011241 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1242 IsError(ERR_IO_PENDING));
zhongyica364fbb2015-12-12 03:39:121243
Ryan Hamilton8d9ee76e2018-05-29 23:52:521244 quic::QuicConnectionCloseFrame frame;
Zhongyi Shica576df2019-04-12 17:43:401245 frame.quic_error_code = quic::QUIC_PEER_GOING_AWAY;
rch1c5b74a2016-06-23 22:10:551246 session_->connection()->OnConnectionCloseFrame(frame);
zhongyica364fbb2015-12-12 03:39:121247
1248 NetErrorDetails details;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521249 EXPECT_EQ(quic::QUIC_NO_ERROR, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121250 stream_->PopulateNetErrorDetails(&details);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521251 EXPECT_EQ(quic::QUIC_PEER_GOING_AWAY, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121252}
1253
Ryan Hamiltone316e482017-08-17 02:48:531254TEST_P(QuicHttpStreamTest, LogGranularQuicErrorIfHandshakeNotConfirmed) {
rch617e0652017-04-26 17:57:511255 // By default the test setup defaults handshake to be confirmed. Manually set
1256 // it to be not confirmed.
rch617e0652017-04-26 17:57:511257 crypto_client_stream_factory_.set_handshake_mode(
Ryan Hamilton9835e662018-08-02 05:36:271258 MockCryptoClientStream::ZERO_RTT);
rch617e0652017-04-26 17:57:511259
zhongyica364fbb2015-12-12 03:39:121260 SetRequest("GET", "/", DEFAULT_PRIORITY);
1261 size_t spdy_request_headers_frame_length;
Michael Warres167db3e2019-03-01 21:38:031262 client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
Nick Harper057264a82019-09-12 23:33:491263 client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
1264 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251265 if (VersionUsesHttp3(version_.transport_version))
Nick Harper057264a82019-09-12 23:33:491266 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371267 AddWrite(InnerConstructRequestHeadersPacket(
Nick Harper057264a82019-09-12 23:33:491268 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1269 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1270 &spdy_request_headers_frame_length));
zhongyica364fbb2015-12-12 03:39:121271 Initialize();
1272
1273 request_.method = "GET";
rchcd379012017-04-12 21:53:321274 request_.url = GURL("https://www.example.org/");
zhongyica364fbb2015-12-12 03:39:121275
xunjieli5fafe142016-03-23 23:32:541276 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271277 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541278 net_log_.bound(), callback_.callback()));
zhongyica364fbb2015-12-12 03:39:121279 EXPECT_EQ(OK,
1280 stream_->SendRequest(headers_, &response_, callback_.callback()));
1281
1282 // Ack the request.
Renjie90e808e2019-01-24 07:24:041283 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011284 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1285 IsError(ERR_IO_PENDING));
zhongyica364fbb2015-12-12 03:39:121286
Ryan Hamilton8d9ee76e2018-05-29 23:52:521287 quic::QuicConnectionCloseFrame frame;
Zhongyi Shica576df2019-04-12 17:43:401288 frame.quic_error_code = quic::QUIC_PEER_GOING_AWAY;
rch1c5b74a2016-06-23 22:10:551289 session_->connection()->OnConnectionCloseFrame(frame);
zhongyica364fbb2015-12-12 03:39:121290
1291 NetErrorDetails details;
zhongyica364fbb2015-12-12 03:39:121292 stream_->PopulateNetErrorDetails(&details);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521293 EXPECT_EQ(quic::QUIC_PEER_GOING_AWAY, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121294}
1295
rch11a114a2014-09-04 23:41:591296// Regression test for http://crbug.com/409871
1297TEST_P(QuicHttpStreamTest, SessionClosedBeforeReadResponseHeaders) {
1298 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451299 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231300 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251301 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231302 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371303 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231304 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1305 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1306 &spdy_request_headers_frame_length));
rch11a114a2014-09-04 23:41:591307 Initialize();
1308
1309 request_.method = "GET";
rchcd379012017-04-12 21:53:321310 request_.url = GURL("https://www.example.org/");
rch11a114a2014-09-04 23:41:591311
xunjieli5fafe142016-03-23 23:32:541312 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271313 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541314 net_log_.bound(), callback_.callback()));
rch11a114a2014-09-04 23:41:591315
rjshaded5ced072015-12-18 19:26:021316 EXPECT_EQ(OK,
1317 stream_->SendRequest(headers_, &response_, callback_.callback()));
rch11a114a2014-09-04 23:41:591318
jri78ec06a2016-03-31 18:19:401319 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521320 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rch11a114a2014-09-04 23:41:591321
1322 EXPECT_NE(OK, stream_->ReadResponseHeaders(callback_.callback()));
sclittle1edeeb22015-09-02 20:46:101323
1324 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451325 // headers and payload.
1326 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1327 stream_->GetTotalSentBytes());
sclittle1edeeb22015-09-02 20:46:101328 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rch11a114a2014-09-04 23:41:591329}
1330
[email protected]1e960032013-12-20 19:00:201331TEST_P(QuicHttpStreamTest, SendPostRequest) {
1332 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451333 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231334 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251335 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231336 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Yixin Wange7ecc472018-03-06 19:00:251337
Victor Vasiliev076657c2019-03-12 02:46:431338 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:321339 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411340 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, {kUploadData}));
Renjief49758b2019-01-11 23:32:411344 } else {
1345 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231346 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1347 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1348 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411349 }
Yixin Wange7ecc472018-03-06 19:00:251350
Renjie Tangcd594f32020-07-11 20:18:341351 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]f702d572012-12-04 15:56:201352
1353 Initialize();
1354
danakjad1777e2016-04-16 00:56:421355 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:191356 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
ricea2deef682016-09-09 08:04:071357 kUploadData, strlen(kUploadData)));
rch97827ee2017-05-24 23:49:121358 upload_data_stream_ =
Jeremy Roman0579ed62017-08-29 15:56:191359 std::make_unique<ElementsUploadDataStream>(std::move(element_readers), 0);
[email protected]f702d572012-12-04 15:56:201360 request_.method = "POST";
rchcd379012017-04-12 21:53:321361 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121362 request_.upload_data_stream = upload_data_stream_.get();
Bence Békyd8a21fc32018-06-27 18:29:581363 ASSERT_THAT(request_.upload_data_stream->Init(CompletionOnceCallback(),
tfarina42834112016-09-22 13:38:201364 NetLogWithSource()),
1365 IsOk());
[email protected]f702d572012-12-04 15:56:201366
xunjieli5fafe142016-03-23 23:32:541367 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271368 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541369 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021370 EXPECT_EQ(OK,
1371 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:201372
1373 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041374 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]f702d572012-12-04 15:56:201375
1376 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281377 SetResponse("200", string());
sclittlec4dc1a32015-09-24 00:15:451378 size_t spdy_response_headers_frame_length;
1379 ProcessPacket(ConstructResponseHeadersPacket(
1380 2, !kFin, &spdy_response_headers_frame_length));
[email protected]f702d572012-12-04 15:56:201381
rchfb47f712017-05-21 03:24:001382 // The headers have already arrived.
1383 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]cadac622013-06-11 16:46:361384 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:201385 EXPECT_EQ(200, response_.headers->response_code());
1386 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1387
1388 // Send the response body.
1389 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431390 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:411391 ProcessPacket(
Ryan Hamilton7505eb92019-06-08 00:22:171392 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
[email protected]f702d572012-12-04 15:56:201393 // Since the body has already arrived, this should return immediately.
1394 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
1395 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1396 callback_.callback()));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291397 EXPECT_EQ(0,
1398 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1399 callback_.callback()));
1400
1401 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1402 EXPECT_TRUE(AtEof());
1403
1404 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
1405 // headers and payload.
1406 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411407 strlen(kUploadData) + header.length()),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291408 stream_->GetTotalSentBytes());
1409 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411410 strlen(kResponseBody) + header2.length()),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291411 stream_->GetTotalReceivedBytes());
1412}
1413
1414TEST_P(QuicHttpStreamTest, SendPostRequestAndReceiveSoloFin) {
1415 SetRequest("POST", "/", DEFAULT_PRIORITY);
1416 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231417 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251418 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231419 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431420 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:321421 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411422 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, {kUploadData}));
Renjief49758b2019-01-11 23:32:411426 } else {
1427 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231428 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1429 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1430 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411431 }
1432
Renjie Tangcd594f32020-07-11 20:18:341433 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291434
1435 Initialize();
1436
1437 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:191438 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
Ryan Hamilton2ef0a9c2017-07-25 03:18:291439 kUploadData, strlen(kUploadData)));
1440 upload_data_stream_ =
Jeremy Roman0579ed62017-08-29 15:56:191441 std::make_unique<ElementsUploadDataStream>(std::move(element_readers), 0);
Ryan Hamilton2ef0a9c2017-07-25 03:18:291442 request_.method = "POST";
1443 request_.url = GURL("https://www.example.org/");
1444 request_.upload_data_stream = upload_data_stream_.get();
Bence Békyd8a21fc32018-06-27 18:29:581445 ASSERT_THAT(request_.upload_data_stream->Init(CompletionOnceCallback(),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291446 NetLogWithSource()),
1447 IsOk());
1448
1449 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271450 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
Ryan Hamilton2ef0a9c2017-07-25 03:18:291451 net_log_.bound(), callback_.callback()));
1452 EXPECT_EQ(OK,
1453 stream_->SendRequest(headers_, &response_, callback_.callback()));
1454
1455 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041456 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291457
1458 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281459 SetResponse("200", string());
Ryan Hamilton2ef0a9c2017-07-25 03:18:291460 size_t spdy_response_headers_frame_length;
1461 ProcessPacket(ConstructResponseHeadersPacket(
1462 2, !kFin, &spdy_response_headers_frame_length));
1463
1464 // The headers have already arrived.
1465 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
1466 ASSERT_TRUE(response_.headers.get());
1467 EXPECT_EQ(200, response_.headers->response_code());
1468 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1469
1470 // Send the response body.
1471 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431472 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:411473 ProcessPacket(
Ryan Hamilton7505eb92019-06-08 00:22:171474 ConstructServerDataPacket(3, false, !kFin, header2 + kResponseBody));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291475 // Since the body has already arrived, this should return immediately.
1476 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
1477 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1478 callback_.callback()));
Ryan Hamilton7505eb92019-06-08 00:22:171479 ProcessPacket(ConstructServerDataPacket(4, false, kFin, ""));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291480 EXPECT_EQ(0,
1481 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1482 callback_.callback()));
[email protected]f702d572012-12-04 15:56:201483
1484 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1485 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101486
1487 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451488 // headers and payload.
1489 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411490 strlen(kUploadData) + header.length()),
sclittle1edeeb22015-09-02 20:46:101491 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451492 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411493 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101494 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:201495}
1496
[email protected]1e960032013-12-20 19:00:201497TEST_P(QuicHttpStreamTest, SendChunkedPostRequest) {
1498 SetRequest("POST", "/", DEFAULT_PRIORITY);
[email protected]c9e49a02013-02-26 05:56:471499 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:451500 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231501 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251502 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231503 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431504 std::string header = ConstructDataHeader(chunk_size);
Nick Harperc6cb7a612020-02-24 20:03:321505 if (version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411506 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231507 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1508 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1509 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjie Tangd5133972019-12-06 00:20:281510 AddWrite(ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin,
1511 {header + kUploadData}));
Renjief49758b2019-01-11 23:32:411512 } else {
1513 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231514 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1515 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1516 &spdy_request_headers_frame_length, {kUploadData}));
1517 AddWrite(ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin,
1518 kUploadData));
Renjief49758b2019-01-11 23:32:411519 }
1520
Renjie Tangcd594f32020-07-11 20:18:341521 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]c9e49a02013-02-26 05:56:471522 Initialize();
1523
Jeremy Roman0579ed62017-08-29 15:56:191524 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121525 auto* chunked_upload_stream =
1526 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1527 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
[email protected]c9e49a02013-02-26 05:56:471528
1529 request_.method = "POST";
rchcd379012017-04-12 21:53:321530 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121531 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071532 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201533 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]c9e49a02013-02-26 05:56:471534
xunjieli5fafe142016-03-23 23:32:541535 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271536 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541537 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021538 ASSERT_EQ(ERR_IO_PENDING,
1539 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]c9e49a02013-02-26 05:56:471540
rch97827ee2017-05-24 23:49:121541 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
robpercival214763f2016-07-01 23:27:011542 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]c9e49a02013-02-26 05:56:471543
1544 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041545 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]c9e49a02013-02-26 05:56:471546
1547 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281548 SetResponse("200", string());
sclittlec4dc1a32015-09-24 00:15:451549 size_t spdy_response_headers_frame_length;
1550 ProcessPacket(ConstructResponseHeadersPacket(
1551 2, !kFin, &spdy_response_headers_frame_length));
[email protected]c9e49a02013-02-26 05:56:471552
rchfb47f712017-05-21 03:24:001553 // The headers have already arrived.
1554 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]cadac622013-06-11 16:46:361555 ASSERT_TRUE(response_.headers.get());
[email protected]c9e49a02013-02-26 05:56:471556 EXPECT_EQ(200, response_.headers->response_code());
1557 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1558
1559 // Send the response body.
1560 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431561 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171562 ProcessPacket(
1563 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
[email protected]c9e49a02013-02-26 05:56:471564
1565 // Since the body has already arrived, this should return immediately.
1566 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1567 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1568 callback_.callback()));
1569
1570 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1571 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101572
1573 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451574 // headers and payload.
1575 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411576 strlen(kUploadData) * 2 + header.length() * 2),
sclittle1edeeb22015-09-02 20:46:101577 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451578 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411579 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101580 stream_->GetTotalReceivedBytes());
[email protected]c9e49a02013-02-26 05:56:471581}
1582
[email protected]16ba7742014-08-22 00:57:251583TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithFinalEmptyDataPacket) {
1584 SetRequest("POST", "/", DEFAULT_PRIORITY);
1585 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:451586 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231587 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251588 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231589 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431590 std::string header = ConstructDataHeader(chunk_size);
Renjief49758b2019-01-11 23:32:411591
Nick Harperc6cb7a612020-02-24 20:03:321592 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411593 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, {kUploadData}));
Renjief49758b2019-01-11 23:32:411597 } else {
1598 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231599 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1600 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1601 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411602 }
Renjie Tangaadb84b2019-08-31 01:00:231603 AddWrite(
1604 ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin, ""));
Renjie Tangcd594f32020-07-11 20:18:341605 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]16ba7742014-08-22 00:57:251606 Initialize();
1607
Jeremy Roman0579ed62017-08-29 15:56:191608 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121609 auto* chunked_upload_stream =
1610 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1611 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
[email protected]16ba7742014-08-22 00:57:251612
1613 request_.method = "POST";
rchcd379012017-04-12 21:53:321614 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121615 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071616 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201617 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]16ba7742014-08-22 00:57:251618
xunjieli5fafe142016-03-23 23:32:541619 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271620 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541621 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021622 ASSERT_EQ(ERR_IO_PENDING,
1623 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251624
rch97827ee2017-05-24 23:49:121625 chunked_upload_stream->AppendData(nullptr, 0, true);
robpercival214763f2016-07-01 23:27:011626 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]16ba7742014-08-22 00:57:251627
Renjie90e808e2019-01-24 07:24:041628 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]16ba7742014-08-22 00:57:251629
1630 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281631 SetResponse("200", string());
sclittlec4dc1a32015-09-24 00:15:451632 size_t spdy_response_headers_frame_length;
1633 ProcessPacket(ConstructResponseHeadersPacket(
1634 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251635
rchfb47f712017-05-21 03:24:001636 // The headers have already arrived.
1637 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]16ba7742014-08-22 00:57:251638 ASSERT_TRUE(response_.headers.get());
1639 EXPECT_EQ(200, response_.headers->response_code());
1640 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1641
1642 // Send the response body.
1643 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431644 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171645 ProcessPacket(
1646 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
[email protected]16ba7742014-08-22 00:57:251647
rchb27683c2015-07-29 23:53:501648 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251649 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1650 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1651 callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251652 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1653 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101654
1655 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451656 // headers and payload.
1657 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411658 strlen(kUploadData) + header.length()),
sclittle1edeeb22015-09-02 20:46:101659 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451660 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411661 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101662 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251663}
1664
1665TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithOneEmptyDataPacket) {
1666 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451667 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231668 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251669 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231670 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371671 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231672 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1673 kIncludeVersion, !kFin, DEFAULT_PRIORITY,
1674 &spdy_request_headers_frame_length));
1675 AddWrite(
1676 ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin, ""));
Renjie Tangcd594f32020-07-11 20:18:341677 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
[email protected]16ba7742014-08-22 00:57:251678 Initialize();
1679
Jeremy Roman0579ed62017-08-29 15:56:191680 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121681 auto* chunked_upload_stream =
1682 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
[email protected]16ba7742014-08-22 00:57:251683
1684 request_.method = "POST";
rchcd379012017-04-12 21:53:321685 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121686 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071687 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201688 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]16ba7742014-08-22 00:57:251689
xunjieli5fafe142016-03-23 23:32:541690 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271691 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541692 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021693 ASSERT_EQ(ERR_IO_PENDING,
1694 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251695
rch97827ee2017-05-24 23:49:121696 chunked_upload_stream->AppendData(nullptr, 0, true);
robpercival214763f2016-07-01 23:27:011697 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]16ba7742014-08-22 00:57:251698
Renjie90e808e2019-01-24 07:24:041699 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]16ba7742014-08-22 00:57:251700
1701 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281702 SetResponse("200", string());
sclittlec4dc1a32015-09-24 00:15:451703 size_t spdy_response_headers_frame_length;
1704 ProcessPacket(ConstructResponseHeadersPacket(
1705 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251706
rchfb47f712017-05-21 03:24:001707 // The headers have already arrived.
1708 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]16ba7742014-08-22 00:57:251709 ASSERT_TRUE(response_.headers.get());
1710 EXPECT_EQ(200, response_.headers->response_code());
1711 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1712
1713 // Send the response body.
1714 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431715 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171716 ProcessPacket(
1717 ConstructServerDataPacket(3, false, kFin, header + kResponseBody));
[email protected]16ba7742014-08-22 00:57:251718
rchb27683c2015-07-29 23:53:501719 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251720 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1721 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1722 callback_.callback()));
1723
1724 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1725 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101726
1727 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451728 // headers and payload.
1729 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1730 stream_->GetTotalSentBytes());
1731 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411732 strlen(kResponseBody) + header.length()),
sclittle1edeeb22015-09-02 20:46:101733 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251734}
1735
Bence Békye3c6f122020-05-08 01:09:471736TEST_P(QuicHttpStreamTest, SendChunkedPostRequestAbortedByResetStream) {
1737 SetRequest("POST", "/", DEFAULT_PRIORITY);
1738 size_t chunk_size = strlen(kUploadData);
1739 size_t spdy_request_headers_frame_length;
1740 int packet_number = 1;
1741
1742 if (version_.UsesHttp3()) {
1743 AddWrite(ConstructInitialSettingsPacket(packet_number++));
1744 }
1745
1746 std::string header = ConstructDataHeader(chunk_size);
1747 if (version_.HasIetfQuicFrames()) {
1748 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1749 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1750 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1751 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjie Tangcd594f32020-07-11 20:18:341752 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
Renjie Tanga35322a2020-12-02 20:12:271753 AddWrite(client_maker_.MakeRstPacket(
1754 packet_number++, true, stream_id_, quic::QUIC_STREAM_NO_ERROR,
Renjie Tangcd594f32020-07-11 20:18:341755 /* include_stop_sending_if_v99 = */ false));
Bence Békye3c6f122020-05-08 01:09:471756 } else {
1757 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1758 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1759 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1760 &spdy_request_headers_frame_length, {kUploadData}));
Renjie Tangcd594f32020-07-11 20:18:341761 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
Bence Békye3c6f122020-05-08 01:09:471762 AddWrite(client_maker_.MakeAckAndRstPacket(
1763 packet_number++,
1764 /* include_version = */ false, stream_id_,
Renjie Tangcd594f32020-07-11 20:18:341765 quic::QUIC_RST_ACKNOWLEDGEMENT, 4, 1,
Bence Békye3c6f122020-05-08 01:09:471766 /* include_stop_sending_if_v99 = */ false));
1767 }
1768
1769 Initialize();
1770
1771 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
1772 auto* chunked_upload_stream =
1773 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1774 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
1775
1776 request_.method = "POST";
1777 request_.url = GURL("https://www.example.org/");
1778 request_.upload_data_stream = upload_data_stream_.get();
1779 ASSERT_THAT(request_.upload_data_stream->Init(
1780 TestCompletionCallback().callback(), NetLogWithSource()),
1781 IsOk());
1782 ASSERT_THAT(stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1783 net_log_.bound(), callback_.callback()),
1784 IsOk());
1785 ASSERT_THAT(stream_->SendRequest(headers_, &response_, callback_.callback()),
1786 IsError(ERR_IO_PENDING));
1787
1788 // Ack both packets in the request.
1789 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
1790
1791 // Send the response headers (but not the body).
Kenichi Ishibashif8634ab2021-03-16 23:41:281792 SetResponse("200", string());
Bence Békye3c6f122020-05-08 01:09:471793 size_t spdy_response_headers_frame_length;
1794 ProcessPacket(ConstructResponseHeadersPacket(
1795 2, !kFin, &spdy_response_headers_frame_length));
1796
1797 // Send the response body.
1798 const char kResponseBody[] = "Hello world!";
1799 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
1800 ProcessPacket(
1801 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
1802
Bence Béky050ec6d2021-02-25 22:07:051803 if (version_.HasIetfQuicFrames()) {
1804 // In IETF QUIC, the server uses a STOP_SENDING frame to notify the client
1805 // that it does not need any further data to fully process the request.
1806 ProcessPacket(server_maker_.MakeStopSendingPacket(
1807 4, /* include_version = */ false, stream_id_,
1808 quic::QUIC_STREAM_NO_ERROR));
1809 } else {
1810 // Server resets stream with H3_NO_ERROR before request body is complete.
1811 ProcessPacket(server_maker_.MakeRstPacket(4, /* include_version = */ false,
1812 stream_id_,
1813 quic::QUIC_STREAM_NO_ERROR));
1814 }
Bence Békye3c6f122020-05-08 01:09:471815
1816 // Finish feeding request body to QuicHttpStream. Data will be discarded.
1817 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1818 EXPECT_THAT(callback_.WaitForResult(), IsOk());
1819
1820 // Verify response.
1821 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
1822 ASSERT_TRUE(response_.headers.get());
1823 EXPECT_EQ(200, response_.headers->response_code());
1824 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1825 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1826 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1827 callback_.callback()));
1828 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1829 EXPECT_TRUE(AtEof());
1830
1831 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
1832 // headers and payload.
1833 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
1834 strlen(kUploadData) + header.length()),
1835 stream_->GetTotalSentBytes());
1836 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1837 strlen(kResponseBody) + header2.length()),
1838 stream_->GetTotalReceivedBytes());
1839}
1840
[email protected]1e960032013-12-20 19:00:201841TEST_P(QuicHttpStreamTest, DestroyedEarly) {
1842 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451843 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231844 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251845 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231846 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371847 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231848 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1849 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1850 &spdy_request_headers_frame_length));
1851 AddWrite(ConstructAckAndRstStreamPacket(packet_number++));
[email protected]63534512012-12-23 18:49:001852 Initialize();
1853
1854 request_.method = "GET";
rchcd379012017-04-12 21:53:321855 request_.url = GURL("https://www.example.org/");
[email protected]63534512012-12-23 18:49:001856
xunjieli5fafe142016-03-23 23:32:541857 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271858 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541859 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021860 EXPECT_EQ(OK,
1861 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]63534512012-12-23 18:49:001862
1863 // Ack the request.
Renjie90e808e2019-01-24 07:24:041864 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
rchfb47f712017-05-21 03:24:001865 EXPECT_THAT(stream_->ReadResponseHeaders(
Yannic Bonenberger3c96beb2019-09-03 20:41:371866 base::BindOnce(&QuicHttpStreamTest::CloseStream,
1867 base::Unretained(this), stream_.get())),
robpercival214763f2016-07-01 23:27:011868 IsError(ERR_IO_PENDING));
[email protected]63534512012-12-23 18:49:001869
1870 // Send the response with a body.
Kenichi Ishibashif8634ab2021-03-16 23:41:281871 SetResponse("404", "hello world!");
[email protected]63534512012-12-23 18:49:001872 // In the course of processing this packet, the QuicHttpStream close itself.
rchfb47f712017-05-21 03:24:001873 size_t response_size = 0;
rch1bcfddf22017-06-03 00:26:291874 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin, &response_size));
[email protected]63534512012-12-23 18:49:001875
fdoray92e35a72016-06-10 15:54:551876 base::RunLoop().RunUntilIdle();
rchb27683c2015-07-29 23:53:501877
[email protected]63534512012-12-23 18:49:001878 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101879
1880 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451881 // headers and payload.
1882 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1883 stream_->GetTotalSentBytes());
rchfb47f712017-05-21 03:24:001884 // The stream was closed after receiving the headers.
1885 EXPECT_EQ(static_cast<int64_t>(response_size),
1886 stream_->GetTotalReceivedBytes());
[email protected]63534512012-12-23 18:49:001887}
1888
[email protected]1e960032013-12-20 19:00:201889TEST_P(QuicHttpStreamTest, Priority) {
1890 SetRequest("GET", "/", MEDIUM);
sclittlec4dc1a32015-09-24 00:15:451891 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231892 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251893 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231894 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371895 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231896 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1897 kIncludeVersion, kFin, MEDIUM, &spdy_request_headers_frame_length));
[email protected]24e5bc52013-09-18 15:36:581898 Initialize();
1899
1900 request_.method = "GET";
rchcd379012017-04-12 21:53:321901 request_.url = GURL("https://www.example.org/");
[email protected]24e5bc52013-09-18 15:36:581902
Steven Valdezb4ff0412018-01-18 22:39:271903 EXPECT_EQ(OK,
1904 stream_->InitializeStream(&request_, true, MEDIUM, net_log_.bound(),
1905 callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581906
rjshaded5ced072015-12-18 19:26:021907 EXPECT_EQ(OK,
1908 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581909
[email protected]24e5bc52013-09-18 15:36:581910 // Ack the request.
Renjie90e808e2019-01-24 07:24:041911 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011912 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1913 IsError(ERR_IO_PENDING));
[email protected]24e5bc52013-09-18 15:36:581914
1915 // Send the response with a body.
Kenichi Ishibashif8634ab2021-03-16 23:41:281916 SetResponse("404", "hello world!");
rchfb47f712017-05-21 03:24:001917 size_t response_size = 0;
1918 ProcessPacket(ConstructResponseHeadersPacket(2, kFin, &response_size));
[email protected]24e5bc52013-09-18 15:36:581919
rchfb47f712017-05-21 03:24:001920 EXPECT_EQ(OK, callback_.WaitForResult());
rchb27683c2015-07-29 23:53:501921
[email protected]24e5bc52013-09-18 15:36:581922 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101923
1924 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451925 // headers and payload.
1926 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1927 stream_->GetTotalSentBytes());
rchfb47f712017-05-21 03:24:001928 EXPECT_EQ(static_cast<int64_t>(response_size),
1929 stream_->GetTotalReceivedBytes());
[email protected]24e5bc52013-09-18 15:36:581930}
1931
xunjieli8dff50b2016-07-22 14:19:061932TEST_P(QuicHttpStreamTest, SessionClosedDuringDoLoop) {
1933 SetRequest("POST", "/", DEFAULT_PRIORITY);
1934 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231935 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251936 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231937 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431938 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:321939 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:411940 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231941 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1942 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1943 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411944 } else {
1945 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231946 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1947 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1948 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411949 }
1950
xunjieli8dff50b2016-07-22 14:19:061951 // Second data write will result in a synchronous failure which will close
1952 // the session.
1953 AddWrite(SYNCHRONOUS, ERR_FAILED);
1954 Initialize();
1955
Jeremy Roman0579ed62017-08-29 15:56:191956 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121957 auto* chunked_upload_stream =
1958 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
xunjieli8dff50b2016-07-22 14:19:061959
1960 request_.method = "POST";
rchcd379012017-04-12 21:53:321961 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121962 request_.upload_data_stream = upload_data_stream_.get();
xunjieli8dff50b2016-07-22 14:19:061963 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201964 TestCompletionCallback().callback(), NetLogWithSource()));
xunjieli8dff50b2016-07-22 14:19:061965
1966 size_t chunk_size = strlen(kUploadData);
rch97827ee2017-05-24 23:49:121967 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
xunjieli8dff50b2016-07-22 14:19:061968 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271969 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli8dff50b2016-07-22 14:19:061970 net_log_.bound(), callback_.callback()));
1971 QuicHttpStream* stream = stream_.get();
1972 DeleteStreamCallback delete_stream_callback(std::move(stream_));
1973 // SendRequest() completes asynchronously after the final chunk is added.
Yixin Wange7ecc472018-03-06 19:00:251974 // Error does not surface yet since packet write is triggered by a packet
1975 // flusher that tries to bundle request body writes.
xunjieli8dff50b2016-07-22 14:19:061976 ASSERT_EQ(ERR_IO_PENDING,
1977 stream->SendRequest(headers_, &response_, callback_.callback()));
rch97827ee2017-05-24 23:49:121978 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
xunjieli8dff50b2016-07-22 14:19:061979 int rv = callback_.WaitForResult();
Yixin Wange7ecc472018-03-06 19:00:251980 EXPECT_EQ(OK, rv);
1981 // Error will be surfaced once an attempt to read the response occurs.
1982 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1983 stream->ReadResponseHeaders(callback_.callback()));
xunjieli8dff50b2016-07-22 14:19:061984}
1985
rtenneti15656ae2016-01-23 03:05:031986TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersComplete) {
1987 SetRequest("POST", "/", DEFAULT_PRIORITY);
Victor Vasiliev7da08172019-10-14 06:04:251988 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231989 AddWrite(ConstructInitialSettingsPacket());
rtenneti15656ae2016-01-23 03:05:031990 AddWrite(SYNCHRONOUS, ERR_FAILED);
1991 Initialize();
1992
Jeremy Roman0579ed62017-08-29 15:56:191993 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
Yixin Wange7ecc472018-03-06 19:00:251994 auto* chunked_upload_stream =
1995 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
rtenneti15656ae2016-01-23 03:05:031996
1997 request_.method = "POST";
rchcd379012017-04-12 21:53:321998 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121999 request_.upload_data_stream = upload_data_stream_.get();
rtenneti15656ae2016-01-23 03:05:032000 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202001 TestCompletionCallback().callback(), NetLogWithSource()));
rtenneti15656ae2016-01-23 03:05:032002
xunjieli5fafe142016-03-23 23:32:542003 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272004 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542005 net_log_.bound(), callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252006 ASSERT_EQ(ERR_IO_PENDING,
rtenneti15656ae2016-01-23 03:05:032007 stream_->SendRequest(headers_, &response_, callback_.callback()));
mmenkeffff3642017-06-15 17:37:242008
Yixin Wange7ecc472018-03-06 19:00:252009 // Error will be surfaced once |upload_data_stream| triggers the next write.
2010 size_t chunk_size = strlen(kUploadData);
2011 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2012 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR, callback_.WaitForResult());
2013
2014 EXPECT_LE(0, stream_->GetTotalSentBytes());
2015 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2016}
2017
2018TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersCompleteReadResponse) {
2019 SetRequest("POST", "/", DEFAULT_PRIORITY);
Victor Vasiliev7da08172019-10-14 06:04:252020 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232021 AddWrite(ConstructInitialSettingsPacket());
Yixin Wange7ecc472018-03-06 19:00:252022 AddWrite(SYNCHRONOUS, ERR_FAILED);
2023 Initialize();
2024
2025 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
2026 auto* chunked_upload_stream =
2027 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
2028
2029 request_.method = "POST";
2030 request_.url = GURL("https://www.example.org/");
2031 request_.upload_data_stream = upload_data_stream_.get();
2032
2033 size_t chunk_size = strlen(kUploadData);
2034 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2035
2036 ASSERT_EQ(OK, request_.upload_data_stream->Init(
2037 TestCompletionCallback().callback(), NetLogWithSource()));
2038
2039 ASSERT_EQ(OK,
2040 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
2041 net_log_.bound(), callback_.callback()));
2042 ASSERT_EQ(OK,
2043 stream_->SendRequest(headers_, &response_, callback_.callback()));
2044
2045 // Error will be surfaced once an attempt to read the response occurs.
2046 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
2047 stream_->ReadResponseHeaders(callback_.callback()));
2048
mmenkeffff3642017-06-15 17:37:242049 EXPECT_LE(0, stream_->GetTotalSentBytes());
2050 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rtenneti15656ae2016-01-23 03:05:032051}
2052
2053TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBodyComplete) {
2054 SetRequest("POST", "/", DEFAULT_PRIORITY);
2055 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232056 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252057 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232058 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:372059 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:232060 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2061 kIncludeVersion, !kFin, DEFAULT_PRIORITY,
2062 &spdy_request_headers_frame_length));
rtenneti15656ae2016-01-23 03:05:032063 AddWrite(SYNCHRONOUS, ERR_FAILED);
2064 Initialize();
2065
Jeremy Roman0579ed62017-08-29 15:56:192066 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:122067 auto* chunked_upload_stream =
2068 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
rtenneti15656ae2016-01-23 03:05:032069
2070 request_.method = "POST";
rchcd379012017-04-12 21:53:322071 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122072 request_.upload_data_stream = upload_data_stream_.get();
rtenneti15656ae2016-01-23 03:05:032073 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202074 TestCompletionCallback().callback(), NetLogWithSource()));
rtenneti15656ae2016-01-23 03:05:032075
xunjieli5fafe142016-03-23 23:32:542076 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272077 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542078 net_log_.bound(), callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252079 ASSERT_EQ(ERR_IO_PENDING,
rtenneti15656ae2016-01-23 03:05:032080 stream_->SendRequest(headers_, &response_, callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:252081
2082 size_t chunk_size = strlen(kUploadData);
2083 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2084 // Error does not surface yet since packet write is triggered by a packet
2085 // flusher that tries to bundle request body writes.
2086 ASSERT_EQ(OK, callback_.WaitForResult());
2087 // Error will be surfaced once an attempt to read the response occurs.
2088 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
2089 stream_->ReadResponseHeaders(callback_.callback()));
2090
2091 EXPECT_LE(0, stream_->GetTotalSentBytes());
2092 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2093}
2094
2095TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBundledBodyComplete) {
2096 SetRequest("POST", "/", DEFAULT_PRIORITY);
2097 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232098 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252099 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232100 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:432101 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harperc6cb7a612020-02-24 20:03:322102 if (!version_.HasIetfQuicFrames()) {
Renjief49758b2019-01-11 23:32:412103 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:232104 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2105 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
2106 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:412107 } else {
2108 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:232109 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2110 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
2111 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:412112 }
2113
Yixin Wange7ecc472018-03-06 19:00:252114 AddWrite(SYNCHRONOUS, ERR_FAILED);
2115 Initialize();
2116
2117 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
2118 auto* chunked_upload_stream =
2119 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
2120
2121 request_.method = "POST";
2122 request_.url = GURL("https://www.example.org/");
2123 request_.upload_data_stream = upload_data_stream_.get();
2124
2125 size_t chunk_size = strlen(kUploadData);
2126 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
2127
2128 ASSERT_EQ(OK, request_.upload_data_stream->Init(
2129 TestCompletionCallback().callback(), NetLogWithSource()));
2130
2131 ASSERT_EQ(OK,
2132 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
2133 net_log_.bound(), callback_.callback()));
2134 ASSERT_EQ(ERR_IO_PENDING,
2135 stream_->SendRequest(headers_, &response_, callback_.callback()));
2136
2137 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
2138
2139 // Error does not surface yet since packet write is triggered by a packet
2140 // flusher that tries to bundle request body writes.
2141 ASSERT_EQ(OK, callback_.WaitForResult());
2142 // Error will be surfaced once an attempt to read the response occurs.
2143 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
2144 stream_->ReadResponseHeaders(callback_.callback()));
2145
2146 EXPECT_LE(0, stream_->GetTotalSentBytes());
2147 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rtenneti15656ae2016-01-23 03:05:032148}
2149
ckrasic3865ee0f2016-02-29 22:04:562150TEST_P(QuicHttpStreamTest, ServerPushGetRequest) {
2151 SetRequest("GET", "/", DEFAULT_PRIORITY);
2152 Initialize();
2153
2154 // Initialize the first stream, for receiving the promise on.
2155 request_.method = "GET";
rchcd379012017-04-12 21:53:322156 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562157
xunjieli5fafe142016-03-23 23:32:542158 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272159 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542160 net_log_.bound(), callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232161 ASSERT_EQ(OK,
2162 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562163
2164 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2165 // packet, but does it matter?
2166 ReceivePromise(promise_id_);
2167 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2168
2169 request_.url = GURL(promise_url_);
2170
2171 // Make the second stream that will exercise the first step of the
2172 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272173 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2174 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2175 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562176
2177 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252178 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562179 size_t spdy_response_headers_frame_length;
2180 ProcessPacket(InnerConstructResponseHeadersPacket(
2181 1, promise_id_, false, &spdy_response_headers_frame_length));
2182
2183 // Receive the promised response body.
2184 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432185 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172186 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2187 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562188
2189 // Now sending a matching request will have successful rendezvous
2190 // with the promised stream.
Ryan Hamiltona1d1f4a2019-06-26 14:43:042191 ASSERT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
ckrasic3865ee0f2016-02-29 22:04:562192 callback_.callback()));
2193
2194 EXPECT_EQ(
2195 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2196 ->id(),
2197 promise_id_);
2198
2199 // The headers will be immediately available.
robpercival214763f2016-07-01 23:27:012200 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2201 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562202
2203 // As will be the body.
2204 EXPECT_EQ(
2205 static_cast<int>(strlen(kResponseBody)),
2206 promised_stream_->ReadResponseBody(
2207 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2208 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2209 EXPECT_TRUE(AtEof());
2210
ckrasic3865ee0f2016-02-29 22:04:562211 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2212 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412213 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562214 promised_stream_->GetTotalReceivedBytes());
2215}
2216
2217TEST_P(QuicHttpStreamTest, ServerPushGetRequestSlowResponse) {
2218 SetRequest("GET", "/", DEFAULT_PRIORITY);
2219 Initialize();
2220
2221 // Initialize the first stream, for receiving the promise on.
2222 request_.method = "GET";
rchcd379012017-04-12 21:53:322223 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562224
xunjieli5fafe142016-03-23 23:32:542225 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272226 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542227 net_log_.bound(), callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232228 ASSERT_EQ(OK,
2229 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562230
2231 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2232 // packet, but does it matter?
2233 ReceivePromise(promise_id_);
2234 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2235
2236 request_.url = GURL(promise_url_);
2237
2238 // Make the second stream that will exercise the first step of the
2239 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272240 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2241 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2242 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562243
2244 // Now sending a matching request will rendezvous with the promised
2245 // stream, but pending secondary validation.
2246 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2247 headers_, &response_, callback_.callback()));
2248
2249 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252250 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562251 size_t spdy_response_headers_frame_length;
2252 ProcessPacket(InnerConstructResponseHeadersPacket(
2253 1, promise_id_, false, &spdy_response_headers_frame_length));
2254
2255 // Receive the promised response body.
2256 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432257 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172258 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2259 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562260
fdoray92e35a72016-06-10 15:54:552261 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562262
2263 // Rendezvous should have succeeded now, so the promised stream
2264 // should point at our push stream, and we should be able read
2265 // headers and data from it.
robpercival214763f2016-07-01 23:27:012266 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562267
2268 EXPECT_EQ(
2269 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2270 ->id(),
2271 promise_id_);
2272
robpercival214763f2016-07-01 23:27:012273 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2274 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562275
2276 EXPECT_EQ(
2277 static_cast<int>(strlen(kResponseBody)),
2278 promised_stream_->ReadResponseBody(
2279 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2280
2281 // Callback should return
2282 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2283 EXPECT_TRUE(AtEof());
2284
ckrasic3865ee0f2016-02-29 22:04:562285 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2286 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412287 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562288 promised_stream_->GetTotalReceivedBytes());
2289}
2290
ckrasic2c63f9b2016-08-16 23:54:072291// Verify fix for crbug.com/637349
2292TEST_P(QuicHttpStreamTest, ServerPushCancelHttpStreamBeforeResponse) {
2293 SetRequest("GET", "/", DEFAULT_PRIORITY);
2294 Initialize();
2295
2296 // Initialize the first stream, for receiving the promise on.
2297 request_.method = "GET";
rchcd379012017-04-12 21:53:322298 request_.url = GURL("https://www.example.org/");
ckrasic2c63f9b2016-08-16 23:54:072299
2300 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272301 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
ckrasic2c63f9b2016-08-16 23:54:072302 net_log_.bound(), callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232303 ASSERT_EQ(OK,
2304 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic2c63f9b2016-08-16 23:54:072305
2306 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2307 // packet, but does it matter?
2308 ReceivePromise(promise_id_);
2309 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2310
2311 request_.url = GURL(promise_url_);
2312
2313 // Make the second stream that will exercise the first step of the
2314 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272315 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2316 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2317 callback_.callback()));
ckrasic2c63f9b2016-08-16 23:54:072318
2319 // Now sending a matching request will rendezvous with the promised
2320 // stream, but pending secondary validation.
2321 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2322 headers_, &response_, callback_.callback()));
2323
2324 base::RunLoop().RunUntilIdle();
2325
2326 // Cause of FinalValidation() crash as per bug.
2327 promised_stream_.reset();
2328
2329 // Receive the promised response headers.
2330 response_headers_ = promised_response_.Clone();
2331 size_t spdy_response_headers_frame_length;
2332 ProcessPacket(InnerConstructResponseHeadersPacket(
2333 1, promise_id_, false, &spdy_response_headers_frame_length));
2334}
2335
ckrasic3865ee0f2016-02-29 22:04:562336TEST_P(QuicHttpStreamTest, ServerPushCrossOriginOK) {
2337 SetRequest("GET", "/", DEFAULT_PRIORITY);
2338 Initialize();
2339
2340 // Initialize the first stream, for receiving the promise on.
2341 request_.method = "GET";
rchcd379012017-04-12 21:53:322342 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562343
xunjieli5fafe142016-03-23 23:32:542344 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272345 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542346 net_log_.bound(), callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232347 ASSERT_EQ(OK,
2348 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562349
2350 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2351 // packet, but does it matter?
2352
2353 push_promise_[":authority"] = "mail.example.org";
David Schinazi3f7465c2019-07-12 01:57:052354 promise_url_ =
2355 quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
ckrasic3865ee0f2016-02-29 22:04:562356
2357 ReceivePromise(promise_id_);
2358 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2359
2360 request_.url = GURL(promise_url_);
2361
2362 // Make the second stream that will exercise the first step of the
2363 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272364 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2365 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2366 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562367
2368 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252369 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562370 size_t spdy_response_headers_frame_length;
2371 ProcessPacket(InnerConstructResponseHeadersPacket(
2372 1, promise_id_, false, &spdy_response_headers_frame_length));
2373
2374 // Receive the promised response body.
2375 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432376 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172377 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2378 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562379
2380 // Now sending a matching request will have successful rendezvous
2381 // with the promised stream.
2382 EXPECT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
2383 callback_.callback()));
2384
2385 EXPECT_EQ(
2386 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2387 ->id(),
2388 promise_id_);
2389
2390 // The headers will be immediately available.
robpercival214763f2016-07-01 23:27:012391 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2392 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562393
2394 // As will be the body.
2395 EXPECT_EQ(
2396 static_cast<int>(strlen(kResponseBody)),
2397 promised_stream_->ReadResponseBody(
2398 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2399 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2400 EXPECT_TRUE(AtEof());
2401
ckrasic3865ee0f2016-02-29 22:04:562402 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2403 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412404 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562405 promised_stream_->GetTotalReceivedBytes());
2406}
2407
2408TEST_P(QuicHttpStreamTest, ServerPushCrossOriginFail) {
2409 SetRequest("GET", "/", DEFAULT_PRIORITY);
2410 Initialize();
2411
2412 // Initialize the first stream, for receiving the promise on.
2413 request_.method = "GET";
rchcd379012017-04-12 21:53:322414 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562415
xunjieli5fafe142016-03-23 23:32:542416 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272417 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542418 net_log_.bound(), callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232419 ASSERT_EQ(OK,
2420 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562421
2422 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2423 // packet, but does it matter?
2424 push_promise_[":authority"] = "www.notexample.org";
David Schinazi3f7465c2019-07-12 01:57:052425 promise_url_ =
2426 quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
ckrasic3865ee0f2016-02-29 22:04:562427
2428 ReceivePromise(promise_id_);
2429 // The promise will have been rejected because the cert doesn't
2430 // match.
2431 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
2432}
2433
2434TEST_P(QuicHttpStreamTest, ServerPushVaryCheckOK) {
2435 SetRequest("GET", "/", DEFAULT_PRIORITY);
2436 Initialize();
2437
2438 // Initialize the first stream, for receiving the promise on.
2439 request_.method = "GET";
rchcd379012017-04-12 21:53:322440 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562441
xunjieli5fafe142016-03-23 23:32:542442 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272443 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542444 net_log_.bound(), callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232445 ASSERT_EQ(OK,
2446 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562447
2448 push_promise_["accept-encoding"] = "gzip";
ckrasic3865ee0f2016-02-29 22:04:562449
2450 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2451 // packet, but does it matter?
2452 ReceivePromise(promise_id_);
2453 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2454
2455 request_.url = GURL(promise_url_);
2456
2457 // Make the second stream that will exercise the first step of the
2458 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272459 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2460 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2461 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562462
2463 headers_.SetHeader("accept-encoding", "gzip");
2464
2465 // Now sending a matching request will rendezvous with the promised
2466 // stream, but pending secondary validation.
2467 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2468 headers_, &response_, callback_.callback()));
2469
2470 // Receive the promised response headers.
2471 promised_response_["vary"] = "accept-encoding";
bnc94893a72016-06-30 13:45:252472 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562473 size_t spdy_response_headers_frame_length;
2474 ProcessPacket(InnerConstructResponseHeadersPacket(
2475 1, promise_id_, false, &spdy_response_headers_frame_length));
2476
2477 // Receive the promised response body.
2478 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432479 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172480 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2481 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562482
fdoray92e35a72016-06-10 15:54:552483 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562484
2485 // Rendezvous should have succeeded now, so the promised stream
2486 // should point at our push stream, and we should be able read
2487 // headers and data from it.
robpercival214763f2016-07-01 23:27:012488 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562489
2490 EXPECT_EQ(
2491 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2492 ->id(),
2493 promise_id_);
2494
robpercival214763f2016-07-01 23:27:012495 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2496 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562497
2498 EXPECT_EQ(
2499 static_cast<int>(strlen(kResponseBody)),
2500 promised_stream_->ReadResponseBody(
2501 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2502
2503 // Callback should return
2504 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2505 EXPECT_TRUE(AtEof());
2506
ckrasic3865ee0f2016-02-29 22:04:562507 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2508 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412509 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562510 promised_stream_->GetTotalReceivedBytes());
2511}
2512
2513TEST_P(QuicHttpStreamTest, ServerPushVaryCheckFail) {
2514 SetRequest("GET", "/", DEFAULT_PRIORITY);
2515 request_headers_[":scheme"] = "https";
2516 request_headers_[":path"] = "/bar";
2517 request_headers_["accept-encoding"] = "sdch";
2518
ckrasic3865ee0f2016-02-29 22:04:562519 Initialize();
2520
2521 // Initialize the first stream, for receiving the promise on.
2522 request_.method = "GET";
rchcd379012017-04-12 21:53:322523 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562524
xunjieli5fafe142016-03-23 23:32:542525 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272526 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542527 net_log_.bound(), callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232528 ASSERT_EQ(OK,
2529 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562530
2531 push_promise_["accept-encoding"] = "gzip";
ckrasic3865ee0f2016-02-29 22:04:562532
2533 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2534 // packet, but does it matter?
2535 ReceivePromise(promise_id_);
2536 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2537
2538 request_.url = GURL(promise_url_);
2539
2540 // Make the second stream that will exercise the first step of the
2541 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272542 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2543 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2544 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562545
2546 headers_.SetHeader("accept-encoding", "sdch");
2547
2548 // Now sending a matching request will rendezvous with the promised
2549 // stream, but pending secondary validation.
2550 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2551 headers_, &response_, callback_.callback()));
2552
2553 // Receive the promised response headers.
2554 promised_response_["vary"] = "accept-encoding";
bnc94893a72016-06-30 13:45:252555 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562556 size_t spdy_response_headers_frame_length;
2557 ProcessPacket(InnerConstructResponseHeadersPacket(
2558 1, promise_id_, false, &spdy_response_headers_frame_length));
2559
fdoray92e35a72016-06-10 15:54:552560 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562561
2562 // Rendezvous should have failed due to vary mismatch, so the
2563 // promised stream should have been aborted, and instead we have a
2564 // new, regular client initiated stream.
robpercival214763f2016-07-01 23:27:012565 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562566
2567 // Not a server-initiated stream.
2568 EXPECT_NE(
2569 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2570 ->id(),
2571 promise_id_);
2572
2573 // Instead, a new client-initiated stream.
2574 EXPECT_EQ(
2575 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2576 ->id(),
Nick Harper23290b82019-05-02 00:02:562577 stream_id_ + quic::QuicUtils::StreamIdDelta(version_.transport_version));
ckrasic3865ee0f2016-02-29 22:04:562578
2579 // After rendezvous failure, the push stream has been cancelled.
2580 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
2581
2582 // The rest of the test verifies that the retried as
2583 // client-initiated version of |promised_stream_| works as intended.
2584
2585 // Ack the request.
Renjie90e808e2019-01-24 07:24:042586 ProcessPacket(ConstructServerAckPacket(2, 1, 1, 1));
ckrasic3865ee0f2016-02-29 22:04:562587
Kenichi Ishibashif8634ab2021-03-16 23:41:282588 SetResponse("404", string());
ckrasic3865ee0f2016-02-29 22:04:562589 size_t spdy_response_header_frame_length;
2590 ProcessPacket(InnerConstructResponseHeadersPacket(
Nick Harper23290b82019-05-02 00:02:562591 3,
2592 stream_id_ + quic::QuicUtils::StreamIdDelta(version_.transport_version),
2593 kFin, &spdy_response_header_frame_length));
ckrasic3865ee0f2016-02-29 22:04:562594
fdoray92e35a72016-06-10 15:54:552595 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562596
robpercival214763f2016-07-01 23:27:012597 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2598 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562599 ASSERT_TRUE(response_.headers.get());
2600 EXPECT_EQ(404, response_.headers->response_code());
2601 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
2602 EXPECT_FALSE(response_.response_time.is_null());
2603 EXPECT_FALSE(response_.request_time.is_null());
2604
2605 // There is no body, so this should return immediately.
2606 EXPECT_EQ(
2607 0, promised_stream_->ReadResponseBody(
2608 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2609 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2610
2611 stream_->Close(true);
2612
2613 EXPECT_TRUE(AtEof());
ckrasic3865ee0f2016-02-29 22:04:562614}
2615
maksim.sisov84e20c92016-06-23 08:49:342616TEST_P(QuicHttpStreamTest, DataReadErrorSynchronous) {
2617 SetRequest("POST", "/", DEFAULT_PRIORITY);
2618 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232619 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252620 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232621 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Yixin Wange7ecc472018-03-06 19:00:252622 AddWrite(ConstructRequestAndRstPacket(
Renjie Tangaadb84b2019-08-31 01:00:232623 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2624 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
2625 &spdy_request_headers_frame_length, quic::QUIC_ERROR_PROCESSING_STREAM));
maksim.sisov84e20c92016-06-23 08:49:342626
2627 Initialize();
2628
Jeremy Roman0579ed62017-08-29 15:56:192629 upload_data_stream_ = std::make_unique<ReadErrorUploadDataStream>(
maksim.sisov84e20c92016-06-23 08:49:342630 ReadErrorUploadDataStream::FailureMode::SYNC);
2631 request_.method = "POST";
rchcd379012017-04-12 21:53:322632 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122633 request_.upload_data_stream = upload_data_stream_.get();
maksim.sisov84e20c92016-06-23 08:49:342634 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202635 TestCompletionCallback().callback(), NetLogWithSource()));
maksim.sisov84e20c92016-06-23 08:49:342636
2637 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272638 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
maksim.sisov84e20c92016-06-23 08:49:342639 net_log_.bound(), callback_.callback()));
2640
2641 int result = stream_->SendRequest(headers_, &response_, callback_.callback());
robpercival214763f2016-07-01 23:27:012642 EXPECT_THAT(result, IsError(ERR_FAILED));
maksim.sisov84e20c92016-06-23 08:49:342643
2644 EXPECT_TRUE(AtEof());
2645
2646 // QuicHttpStream::GetTotalSent/ReceivedBytes includes only headers.
2647 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
2648 stream_->GetTotalSentBytes());
2649 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2650}
2651
2652TEST_P(QuicHttpStreamTest, DataReadErrorAsynchronous) {
2653 SetRequest("POST", "/", DEFAULT_PRIORITY);
2654 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232655 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252656 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232657 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:372658 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:232659 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2660 kIncludeVersion, !kFin, DEFAULT_PRIORITY,
2661 &spdy_request_headers_frame_length));
2662 AddWrite(
2663 ConstructClientRstStreamErrorPacket(packet_number++, !kIncludeVersion));
maksim.sisov84e20c92016-06-23 08:49:342664
2665 Initialize();
2666
Jeremy Roman0579ed62017-08-29 15:56:192667 upload_data_stream_ = std::make_unique<ReadErrorUploadDataStream>(
maksim.sisov84e20c92016-06-23 08:49:342668 ReadErrorUploadDataStream::FailureMode::ASYNC);
2669 request_.method = "POST";
rchcd379012017-04-12 21:53:322670 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122671 request_.upload_data_stream = upload_data_stream_.get();
maksim.sisov84e20c92016-06-23 08:49:342672 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202673 TestCompletionCallback().callback(), NetLogWithSource()));
maksim.sisov84e20c92016-06-23 08:49:342674
2675 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272676 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
maksim.sisov84e20c92016-06-23 08:49:342677 net_log_.bound(), callback_.callback()));
2678
2679 int result = stream_->SendRequest(headers_, &response_, callback_.callback());
2680
Renjie90e808e2019-01-24 07:24:042681 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
Kenichi Ishibashif8634ab2021-03-16 23:41:282682 SetResponse("200", string());
maksim.sisov84e20c92016-06-23 08:49:342683
robpercival214763f2016-07-01 23:27:012684 EXPECT_THAT(result, IsError(ERR_IO_PENDING));
2685 EXPECT_THAT(callback_.GetResult(result), IsError(ERR_FAILED));
maksim.sisov84e20c92016-06-23 08:49:342686
2687 EXPECT_TRUE(AtEof());
2688
2689 // QuicHttpStream::GetTotalSent/ReceivedBytes includes only headers.
2690 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
2691 stream_->GetTotalSentBytes());
2692 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2693}
2694
Bence Béky97ec688c2021-03-16 13:48:502695TEST_P(QuicHttpStreamTest, GetAcceptChViaAlps) {
2696 AddWrite(ConstructInitialSettingsPacket());
2697 Initialize();
2698
2699 if (!VersionUsesHttp3(version_.transport_version)) {
2700 // ALPS is only implemented for HTTP/3.
2701 return;
2702 }
2703
2704 base::HistogramTester histogram_tester;
2705
2706 session_->OnAcceptChFrameReceivedViaAlps(
2707 {{{"https://www.example.org", "Sec-UA-CH-Platform"}}});
2708
2709 request_.method = "GET";
2710 request_.url = GURL("https://www.example.org/foo");
2711
2712 EXPECT_EQ(OK,
2713 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
2714 net_log_.bound(), callback_.callback()));
2715 EXPECT_EQ("Sec-UA-CH-Platform", stream_->GetAcceptChViaAlps());
2716 EXPECT_TRUE(AtEof());
2717
2718 histogram_tester.ExpectBucketCount(
2719 "Net.QuicSession.AcceptChFrameReceivedViaAlps", 1, 1);
2720 histogram_tester.ExpectTotalCount(
2721 "Net.QuicSession.AcceptChFrameReceivedViaAlps", 1);
2722 histogram_tester.ExpectBucketCount("Net.QuicSession.AcceptChForOrigin", 1, 1);
2723 histogram_tester.ExpectTotalCount("Net.QuicSession.AcceptChForOrigin", 1);
2724}
2725
[email protected]f702d572012-12-04 15:56:202726} // namespace test
[email protected]f702d572012-12-04 15:56:202727} // namespace net