blob: 1a058f95410aed78112f8de060911fb6dfb28a52 [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"
xunjieli188bd402016-03-12 00:17:2516#include "base/strings/string_number_conversions.h"
gabf767595f2016-05-11 18:50:3517#include "base/threading/thread_task_runner_handle.h"
Zhongyi Shic16b4102019-02-12 00:37:4018#include "base/time/default_tick_clock.h"
xunjieli84adaab2016-09-20 01:12:2819#include "base/time/time.h"
mmenkecbc2b712014-10-09 20:29:0720#include "net/base/chunked_upload_data_stream.h"
21#include "net/base/elements_upload_data_stream.h"
David Benjamin0288768a2019-07-22 15:00:2622#include "net/base/load_flags.h"
xunjieli84adaab2016-09-20 01:12:2823#include "net/base/load_timing_info.h"
24#include "net/base/load_timing_info_test_util.h"
[email protected]f702d572012-12-04 15:56:2025#include "net/base/net_errors.h"
26#include "net/base/test_completion_callback.h"
[email protected]b2d26cfd2012-12-11 10:36:0627#include "net/base/upload_bytes_element_reader.h"
[email protected]f702d572012-12-04 15:56:2028#include "net/http/http_response_headers.h"
[email protected]5db452202014-08-19 05:22:1529#include "net/http/transport_security_state.h"
mikecirone8b85c432016-09-08 19:11:0030#include "net/log/net_log_event_type.h"
xunjieli5fafe142016-03-23 23:32:5431#include "net/log/test_net_log.h"
32#include "net/log/test_net_log_util.h"
Victor Vasiliev4f6fb892019-05-31 16:58:3133#include "net/quic/address_utils.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0834#include "net/quic/crypto/proof_verifier_chromium.h"
35#include "net/quic/mock_crypto_client_stream_factory.h"
Ryan Hamiltona1d1f4a2019-06-26 14:43:0436#include "net/quic/platform/impl/quic_test_impl.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0837#include "net/quic/quic_chromium_alarm_factory.h"
38#include "net/quic/quic_chromium_connection_helper.h"
39#include "net/quic/quic_chromium_packet_reader.h"
40#include "net/quic/quic_chromium_packet_writer.h"
Matt Menkefca05b62019-09-20 23:15:5641#include "net/quic/quic_crypto_client_config_handle.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0842#include "net/quic/quic_http_utils.h"
43#include "net/quic/quic_server_info.h"
44#include "net/quic/quic_stream_factory.h"
45#include "net/quic/quic_test_packet_maker.h"
Ryan Hamilton0d65a8c2019-06-07 00:46:0246#include "net/quic/quic_test_packet_printer.h"
Matt Menkefca05b62019-09-20 23:15:5647#include "net/quic/test_quic_crypto_client_config_handle.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0848#include "net/quic/test_task_runner.h"
tbansalca83c002016-04-28 20:56:2849#include "net/socket/socket_performance_watcher.h"
[email protected]f702d572012-12-04 15:56:2050#include "net/socket/socket_test_util.h"
Bence Béky94658bf2018-05-11 19:22:5851#include "net/spdy/spdy_http_utils.h"
rch03b7a202016-02-05 00:54:2052#include "net/test/cert_test_util.h"
robpercival214763f2016-07-01 23:27:0153#include "net/test/gtest_util.h"
rsleevia69c79a2016-06-22 03:28:4354#include "net/test/test_data_directory.h"
Gabriel Charettec7108742019-08-23 03:31:4055#include "net/test/test_with_task_environment.h"
Victor Vasiliev6bb59d22019-03-08 21:34:5156#include "net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.h"
57#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
58#include "net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h"
59#include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
David Schinazi3f7465c2019-07-12 01:57:0560#include "net/third_party/quiche/src/quic/core/http/spdy_server_push_utils.h"
Victor Vasiliev6bb59d22019-03-08 21:34:5161#include "net/third_party/quiche/src/quic/core/quic_connection.h"
62#include "net/third_party/quiche/src/quic/core/quic_utils.h"
63#include "net/third_party/quiche/src/quic/core/quic_write_blocked_list.h"
Ryan Hamiltona1d1f4a2019-06-26 14:43:0464#include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h"
65#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
Victor Vasiliev6bb59d22019-03-08 21:34:5166#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
67#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
68#include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
69#include "net/third_party/quiche/src/quic/test_tools/mock_random.h"
70#include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
71#include "net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h"
72#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
Victor Vasiliev27cc7712019-01-24 11:50:1473#include "net/third_party/quiche/src/spdy/core/spdy_frame_builder.h"
74#include "net/third_party/quiche/src/spdy/core/spdy_framer.h"
75#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
Ramin Halavati683bcaa92018-02-14 08:42:3976#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
[email protected]f702d572012-12-04 15:56:2077#include "testing/gmock/include/gmock/gmock.h"
78#include "testing/gtest/include/gtest/gtest.h"
79
bnc614a92d32016-04-04 13:56:0780using std::string;
[email protected]f702d572012-12-04 15:56:2081using testing::_;
[email protected]06ff5152013-08-29 01:03:0582using testing::AnyNumber;
83using testing::Return;
[email protected]f702d572012-12-04 15:56:2084
85namespace net {
[email protected]f702d572012-12-04 15:56:2086namespace test {
[email protected]f702d572012-12-04 15:56:2087namespace {
88
[email protected]16ba7742014-08-22 00:57:2589const char kUploadData[] = "Really nifty data!";
rch9ae5b3b2016-02-11 00:36:2990const char kDefaultServerHostName[] = "www.example.org";
rchcd379012017-04-12 21:53:3291const uint16_t kDefaultServerPort = 443;
[email protected]f702d572012-12-04 15:56:2092
David Schinazi09e9a6012019-10-03 17:37:5793struct TestParams {
94 quic::ParsedQuicVersion version;
95 bool client_headers_include_h2_stream_dependency;
96};
97
98// Used by ::testing::PrintToStringParamName().
99std::string PrintToString(const TestParams& p) {
100 return quic::QuicStrCat(
101 ParsedQuicVersionToString(p.version), "_",
102 (p.client_headers_include_h2_stream_dependency ? "" : "No"),
103 "Dependency");
104}
105
106std::vector<TestParams> GetTestParams() {
107 std::vector<TestParams> params;
108 quic::ParsedQuicVersionVector all_supported_versions =
109 quic::AllSupportedVersions();
110 for (const auto& version : all_supported_versions) {
111 params.push_back(TestParams{version, false});
112 params.push_back(TestParams{version, true});
113 }
114 return params;
115}
116
Ryan Hamilton8d9ee76e2018-05-29 23:52:52117class TestQuicConnection : public quic::QuicConnection {
[email protected]f702d572012-12-04 15:56:20118 public:
Ryan Hamilton8d9ee76e2018-05-29 23:52:52119 TestQuicConnection(const quic::ParsedQuicVersionVector& versions,
120 quic::QuicConnectionId connection_id,
[email protected]f702d572012-12-04 15:56:20121 IPEndPoint address,
rch12fef552016-01-15 16:26:31122 QuicChromiumConnectionHelper* helper,
rch16c74d1d2016-04-22 06:14:07123 QuicChromiumAlarmFactory* alarm_factory,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52124 quic::QuicPacketWriter* writer)
Victor Vasiliev4f6fb892019-05-31 16:58:31125 : quic::QuicConnection(connection_id,
126 ToQuicSocketAddress(address),
127 helper,
128 alarm_factory,
129 writer,
130 true /* owns_writer */,
131 quic::Perspective::IS_CLIENT,
132 versions) {}
[email protected]f702d572012-12-04 15:56:20133
Ryan Hamilton8d9ee76e2018-05-29 23:52:52134 void SetSendAlgorithm(quic::SendAlgorithmInterface* send_algorithm) {
135 quic::test::QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
[email protected]f702d572012-12-04 15:56:20136 }
137};
138
maksim.sisov84e20c92016-06-23 08:49:34139// UploadDataStream that always returns errors on data read.
140class ReadErrorUploadDataStream : public UploadDataStream {
141 public:
142 enum class FailureMode { SYNC, ASYNC };
143
144 explicit ReadErrorUploadDataStream(FailureMode mode)
Jeremy Romand54000b22019-07-08 18:40:16145 : UploadDataStream(true, 0), async_(mode) {}
maksim.sisov84e20c92016-06-23 08:49:34146 ~ReadErrorUploadDataStream() override {}
147
148 private:
149 void CompleteRead() { UploadDataStream::OnReadCompleted(ERR_FAILED); }
150
151 // UploadDataStream implementation:
tfarina42834112016-09-22 13:38:20152 int InitInternal(const NetLogWithSource& net_log) override { return OK; }
maksim.sisov84e20c92016-06-23 08:49:34153
154 int ReadInternal(IOBuffer* buf, int buf_len) override {
155 if (async_ == FailureMode::ASYNC) {
156 base::ThreadTaskRunnerHandle::Get()->PostTask(
kylecharf4fe5172019-02-15 18:53:49157 FROM_HERE, base::BindOnce(&ReadErrorUploadDataStream::CompleteRead,
158 weak_factory_.GetWeakPtr()));
maksim.sisov84e20c92016-06-23 08:49:34159 return ERR_IO_PENDING;
160 }
161 return ERR_FAILED;
162 }
163
164 void ResetInternal() override {}
165
166 const FailureMode async_;
167
Jeremy Romand54000b22019-07-08 18:40:16168 base::WeakPtrFactory<ReadErrorUploadDataStream> weak_factory_{this};
maksim.sisov84e20c92016-06-23 08:49:34169
170 DISALLOW_COPY_AND_ASSIGN(ReadErrorUploadDataStream);
171};
172
Bence Béky8ddc2492018-06-13 01:02:04173// A helper class that will delete |stream| when the callback is invoked.
xunjieli8dff50b2016-07-22 14:19:06174class DeleteStreamCallback : public TestCompletionCallbackBase {
175 public:
Bence Béky8ddc2492018-06-13 01:02:04176 explicit DeleteStreamCallback(std::unique_ptr<QuicHttpStream> stream)
177 : stream_(std::move(stream)) {}
xunjieli8dff50b2016-07-22 14:19:06178
Bence Béky8ddc2492018-06-13 01:02:04179 CompletionOnceCallback callback() {
180 return base::BindOnce(&DeleteStreamCallback::DeleteStream,
181 base::Unretained(this));
182 }
xunjieli8dff50b2016-07-22 14:19:06183
184 private:
185 void DeleteStream(int result) {
186 stream_.reset();
187 SetResult(result);
188 }
189
190 std::unique_ptr<QuicHttpStream> stream_;
xunjieli8dff50b2016-07-22 14:19:06191};
192
[email protected]f702d572012-12-04 15:56:20193} // namespace
194
[email protected]24e5bc52013-09-18 15:36:58195class QuicHttpStreamPeer {
196 public:
rch08e198572017-05-09 16:56:55197 static QuicChromiumClientStream::Handle* GetQuicChromiumClientStream(
[email protected]24e5bc52013-09-18 15:36:58198 QuicHttpStream* stream) {
rch08e198572017-05-09 16:56:55199 return stream->stream_.get();
[email protected]24e5bc52013-09-18 15:36:58200 }
201};
202
David Schinazi09e9a6012019-10-03 17:37:57203class QuicHttpStreamTest : public ::testing::TestWithParam<TestParams>,
Gabriel Charette694c3c332019-08-19 14:53:05204 public WithTaskEnvironment {
rchfb47f712017-05-21 03:24:00205 public:
206 void CloseStream(QuicHttpStream* stream, int /*rv*/) { stream->Close(false); }
207
[email protected]f702d572012-12-04 15:56:20208 protected:
[email protected]1e960032013-12-20 19:00:20209 static const bool kFin = true;
210 static const bool kIncludeVersion = true;
211 static const bool kIncludeCongestionFeedback = true;
212
[email protected]f702d572012-12-04 15:56:20213 // Holds a packet to be written to the wire, and the IO mode that should
214 // be used by the mock socket when performing the write.
215 struct PacketToWrite {
Ryan Hamilton8d9ee76e2018-05-29 23:52:52216 PacketToWrite(IoMode mode, quic::QuicReceivedPacket* packet)
rjshaded5ced072015-12-18 19:26:02217 : mode(mode), packet(packet) {}
rtenneti15656ae2016-01-23 03:05:03218 PacketToWrite(IoMode mode, int rv) : mode(mode), packet(nullptr), rv(rv) {}
[email protected]f702d572012-12-04 15:56:20219 IoMode mode;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52220 quic::QuicReceivedPacket* packet;
rtenneti15656ae2016-01-23 03:05:03221 int rv;
[email protected]f702d572012-12-04 15:56:20222 };
223
224 QuicHttpStreamTest()
David Schinazi09e9a6012019-10-03 17:37:57225 : version_(GetParam().version),
226 client_headers_include_h2_stream_dependency_(
227 GetParam().client_headers_include_h2_stream_dependency),
Nick Harpera598fc5f2019-06-21 08:46:50228 crypto_config_(
229 quic::test::crypto_test_utils::ProofVerifierForTesting()),
Victor Costan9c7302b2018-08-27 16:39:44230 read_buffer_(base::MakeRefCounted<IOBufferWithSize>(4096)),
Fan Yang32c5a112018-12-10 20:06:33231 promise_id_(GetNthServerInitiatedUnidirectionalStreamId(0)),
232 stream_id_(GetNthClientInitiatedBidirectionalStreamId(0)),
David Schinazic8281052019-01-24 06:14:17233 connection_id_(quic::test::TestConnectionId(2)),
Yixin Wang079ad542018-01-11 04:06:05234 client_maker_(version_,
alyssar2adf3ac2016-05-03 17:12:58235 connection_id_,
236 &clock_,
237 kDefaultServerHostName,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52238 quic::Perspective::IS_CLIENT,
Yixin Wang079ad542018-01-11 04:06:05239 client_headers_include_h2_stream_dependency_),
240 server_maker_(version_,
zhongyi5dbfdd42017-06-20 05:22:15241 connection_id_,
alyssar2adf3ac2016-05-03 17:12:58242 &clock_,
243 kDefaultServerHostName,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52244 quic::Perspective::IS_SERVER,
Yixin Wang079ad542018-01-11 04:06:05245 false),
ckrasic3865ee0f2016-02-29 22:04:56246 random_generator_(0),
Ryan Hamilton0d65a8c2019-06-07 00:46:02247 printer_(version_) {
Nick Harper057264a82019-09-12 23:33:49248 SetQuicReloadableFlag(quic_supports_tls_handshake, true);
martijn21968ea2016-02-24 18:46:20249 IPAddress ip(192, 0, 2, 33);
[email protected]f702d572012-12-04 15:56:20250 peer_addr_ = IPEndPoint(ip, 443);
251 self_addr_ = IPEndPoint(ip, 8435);
Ryan Hamilton8d9ee76e2018-05-29 23:52:52252 clock_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(20));
Ramin Halavati683bcaa92018-02-14 08:42:39253 request_.traffic_annotation =
254 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f702d572012-12-04 15:56:20255 }
256
257 ~QuicHttpStreamTest() {
Renjieba55fae2018-09-20 03:05:16258 session_->CloseSessionOnError(ERR_ABORTED, quic::QUIC_INTERNAL_ERROR,
259 quic::ConnectionCloseBehavior::SILENT_CLOSE);
[email protected]f702d572012-12-04 15:56:20260 for (size_t i = 0; i < writes_.size(); i++) {
261 delete writes_[i].packet;
262 }
263 }
264
265 // Adds a packet to the list of expected writes.
Ryan Hamilton8d9ee76e2018-05-29 23:52:52266 void AddWrite(std::unique_ptr<quic::QuicReceivedPacket> packet) {
[email protected]1e960032013-12-20 19:00:20267 writes_.push_back(PacketToWrite(SYNCHRONOUS, packet.release()));
[email protected]f702d572012-12-04 15:56:20268 }
269
rtenneti15656ae2016-01-23 03:05:03270 void AddWrite(IoMode mode, int rv) {
271 writes_.push_back(PacketToWrite(mode, rv));
272 }
273
[email protected]f702d572012-12-04 15:56:20274 // Returns the packet to be written at position |pos|.
Ryan Hamilton8d9ee76e2018-05-29 23:52:52275 quic::QuicReceivedPacket* GetWrite(size_t pos) { return writes_[pos].packet; }
[email protected]f702d572012-12-04 15:56:20276
277 bool AtEof() {
rch37de576c2015-05-17 20:28:17278 return socket_data_->AllReadDataConsumed() &&
279 socket_data_->AllWriteDataConsumed();
[email protected]f702d572012-12-04 15:56:20280 }
281
Ryan Hamilton8d9ee76e2018-05-29 23:52:52282 void ProcessPacket(std::unique_ptr<quic::QuicReceivedPacket> packet) {
Victor Vasiliev4f6fb892019-05-31 16:58:31283 connection_->ProcessUdpPacket(ToQuicSocketAddress(self_addr_),
284 ToQuicSocketAddress(peer_addr_), *packet);
[email protected]f702d572012-12-04 15:56:20285 }
286
287 // Configures the test fixture to use the list of expected writes.
288 void Initialize() {
289 mock_writes_.reset(new MockWrite[writes_.size()]);
290 for (size_t i = 0; i < writes_.size(); i++) {
rtenneti15656ae2016-01-23 03:05:03291 if (writes_[i].packet == nullptr) {
292 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].rv, i);
293 } else {
294 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].packet->data(),
295 writes_[i].packet->length());
296 }
bnc614a92d32016-04-04 13:56:07297 }
[email protected]f702d572012-12-04 15:56:20298
rtennetibe635732014-10-02 22:51:42299 socket_data_.reset(new StaticSocketDataProvider(
Ryan Sleevib8d7ea02018-05-07 20:01:01300 base::span<MockRead>(),
301 base::make_span(mock_writes_.get(), writes_.size())));
Ryan Hamilton0d65a8c2019-06-07 00:46:02302 socket_data_->set_printer(&printer_);
[email protected]f702d572012-12-04 15:56:20303
danakjad1777e2016-04-16 00:56:42304 std::unique_ptr<MockUDPClientSocket> socket(new MockUDPClientSocket(
xunjielib53b38c2016-03-24 15:54:36305 socket_data_.get(), net_log_.bound().net_log()));
[email protected]e13201d82012-12-12 05:00:32306 socket->Connect(peer_addr_);
[email protected]f702d572012-12-04 15:56:20307 runner_ = new TestTaskRunner(&clock_);
Ryan Hamilton8d9ee76e2018-05-29 23:52:52308 send_algorithm_ = new quic::test::MockSendAlgorithm();
rch7dd15702015-07-01 18:57:57309 EXPECT_CALL(*send_algorithm_, InRecovery()).WillRepeatedly(Return(false));
310 EXPECT_CALL(*send_algorithm_, InSlowStart()).WillRepeatedly(Return(false));
Victor Vasiliev7da08172019-10-14 06:04:25311 if (VersionUsesHttp3(version_.transport_version)) {
Renjie Tangaadb84b2019-08-31 01:00:23312 EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
313 .Times(testing::AtLeast(1));
314 }
Ryan Hamiltona1d1f4a2019-06-26 14:43:04315 EXPECT_CALL(*send_algorithm_, OnCongestionEvent(_, _, _, _, _))
316 .Times(AnyNumber());
rtenneti44f4a2e2015-08-07 14:00:07317 EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
Zhongyi Shica576df2019-04-12 17:43:40318 .WillRepeatedly(Return(quic::kMaxOutgoingPacketSize));
jokulik0e0a00c32016-06-13 21:51:58319 EXPECT_CALL(*send_algorithm_, PacingRate(_))
Ryan Hamilton8d9ee76e2018-05-29 23:52:52320 .WillRepeatedly(Return(quic::QuicBandwidth::Zero()));
Michael Warres74ee3ce2017-10-09 15:26:37321 EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true));
rtenneti44f4a2e2015-08-07 14:00:07322 EXPECT_CALL(*send_algorithm_, BandwidthEstimate())
Ryan Hamilton8d9ee76e2018-05-29 23:52:52323 .WillRepeatedly(Return(quic::QuicBandwidth::Zero()));
rch1e543ec2015-03-29 07:04:40324 EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(AnyNumber());
rch08cae032017-03-29 00:59:15325 EXPECT_CALL(*send_algorithm_, OnApplicationLimited(_)).Times(AnyNumber());
rch0d5bcf62017-05-24 22:48:45326 EXPECT_CALL(*send_algorithm_, GetCongestionControlType())
327 .Times(AnyNumber());
rch16c74d1d2016-04-22 06:14:07328 helper_.reset(
329 new QuicChromiumConnectionHelper(&clock_, &random_generator_));
330 alarm_factory_.reset(new QuicChromiumAlarmFactory(runner_.get(), &clock_));
331
Michael Warres74ee3ce2017-10-09 15:26:37332 connection_ = new TestQuicConnection(
Nick Harper23290b82019-05-02 00:02:56333 quic::test::SupportedVersions(version_), connection_id_, peer_addr_,
334 helper_.get(), alarm_factory_.get(),
Ryan Hamilton9edcf1a2017-11-22 05:55:17335 new QuicChromiumPacketWriter(
336 socket.get(), base::ThreadTaskRunnerHandle::Get().get()));
[email protected]f702d572012-12-04 15:56:20337 connection_->set_visitor(&visitor_);
[email protected]fee17f72013-02-03 07:47:41338 connection_->SetSendAlgorithm(send_algorithm_);
rch03b7a202016-02-05 00:54:20339
340 // Load a certificate that is valid for *.example.org
341 scoped_refptr<X509Certificate> test_cert(
342 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
343 EXPECT_TRUE(test_cert.get());
344
345 verify_details_.cert_verify_result.verified_cert = test_cert;
346 verify_details_.cert_verify_result.is_issued_by_known_root = true;
347 crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details_);
348
xunjieli84adaab2016-09-20 01:12:28349 base::TimeTicks dns_end = base::TimeTicks::Now();
350 base::TimeTicks dns_start = dns_end - base::TimeDelta::FromMilliseconds(1);
ckrasic4f9d88d2015-07-22 22:23:16351 session_.reset(new QuicChromiumClientSession(
xunjielib53b38c2016-03-24 15:54:36352 connection_, std::move(socket),
rtenneti1cd3b162015-09-29 02:58:28353 /*stream_factory=*/nullptr, &crypto_client_stream_factory_, &clock_,
Nick Harper89bc7212018-07-31 19:07:57354 &transport_security_state_, /*ssl_config_service=*/nullptr,
danakjad1777e2016-04-16 00:56:42355 base::WrapUnique(static_cast<QuicServerInfo*>(nullptr)),
Paul Jensen8e3c5d32018-02-19 17:06:33356 QuicSessionKey(kDefaultServerHostName, kDefaultServerPort,
dalyk51ab46b2019-10-15 15:14:34357 PRIVACY_MODE_DISABLED, SocketTag(),
358 NetworkIsolationKey(), false /* disable_secure_dns */),
Bence Béky1ceba552019-07-19 17:11:05359 /*require_confirmation=*/false,
360 /*max_allowed_push_id=*/0,
361 /*migrate_session_early_v2=*/false,
Zhongyi Shi757fcce2018-06-27 05:41:27362 /*migrate_session_on_network_change_v2=*/false,
363 /*default_network=*/NetworkChangeNotifier::kInvalidNetworkHandle,
Zhongyi Shie01f2db2019-02-22 19:53:23364 quic::QuicTime::Delta::FromMilliseconds(
Ryan Sleevi2e8255b2019-07-17 21:02:21365 kDefaultRetransmittableOnWireTimeout.InMilliseconds()),
Zhongyi Shiaf38c4e42019-08-29 22:49:05366 /*migrate_idle_session=*/false, /*allow_port_migration=*/false,
367 kDefaultIdleSessionMigrationPeriod, kMaxTimeOnNonDefaultNetwork,
Zhongyi Shiee760762018-08-01 00:54:29368 kMaxMigrationsToNonDefaultNetworkOnWriteError,
Zhongyi Shi8b1e43f2017-12-13 20:46:30369 kMaxMigrationsToNonDefaultNetworkOnPathDegrading,
Zhongyi Shi5f587cc2017-11-21 23:24:17370 kQuicYieldAfterPacketsRead,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52371 quic::QuicTime::Delta::FromMilliseconds(
372 kQuicYieldAfterDurationMilliseconds),
Zhongyi Shidbce7f412019-02-01 23:16:29373 /*go_away_on_path_degrading*/ false,
Yixin Wang079ad542018-01-11 04:06:05374 client_headers_include_h2_stream_dependency_, /*cert_verify_flags=*/0,
Matt Menkefca05b62019-09-20 23:15:56375 quic::test::DefaultQuicConfig(),
376 std::make_unique<TestQuicCryptoClientConfigHandle>(&crypto_config_),
377 "CONNECTION_UNKNOWN", dns_start, dns_end, &push_promise_index_, nullptr,
Zhongyi Shic16b4102019-02-12 00:37:40378 base::DefaultTickClock::GetInstance(),
xunjieli84adaab2016-09-20 01:12:28379 base::ThreadTaskRunnerHandle::Get().get(),
xunjieli5fafe142016-03-23 23:32:54380 /*socket_performance_watcher=*/nullptr, net_log_.bound().net_log()));
rtennetid39bd762015-06-12 01:05:52381 session_->Initialize();
xunjieli100937eb52016-09-15 20:09:37382 TestCompletionCallback callback;
rchf0b18c8a2017-05-05 19:31:57383
rch433bf5f2017-02-14 04:10:47384 session_->CryptoConnect(callback.callback());
Ryan Hamilton6c2a2a82017-12-15 02:06:28385 stream_ = std::make_unique<QuicHttpStream>(
386 session_->CreateHandle(HostPortPair("www.example.org", 443)));
387 promised_stream_ = std::make_unique<QuicHttpStream>(
388 session_->CreateHandle(HostPortPair("www.example.org", 443)));
ckrasic3865ee0f2016-02-29 22:04:56389 push_promise_[":path"] = "/bar";
390 push_promise_[":authority"] = "www.example.org";
391 push_promise_[":version"] = "HTTP/1.1";
392 push_promise_[":method"] = "GET";
393 push_promise_[":scheme"] = "https";
394
395 promised_response_[":status"] = "200 OK";
396 promised_response_[":version"] = "HTTP/1.1";
397 promised_response_["content-type"] = "text/plain";
398
David Schinazi3f7465c2019-07-12 01:57:05399 promise_url_ =
400 quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
[email protected]6cca996b2013-01-25 07:43:36401 }
402
bnc614a92d32016-04-04 13:56:07403 void SetRequest(const string& method,
404 const string& path,
[email protected]1e960032013-12-20 19:00:20405 RequestPriority priority) {
rchcd379012017-04-12 21:53:32406 request_headers_ = client_maker_.GetRequestHeaders(method, "https", path);
[email protected]6cca996b2013-01-25 07:43:36407 }
408
bnc614a92d32016-04-04 13:56:07409 void SetResponse(const string& status, const string& body) {
alyssar2adf3ac2016-05-03 17:12:58410 response_headers_ = server_maker_.GetResponseHeaders(status);
[email protected]92bf17c2014-03-03 21:14:03411 response_data_ = body;
[email protected]6cca996b2013-01-25 07:43:36412 }
[email protected]f702d572012-12-04 15:56:20413
Ryan Hamilton8d9ee76e2018-05-29 23:52:52414 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructDataPacket(
Fan Yangac867502019-01-28 21:10:23415 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52416 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56417 bool should_include_version,
418 bool fin,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52419 quic::QuicStringPiece data,
alyssar2adf3ac2016-05-03 17:12:58420 QuicTestPacketMaker* maker) {
421 return maker->MakeDataPacket(packet_number, stream_id,
Ryan Hamilton7505eb92019-06-08 00:22:17422 should_include_version, fin, data);
ckrasic3865ee0f2016-02-29 22:04:56423 }
424
Ryan Hamilton8d9ee76e2018-05-29 23:52:52425 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientDataPacket(
Fan Yangac867502019-01-28 21:10:23426 uint64_t packet_number,
[email protected]e8ff26842013-03-22 21:02:05427 bool should_include_version,
[email protected]f702d572012-12-04 15:56:20428 bool fin,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52429 quic::QuicStringPiece data) {
Ryan Hamilton7505eb92019-06-08 00:22:17430 return client_maker_.MakeDataPacket(packet_number, stream_id_,
431 should_include_version, fin, data);
alyssar2adf3ac2016-05-03 17:12:58432 }
433
Renjief49758b2019-01-11 23:32:41434 std::unique_ptr<quic::QuicReceivedPacket>
435 ConstructClientMultipleDataFramesPacket(
Fan Yangac867502019-01-28 21:10:23436 uint64_t packet_number,
Renjief49758b2019-01-11 23:32:41437 bool should_include_version,
438 bool fin,
Renjief49758b2019-01-11 23:32:41439 const std::vector<std::string>& data) {
440 return client_maker_.MakeMultipleDataFramesPacket(
Ryan Hamilton7505eb92019-06-08 00:22:17441 packet_number, stream_id_, should_include_version, fin, data);
Renjief49758b2019-01-11 23:32:41442 }
443
Ryan Hamilton8d9ee76e2018-05-29 23:52:52444 std::unique_ptr<quic::QuicReceivedPacket> ConstructServerDataPacket(
Fan Yangac867502019-01-28 21:10:23445 uint64_t packet_number,
alyssar2adf3ac2016-05-03 17:12:58446 bool should_include_version,
447 bool fin,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52448 quic::QuicStringPiece data) {
Ryan Hamilton7505eb92019-06-08 00:22:17449 return server_maker_.MakeDataPacket(packet_number, stream_id_,
450 should_include_version, fin, data);
ckrasic3865ee0f2016-02-29 22:04:56451 }
452
Ryan Hamilton8d9ee76e2018-05-29 23:52:52453 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23454 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52455 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56456 bool should_include_version,
457 bool fin,
458 RequestPriority request_priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02459 size_t* spdy_headers_frame_length) {
Yixin Wang7a3f1b8d2018-01-17 21:40:48460 return InnerConstructRequestHeadersPacket(
461 packet_number, stream_id, should_include_version, fin, request_priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02462 0, spdy_headers_frame_length);
Yixin Wang7a3f1b8d2018-01-17 21:40:48463 }
464
Ryan Hamilton8d9ee76e2018-05-29 23:52:52465 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23466 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52467 quic::QuicStreamId stream_id,
Yixin Wang7a3f1b8d2018-01-17 21:40:48468 bool should_include_version,
469 bool fin,
470 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52471 quic::QuicStreamId parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02472 size_t* spdy_headers_frame_length) {
Ryan Hamilton0239aac2018-05-19 00:03:13473 spdy::SpdyPriority priority =
ckrasic3865ee0f2016-02-29 22:04:56474 ConvertRequestPriorityToQuicPriority(request_priority);
alyssar2adf3ac2016-05-03 17:12:58475 return client_maker_.MakeRequestHeadersPacket(
ckrasic3865ee0f2016-02-29 22:04:56476 packet_number, stream_id, should_include_version, fin, priority,
Yixin Wang7a3f1b8d2018-01-17 21:40:48477 std::move(request_headers_), parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02478 spdy_headers_frame_length);
[email protected]f702d572012-12-04 15:56:20479 }
480
Ryan Hamilton8d9ee76e2018-05-29 23:52:52481 std::unique_ptr<quic::QuicReceivedPacket>
Yixin Wange7ecc472018-03-06 19:00:25482 ConstructRequestHeadersAndDataFramesPacket(
Fan Yangac867502019-01-28 21:10:23483 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52484 quic::QuicStreamId stream_id,
Yixin Wange7ecc472018-03-06 19:00:25485 bool should_include_version,
486 bool fin,
487 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52488 quic::QuicStreamId parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25489 size_t* spdy_headers_frame_length,
490 const std::vector<std::string>& data_writes) {
Ryan Hamilton0239aac2018-05-19 00:03:13491 spdy::SpdyPriority priority =
Yixin Wange7ecc472018-03-06 19:00:25492 ConvertRequestPriorityToQuicPriority(request_priority);
493 return client_maker_.MakeRequestHeadersAndMultipleDataFramesPacket(
494 packet_number, stream_id, should_include_version, fin, priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02495 std::move(request_headers_), parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25496 spdy_headers_frame_length, data_writes);
497 }
498
Ryan Hamilton8d9ee76e2018-05-29 23:52:52499 std::unique_ptr<quic::QuicReceivedPacket> ConstructRequestAndRstPacket(
Fan Yangac867502019-01-28 21:10:23500 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52501 quic::QuicStreamId stream_id,
Yixin Wange7ecc472018-03-06 19:00:25502 bool should_include_version,
503 bool fin,
504 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52505 quic::QuicStreamId parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25506 size_t* spdy_headers_frame_length,
Ryan Hamiltonb5d4c5a2019-06-21 22:08:41507 quic::QuicRstStreamErrorCode error_code) {
Ryan Hamilton0239aac2018-05-19 00:03:13508 spdy::SpdyPriority priority =
Yixin Wange7ecc472018-03-06 19:00:25509 ConvertRequestPriorityToQuicPriority(request_priority);
510 return client_maker_.MakeRequestHeadersAndRstPacket(
511 packet_number, stream_id, should_include_version, fin, priority,
512 std::move(request_headers_), parent_stream_id,
Ryan Hamiltonb5d4c5a2019-06-21 22:08:41513 spdy_headers_frame_length, error_code);
Yixin Wange7ecc472018-03-06 19:00:25514 }
515
Ryan Hamilton8d9ee76e2018-05-29 23:52:52516 std::unique_ptr<quic::QuicReceivedPacket> ConstructRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23517 uint64_t packet_number,
rtennetif4bdb542015-01-21 14:33:05518 bool fin,
sclittlec4dc1a32015-09-24 00:15:45519 RequestPriority request_priority,
520 size_t* spdy_headers_frame_length) {
ckrasic3865ee0f2016-02-29 22:04:56521 return InnerConstructRequestHeadersPacket(
522 packet_number, stream_id_, kIncludeVersion, fin, request_priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02523 spdy_headers_frame_length);
ckrasic3865ee0f2016-02-29 22:04:56524 }
525
Ryan Hamilton8d9ee76e2018-05-29 23:52:52526 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructResponseHeadersPacket(
Fan Yangac867502019-01-28 21:10:23527 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52528 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56529 bool fin,
530 size_t* spdy_headers_frame_length) {
alyssar2adf3ac2016-05-03 17:12:58531 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26532 packet_number, stream_id, !kIncludeVersion, fin,
Ryan Hamilton0d65a8c2019-06-07 00:46:02533 std::move(response_headers_), spdy_headers_frame_length);
[email protected]1e960032013-12-20 19:00:20534 }
535
Ryan Hamilton8d9ee76e2018-05-29 23:52:52536 std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseHeadersPacket(
Fan Yangac867502019-01-28 21:10:23537 uint64_t packet_number,
sclittlec4dc1a32015-09-24 00:15:45538 bool fin,
539 size_t* spdy_headers_frame_length) {
ckrasic3865ee0f2016-02-29 22:04:56540 return InnerConstructResponseHeadersPacket(packet_number, stream_id_, fin,
541 spdy_headers_frame_length);
[email protected]1e960032013-12-20 19:00:20542 }
543
Ryan Hamilton8d9ee76e2018-05-29 23:52:52544 std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseTrailersPacket(
Fan Yangac867502019-01-28 21:10:23545 uint64_t packet_number,
xunjieli34291fe12016-03-02 13:58:38546 bool fin,
Ryan Hamilton0239aac2018-05-19 00:03:13547 spdy::SpdyHeaderBlock trailers,
Ryan Hamilton0d65a8c2019-06-07 00:46:02548 size_t* spdy_headers_frame_length) {
alyssar2adf3ac2016-05-03 17:12:58549 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26550 packet_number, stream_id_, !kIncludeVersion, fin, std::move(trailers),
Ryan Hamilton0d65a8c2019-06-07 00:46:02551 spdy_headers_frame_length);
xunjieli34291fe12016-03-02 13:58:38552 }
553
Ryan Hamilton8d9ee76e2018-05-29 23:52:52554 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientRstStreamPacket(
Fan Yangac867502019-01-28 21:10:23555 uint64_t packet_number) {
alyssara72f5352016-10-20 12:45:16556 return client_maker_.MakeRstPacket(packet_number, true, stream_id_,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52557 quic::QUIC_RST_ACKNOWLEDGEMENT);
[email protected]06ff5152013-08-29 01:03:05558 }
559
Ryan Hamilton8d9ee76e2018-05-29 23:52:52560 std::unique_ptr<quic::QuicReceivedPacket>
Fan Yangac867502019-01-28 21:10:23561 ConstructClientRstStreamCancelledPacket(uint64_t packet_number) {
alyssar2adf3ac2016-05-03 17:12:58562 return client_maker_.MakeRstPacket(packet_number, !kIncludeVersion,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52563 stream_id_, quic::QUIC_STREAM_CANCELLED);
rtenneti6bd660b2015-07-18 00:19:53564 }
565
Ryan Hamilton8d9ee76e2018-05-29 23:52:52566 std::unique_ptr<quic::QuicReceivedPacket>
Fan Yangac867502019-01-28 21:10:23567 ConstructClientRstStreamVaryMismatchPacket(uint64_t packet_number) {
alyssar2adf3ac2016-05-03 17:12:58568 return client_maker_.MakeRstPacket(packet_number, !kIncludeVersion,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52569 promise_id_,
570 quic::QUIC_PROMISE_VARY_MISMATCH);
ckrasic3865ee0f2016-02-29 22:04:56571 }
572
Fan Yang550c6282018-06-22 18:53:25573 std::unique_ptr<quic::QuicReceivedPacket>
574 ConstructClientRstStreamVaryMismatchAndRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23575 uint64_t packet_number,
Fan Yang550c6282018-06-22 18:53:25576 quic::QuicStreamId stream_id,
577 bool should_include_version,
578 bool fin,
579 RequestPriority request_priority,
580 quic::QuicStreamId parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02581 size_t* spdy_headers_frame_length) {
Fan Yang550c6282018-06-22 18:53:25582 spdy::SpdyPriority priority =
583 ConvertRequestPriorityToQuicPriority(request_priority);
584 return client_maker_.MakeRstAndRequestHeadersPacket(
585 packet_number, should_include_version, promise_id_,
586 quic::QUIC_PROMISE_VARY_MISMATCH, stream_id, fin, priority,
587 std::move(request_headers_), parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02588 spdy_headers_frame_length);
Fan Yang550c6282018-06-22 18:53:25589 }
590
Ryan Hamilton8d9ee76e2018-05-29 23:52:52591 std::unique_ptr<quic::QuicReceivedPacket> ConstructAckAndRstStreamPacket(
Fan Yangac867502019-01-28 21:10:23592 uint64_t packet_number,
593 uint64_t largest_received,
594 uint64_t smallest_received,
595 uint64_t least_unacked) {
alyssar2adf3ac2016-05-03 17:12:58596 return client_maker_.MakeAckAndRstPacket(
Ryan Hamilton8d9ee76e2018-05-29 23:52:52597 packet_number, !kIncludeVersion, stream_id_,
598 quic::QUIC_STREAM_CANCELLED, largest_received, smallest_received,
599 least_unacked, !kIncludeCongestionFeedback);
xunjieli34291fe12016-03-02 13:58:38600 }
601
Ryan Hamilton8d9ee76e2018-05-29 23:52:52602 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientRstStreamErrorPacket(
Fan Yangac867502019-01-28 21:10:23603 uint64_t packet_number,
maksim.sisov84e20c92016-06-23 08:49:34604 bool include_version) {
605 return client_maker_.MakeRstPacket(packet_number, include_version,
606 stream_id_,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52607 quic::QUIC_ERROR_PROCESSING_STREAM);
maksim.sisov84e20c92016-06-23 08:49:34608 }
609
Ryan Hamilton8d9ee76e2018-05-29 23:52:52610 std::unique_ptr<quic::QuicReceivedPacket> ConstructAckAndRstStreamPacket(
Fan Yangac867502019-01-28 21:10:23611 uint64_t packet_number) {
Renjie90e808e2019-01-24 07:24:04612 return ConstructAckAndRstStreamPacket(packet_number, 2, 1, 2);
[email protected]c5e1aca2014-01-30 04:03:04613 }
614
Ryan Hamilton8d9ee76e2018-05-29 23:52:52615 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientAckPacket(
Fan Yangac867502019-01-28 21:10:23616 uint64_t packet_number,
617 uint64_t largest_received,
618 uint64_t smallest_received,
619 uint64_t least_unacked) {
alyssar2adf3ac2016-05-03 17:12:58620 return client_maker_.MakeAckPacket(packet_number, largest_received,
wangyix6444ffe2017-04-25 17:49:49621 smallest_received, least_unacked,
alyssar2adf3ac2016-05-03 17:12:58622 !kIncludeCongestionFeedback);
623 }
624
Ryan Hamilton8d9ee76e2018-05-29 23:52:52625 std::unique_ptr<quic::QuicReceivedPacket> ConstructServerAckPacket(
Fan Yangac867502019-01-28 21:10:23626 uint64_t packet_number,
627 uint64_t largest_received,
628 uint64_t smallest_received,
629 uint64_t least_unacked) {
alyssar2adf3ac2016-05-03 17:12:58630 return server_maker_.MakeAckPacket(packet_number, largest_received,
wangyix6444ffe2017-04-25 17:49:49631 smallest_received, least_unacked,
alyssar2adf3ac2016-05-03 17:12:58632 !kIncludeCongestionFeedback);
[email protected]63534512012-12-23 18:49:00633 }
634
Ryan Hamilton8d9ee76e2018-05-29 23:52:52635 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientPriorityPacket(
Fan Yangac867502019-01-28 21:10:23636 uint64_t packet_number,
Yixin Wangb470bc882018-02-15 18:43:57637 bool should_include_version,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52638 quic::QuicStreamId id,
639 quic::QuicStreamId parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02640 RequestPriority request_priority) {
Yixin Wangb470bc882018-02-15 18:43:57641 return client_maker_.MakePriorityPacket(
642 packet_number, should_include_version, id, parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02643 ConvertRequestPriorityToQuicPriority(request_priority));
Yixin Wangb470bc882018-02-15 18:43:57644 }
645
Ryan Hamilton0d65a8c2019-06-07 00:46:02646 std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket() {
647 return client_maker_.MakeInitialSettingsPacket(1);
fayang3bcb8b502016-12-07 21:44:37648 }
649
Renjie Tangaadb84b2019-08-31 01:00:23650 std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket(
651 int packet_number) {
652 return client_maker_.MakeInitialSettingsPacket(packet_number);
653 }
654
Victor Vasiliev076657c2019-03-12 02:46:43655 std::string ConstructDataHeader(size_t body_len) {
Nick Harper23290b82019-05-02 00:02:56656 if (version_.transport_version != quic::QUIC_VERSION_99) {
Renjief49758b2019-01-11 23:32:41657 return "";
658 }
Renjief49758b2019-01-11 23:32:41659 std::unique_ptr<char[]> buffer;
Victor Vasiliev55d997922019-10-31 19:40:57660 auto header_length =
661 quic::HttpEncoder::SerializeDataFrameHeader(body_len, &buffer);
Victor Vasiliev076657c2019-03-12 02:46:43662 return std::string(buffer.get(), header_length);
Renjief49758b2019-01-11 23:32:41663 }
664
Ryan Hamilton8d9ee76e2018-05-29 23:52:52665 void ReceivePromise(quic::QuicStreamId id) {
666 auto headers = quic::test::AsHeaderList(push_promise_);
rch08e198572017-05-09 16:56:55667 QuicChromiumClientStream::Handle* stream =
ckrasic3865ee0f2016-02-29 22:04:56668 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
ckrasic32b17dcd2016-10-31 06:15:35669 stream->OnPromiseHeaderList(id, headers.uncompressed_header_bytes(),
670 headers);
ckrasic3865ee0f2016-02-29 22:04:56671 }
672
xunjieli84adaab2016-09-20 01:12:28673 void ExpectLoadTimingValid(const LoadTimingInfo& load_timing_info,
xunjieli100937eb52016-09-15 20:09:37674 bool session_reused) {
675 EXPECT_EQ(session_reused, load_timing_info.socket_reused);
xunjieli84adaab2016-09-20 01:12:28676 if (session_reused) {
677 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
678 } else {
679 ExpectConnectTimingHasTimes(
680 load_timing_info.connect_timing,
681 CONNECT_TIMING_HAS_SSL_TIMES | CONNECT_TIMING_HAS_DNS_TIMES);
682 }
683 ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info);
xunjieli100937eb52016-09-15 20:09:37684 }
685
Fan Yang32c5a112018-12-10 20:06:33686 quic::QuicStreamId GetNthClientInitiatedBidirectionalStreamId(int n) {
Nick Harper23290b82019-05-02 00:02:56687 return quic::test::GetNthClientInitiatedBidirectionalStreamId(
688 version_.transport_version, n);
ckrasicbf2f59c2017-05-04 23:54:36689 }
690
Fan Yang32c5a112018-12-10 20:06:33691 quic::QuicStreamId GetNthServerInitiatedUnidirectionalStreamId(int n) {
Nick Harper23290b82019-05-02 00:02:56692 return quic::test::GetNthServerInitiatedUnidirectionalStreamId(
693 version_.transport_version, n);
ckrasicbf2f59c2017-05-04 23:54:36694 }
695
Ryan Hamiltona1d1f4a2019-06-26 14:43:04696 QuicFlagSaver saver_;
697
Nick Harper23290b82019-05-02 00:02:56698 const quic::ParsedQuicVersion version_;
Yixin Wang079ad542018-01-11 04:06:05699 const bool client_headers_include_h2_stream_dependency_;
700
Matt Muellerd9342e3a2019-11-26 01:41:14701 RecordingBoundTestNetLog net_log_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52702 quic::test::MockSendAlgorithm* send_algorithm_;
[email protected]f702d572012-12-04 15:56:20703 scoped_refptr<TestTaskRunner> runner_;
danakjad1777e2016-04-16 00:56:42704 std::unique_ptr<MockWrite[]> mock_writes_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52705 quic::MockClock clock_;
[email protected]f702d572012-12-04 15:56:20706 TestQuicConnection* connection_;
danakjad1777e2016-04-16 00:56:42707 std::unique_ptr<QuicChromiumConnectionHelper> helper_;
rch16c74d1d2016-04-22 06:14:07708 std::unique_ptr<QuicChromiumAlarmFactory> alarm_factory_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52709 testing::StrictMock<quic::test::MockQuicConnectionVisitor> visitor_;
rch97827ee2017-05-24 23:49:12710 std::unique_ptr<UploadDataStream> upload_data_stream_;
danakjad1777e2016-04-16 00:56:42711 std::unique_ptr<QuicHttpStream> stream_;
[email protected]5db452202014-08-19 05:22:15712 TransportSecurityState transport_security_state_;
danakjad1777e2016-04-16 00:56:42713 std::unique_ptr<QuicChromiumClientSession> session_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52714 quic::QuicCryptoClientConfig crypto_config_;
[email protected]f702d572012-12-04 15:56:20715 TestCompletionCallback callback_;
716 HttpRequestInfo request_;
717 HttpRequestHeaders headers_;
718 HttpResponseInfo response_;
719 scoped_refptr<IOBufferWithSize> read_buffer_;
Ryan Hamilton0239aac2018-05-19 00:03:13720 spdy::SpdyHeaderBlock request_headers_;
721 spdy::SpdyHeaderBlock response_headers_;
bnc614a92d32016-04-04 13:56:07722 string request_data_;
723 string response_data_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52724 quic::QuicClientPushPromiseIndex push_promise_index_;
[email protected]f702d572012-12-04 15:56:20725
ckrasic3865ee0f2016-02-29 22:04:56726 // For server push testing
danakjad1777e2016-04-16 00:56:42727 std::unique_ptr<QuicHttpStream> promised_stream_;
Ryan Hamilton0239aac2018-05-19 00:03:13728 spdy::SpdyHeaderBlock push_promise_;
729 spdy::SpdyHeaderBlock promised_response_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52730 const quic::QuicStreamId promise_id_;
ckrasic3865ee0f2016-02-29 22:04:56731 string promise_url_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52732 const quic::QuicStreamId stream_id_;
ckrasic3865ee0f2016-02-29 22:04:56733
Ryan Hamilton8d9ee76e2018-05-29 23:52:52734 const quic::QuicConnectionId connection_id_;
alyssar2adf3ac2016-05-03 17:12:58735 QuicTestPacketMaker client_maker_;
736 QuicTestPacketMaker server_maker_;
[email protected]f702d572012-12-04 15:56:20737 IPEndPoint self_addr_;
738 IPEndPoint peer_addr_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52739 quic::test::MockRandom random_generator_;
rch03b7a202016-02-05 00:54:20740 ProofVerifyDetailsChromium verify_details_;
[email protected]e8ff26842013-03-22 21:02:05741 MockCryptoClientStreamFactory crypto_client_stream_factory_;
danakjad1777e2016-04-16 00:56:42742 std::unique_ptr<StaticSocketDataProvider> socket_data_;
Ryan Hamilton0d65a8c2019-06-07 00:46:02743 QuicPacketPrinter printer_;
[email protected]f702d572012-12-04 15:56:20744 std::vector<PacketToWrite> writes_;
745};
746
David Schinazi09e9a6012019-10-03 17:37:57747INSTANTIATE_TEST_SUITE_P(VersionIncludeStreamDependencySequence,
748 QuicHttpStreamTest,
749 ::testing::ValuesIn(GetTestParams()),
750 ::testing::PrintToStringParamName());
[email protected]1e960032013-12-20 19:00:20751
752TEST_P(QuicHttpStreamTest, RenewStreamForAuth) {
[email protected]ed3fc15d2013-03-08 18:37:44753 Initialize();
rtennetibe635732014-10-02 22:51:42754 EXPECT_EQ(nullptr, stream_->RenewStreamForAuth());
[email protected]f702d572012-12-04 15:56:20755}
756
mmenkebd84c392015-09-02 14:12:34757TEST_P(QuicHttpStreamTest, CanReuseConnection) {
[email protected]ed3fc15d2013-03-08 18:37:44758 Initialize();
mmenkebd84c392015-09-02 14:12:34759 EXPECT_FALSE(stream_->CanReuseConnection());
[email protected]f702d572012-12-04 15:56:20760}
761
jri231c2972016-03-08 19:50:11762TEST_P(QuicHttpStreamTest, DisableConnectionMigrationForStream) {
Zhongyi Shibb28b1f2018-07-18 02:41:26763 request_.load_flags |= LOAD_DISABLE_CONNECTION_MIGRATION_TO_CELLULAR;
jri231c2972016-03-08 19:50:11764 Initialize();
xunjieli5fafe142016-03-23 23:32:54765 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27766 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:54767 net_log_.bound(), callback_.callback()));
rch08e198572017-05-09 16:56:55768 QuicChromiumClientStream::Handle* client_stream =
jri231c2972016-03-08 19:50:11769 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
Zhongyi Shibb28b1f2018-07-18 02:41:26770 EXPECT_FALSE(client_stream->can_migrate_to_cellular_network());
jri231c2972016-03-08 19:50:11771}
772
[email protected]1e960032013-12-20 19:00:20773TEST_P(QuicHttpStreamTest, GetRequest) {
774 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:45775 size_t spdy_request_header_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:23776 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:25777 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:23778 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:37779 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23780 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
781 kIncludeVersion, kFin, DEFAULT_PRIORITY,
782 &spdy_request_header_frame_length));
fayang3bcb8b502016-12-07 21:44:37783
[email protected]f702d572012-12-04 15:56:20784 Initialize();
785
786 request_.method = "GET";
rchcd379012017-04-12 21:53:32787 request_.url = GURL("https://www.example.org/");
[email protected]f702d572012-12-04 15:56:20788
xunjieli100937eb52016-09-15 20:09:37789 // Make sure getting load timing from the stream early does not crash.
790 LoadTimingInfo load_timing_info;
791 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
792
xunjieli5fafe142016-03-23 23:32:54793 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27794 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:54795 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:02796 EXPECT_EQ(OK,
797 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20798
799 // Ack the request.
Renjie90e808e2019-01-24 07:24:04800 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]f702d572012-12-04 15:56:20801
robpercival214763f2016-07-01 23:27:01802 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
803 IsError(ERR_IO_PENDING));
[email protected]f702d572012-12-04 15:56:20804
bnc614a92d32016-04-04 13:56:07805 SetResponse("404 Not Found", string());
sclittlec4dc1a32015-09-24 00:15:45806 size_t spdy_response_header_frame_length;
807 ProcessPacket(ConstructResponseHeadersPacket(
808 2, kFin, &spdy_response_header_frame_length));
[email protected]f702d572012-12-04 15:56:20809
810 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:01811 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]cadac622013-06-11 16:46:36812 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:20813 EXPECT_EQ(404, response_.headers->response_code());
814 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
[email protected]6ed67432014-06-24 01:53:53815 EXPECT_FALSE(response_.response_time.is_null());
816 EXPECT_FALSE(response_.request_time.is_null());
[email protected]f702d572012-12-04 15:56:20817
818 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:02819 EXPECT_EQ(0,
820 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
821 callback_.callback()));
[email protected]f702d572012-12-04 15:56:20822 EXPECT_TRUE(stream_->IsResponseBodyComplete());
823 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:10824
xunjieli100937eb52016-09-15 20:09:37825 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
xunjieli84adaab2016-09-20 01:12:28826 ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
xunjieli100937eb52016-09-15 20:09:37827
sclittle1edeeb22015-09-02 20:46:10828 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:45829 // headers and payload.
830 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
831 stream_->GetTotalSentBytes());
832 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length),
833 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:20834}
835
xunjieli100937eb52016-09-15 20:09:37836TEST_P(QuicHttpStreamTest, LoadTimingTwoRequests) {
837 SetRequest("GET", "/", DEFAULT_PRIORITY);
838 size_t spdy_request_header_frame_length;
839
Renjie Tangaadb84b2019-08-31 01:00:23840 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:25841 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:23842 AddWrite(ConstructInitialSettingsPacket(packet_number++));
xunjieli100937eb52016-09-15 20:09:37843 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23844 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
845 kIncludeVersion, kFin, DEFAULT_PRIORITY,
846 &spdy_request_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37847
848 // SetRequest() again for second request as |request_headers_| was moved.
849 SetRequest("GET", "/", DEFAULT_PRIORITY);
850 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23851 packet_number++, GetNthClientInitiatedBidirectionalStreamId(1),
852 kIncludeVersion, kFin, DEFAULT_PRIORITY,
853 GetNthClientInitiatedBidirectionalStreamId(0),
Ryan Hamilton0d65a8c2019-06-07 00:46:02854 &spdy_request_header_frame_length));
Renjie Tangaadb84b2019-08-31 01:00:23855 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1,
856 2)); // Ack the responses.
xunjieli100937eb52016-09-15 20:09:37857
858 Initialize();
859
860 request_.method = "GET";
rchcd379012017-04-12 21:53:32861 request_.url = GURL("https://www.example.org/");
xunjieli100937eb52016-09-15 20:09:37862 // Start first request.
863 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27864 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli100937eb52016-09-15 20:09:37865 net_log_.bound(), callback_.callback()));
866 EXPECT_EQ(OK,
867 stream_->SendRequest(headers_, &response_, callback_.callback()));
868
869 // Start a second request.
Ryan Hamilton6c2a2a82017-12-15 02:06:28870 QuicHttpStream stream2(
871 session_->CreateHandle(HostPortPair("www.example.org", 443)));
xunjieli100937eb52016-09-15 20:09:37872 TestCompletionCallback callback2;
873 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27874 stream2.InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli100937eb52016-09-15 20:09:37875 net_log_.bound(), callback2.callback()));
876 EXPECT_EQ(OK,
877 stream2.SendRequest(headers_, &response_, callback2.callback()));
878
879 // Ack both requests.
Renjie90e808e2019-01-24 07:24:04880 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
xunjieli100937eb52016-09-15 20:09:37881
882 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
883 IsError(ERR_IO_PENDING));
884 size_t spdy_response_header_frame_length;
885 SetResponse("200 OK", string());
886 ProcessPacket(InnerConstructResponseHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33887 2, GetNthClientInitiatedBidirectionalStreamId(0), kFin,
ckrasicbf2f59c2017-05-04 23:54:36888 &spdy_response_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37889
890 // Now that the headers have been processed, the callback will return.
891 EXPECT_THAT(callback_.WaitForResult(), IsOk());
892 EXPECT_EQ(200, response_.headers->response_code());
893
894 // There is no body, so this should return immediately.
895 EXPECT_EQ(0,
896 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
897 callback_.callback()));
898 EXPECT_TRUE(stream_->IsResponseBodyComplete());
899
900 LoadTimingInfo load_timing_info;
901 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
xunjieli84adaab2016-09-20 01:12:28902 ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
xunjieli100937eb52016-09-15 20:09:37903
904 // SetResponse() again for second request as |response_headers_| was moved.
905 SetResponse("200 OK", string());
906 EXPECT_THAT(stream2.ReadResponseHeaders(callback2.callback()),
907 IsError(ERR_IO_PENDING));
908
909 ProcessPacket(InnerConstructResponseHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33910 3, GetNthClientInitiatedBidirectionalStreamId(1), kFin,
ckrasicbf2f59c2017-05-04 23:54:36911 &spdy_response_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37912
913 EXPECT_THAT(callback2.WaitForResult(), IsOk());
914
915 // There is no body, so this should return immediately.
916 EXPECT_EQ(0,
917 stream2.ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
918 callback2.callback()));
919 EXPECT_TRUE(stream2.IsResponseBodyComplete());
920
921 LoadTimingInfo load_timing_info2;
922 EXPECT_TRUE(stream2.GetLoadTimingInfo(&load_timing_info2));
xunjieli84adaab2016-09-20 01:12:28923 ExpectLoadTimingValid(load_timing_info2, /*session_reused=*/true);
xunjieli100937eb52016-09-15 20:09:37924}
925
xunjieli34291fe12016-03-02 13:58:38926// QuicHttpStream does not currently support trailers. It should ignore
927// trailers upon receiving them.
928TEST_P(QuicHttpStreamTest, GetRequestWithTrailers) {
929 SetRequest("GET", "/", DEFAULT_PRIORITY);
930 size_t spdy_request_header_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:23931 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:25932 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:23933 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:37934 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:23935 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
936 kIncludeVersion, kFin, DEFAULT_PRIORITY,
937 &spdy_request_header_frame_length));
938 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1,
939 2)); // Ack the data packet.
xunjieli34291fe12016-03-02 13:58:38940
941 Initialize();
942
943 request_.method = "GET";
rchcd379012017-04-12 21:53:32944 request_.url = GURL("https://www.example.org/");
xunjieli34291fe12016-03-02 13:58:38945
xunjieli5fafe142016-03-23 23:32:54946 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27947 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:54948 net_log_.bound(), callback_.callback()));
949
xunjieli34291fe12016-03-02 13:58:38950 EXPECT_EQ(OK,
951 stream_->SendRequest(headers_, &response_, callback_.callback()));
xunjieli34291fe12016-03-02 13:58:38952 // Ack the request.
Renjie90e808e2019-01-24 07:24:04953 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
xunjieli34291fe12016-03-02 13:58:38954
robpercival214763f2016-07-01 23:27:01955 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
956 IsError(ERR_IO_PENDING));
xunjieli34291fe12016-03-02 13:58:38957
bnc614a92d32016-04-04 13:56:07958 SetResponse("200 OK", string());
xunjieli34291fe12016-03-02 13:58:38959
960 // Send the response headers.
961 size_t spdy_response_header_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:02962 ProcessPacket(ConstructResponseHeadersPacket(
963 2, !kFin, &spdy_response_header_frame_length));
xunjieli34291fe12016-03-02 13:58:38964 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:01965 EXPECT_THAT(callback_.WaitForResult(), IsOk());
xunjieli34291fe12016-03-02 13:58:38966 ASSERT_TRUE(response_.headers.get());
967 EXPECT_EQ(200, response_.headers->response_code());
968 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
969 EXPECT_FALSE(response_.response_time.is_null());
970 EXPECT_FALSE(response_.request_time.is_null());
971
972 // Send the response body.
973 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:43974 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:17975 ProcessPacket(
976 ConstructServerDataPacket(3, false, !kFin, header + kResponseBody));
Ryan Hamilton0239aac2018-05-19 00:03:13977 spdy::SpdyHeaderBlock trailers;
xunjieli34291fe12016-03-02 13:58:38978 size_t spdy_trailers_frame_length;
979 trailers["foo"] = "bar";
Victor Vasiliev7da08172019-10-14 06:04:25980 if (!quic::VersionUsesHttp3(version_.transport_version)) {
Ryan Hamiltona1d1f4a2019-06-26 14:43:04981 trailers[quic::kFinalOffsetHeaderKey] =
982 base::NumberToString(strlen(kResponseBody) + header.length());
983 }
Ryan Hamilton0d65a8c2019-06-07 00:46:02984 ProcessPacket(ConstructResponseTrailersPacket(4, kFin, std::move(trailers),
985 &spdy_trailers_frame_length));
xunjieli34291fe12016-03-02 13:58:38986
987 // Make sure trailers are processed.
fdoray92e35a72016-06-10 15:54:55988 base::RunLoop().RunUntilIdle();
xunjieli34291fe12016-03-02 13:58:38989
990 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
991 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
992 callback_.callback()));
993 EXPECT_TRUE(stream_->IsResponseBodyComplete());
994
995 EXPECT_EQ(OK,
996 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
997 callback_.callback()));
998
999 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1000 EXPECT_TRUE(AtEof());
1001
1002 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
1003 // headers and payload.
1004 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
1005 stream_->GetTotalSentBytes());
Renjief49758b2019-01-11 23:32:411006 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length +
1007 strlen(kResponseBody) + header.length() +
1008 +spdy_trailers_frame_length),
1009 stream_->GetTotalReceivedBytes());
xunjieli5fafe142016-03-23 23:32:541010 // Check that NetLog was filled as expected.
Eric Roman79cc7552019-07-19 02:17:541011 auto entries = net_log_.GetEntries();
xunjieli5fafe142016-03-23 23:32:541012 size_t pos = ExpectLogContainsSomewhere(
1013 entries, /*min_offset=*/0,
mikecirone8b85c432016-09-08 19:11:001014 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
1015 NetLogEventPhase::NONE);
xunjieli5fafe142016-03-23 23:32:541016 pos = ExpectLogContainsSomewhere(
1017 entries, /*min_offset=*/pos,
mikecirone8b85c432016-09-08 19:11:001018 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
1019 NetLogEventPhase::NONE);
xunjieli5fafe142016-03-23 23:32:541020 ExpectLogContainsSomewhere(
1021 entries, /*min_offset=*/pos,
mikecirone8b85c432016-09-08 19:11:001022 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
1023 NetLogEventPhase::NONE);
xunjieli34291fe12016-03-02 13:58:381024}
1025
[email protected]3e7dca62013-09-10 16:14:231026// Regression test for http://crbug.com/288128
[email protected]1e960032013-12-20 19:00:201027TEST_P(QuicHttpStreamTest, GetRequestLargeResponse) {
1028 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451029 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231030 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251031 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231032 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371033 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231034 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1035 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1036 &spdy_request_headers_frame_length));
[email protected]3e7dca62013-09-10 16:14:231037 Initialize();
1038
1039 request_.method = "GET";
rchcd379012017-04-12 21:53:321040 request_.url = GURL("https://www.example.org/");
[email protected]3e7dca62013-09-10 16:14:231041
xunjieli5fafe142016-03-23 23:32:541042 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271043 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541044 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021045 EXPECT_EQ(OK,
1046 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:231047
1048 // Ack the request.
Renjie90e808e2019-01-24 07:24:041049 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]3e7dca62013-09-10 16:14:231050
robpercival214763f2016-07-01 23:27:011051 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1052 IsError(ERR_IO_PENDING));
[email protected]3e7dca62013-09-10 16:14:231053
bnc086b39e12016-06-24 13:05:261054 response_headers_[":status"] = "200 OK";
1055 response_headers_[":version"] = "HTTP/1.1";
1056 response_headers_["content-type"] = "text/plain";
1057 response_headers_["big6"] = string(1000, 'x'); // Lots of x's.
[email protected]3e7dca62013-09-10 16:14:231058
sclittlec4dc1a32015-09-24 00:15:451059 size_t spdy_response_headers_frame_length;
1060 ProcessPacket(ConstructResponseHeadersPacket(
1061 2, kFin, &spdy_response_headers_frame_length));
[email protected]3e7dca62013-09-10 16:14:231062
1063 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:011064 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]3e7dca62013-09-10 16:14:231065 ASSERT_TRUE(response_.headers.get());
1066 EXPECT_EQ(200, response_.headers->response_code());
1067 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1068
1069 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:021070 EXPECT_EQ(0,
1071 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1072 callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:231073 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1074 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101075
1076 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451077 // headers and payload.
1078 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1079 stream_->GetTotalSentBytes());
1080 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length),
1081 stream_->GetTotalReceivedBytes());
[email protected]3e7dca62013-09-10 16:14:231082}
1083
rchf9f103cbc2014-08-30 05:28:041084// Regression test for http://crbug.com/409101
1085TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendRequest) {
1086 SetRequest("GET", "/", DEFAULT_PRIORITY);
1087 Initialize();
1088
1089 request_.method = "GET";
rchcd379012017-04-12 21:53:321090 request_.url = GURL("https://www.example.org/");
rchf9f103cbc2014-08-30 05:28:041091
xunjieli5fafe142016-03-23 23:32:541092 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271093 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541094 net_log_.bound(), callback_.callback()));
rchf9f103cbc2014-08-30 05:28:041095
jri78ec06a2016-03-31 18:19:401096 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521097 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rchf9f103cbc2014-08-30 05:28:041098
1099 EXPECT_EQ(ERR_CONNECTION_CLOSED,
rjshaded5ced072015-12-18 19:26:021100 stream_->SendRequest(headers_, &response_, callback_.callback()));
sclittle1edeeb22015-09-02 20:46:101101
1102 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1103 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rchf9f103cbc2014-08-30 05:28:041104}
1105
rch03b7a202016-02-05 00:54:201106// Regression test for http://crbug.com/584441
1107TEST_P(QuicHttpStreamTest, GetSSLInfoAfterSessionClosed) {
1108 SetRequest("GET", "/", DEFAULT_PRIORITY);
1109 Initialize();
1110
1111 request_.method = "GET";
rchcd379012017-04-12 21:53:321112 request_.url = GURL("https://www.example.org/");
rch03b7a202016-02-05 00:54:201113
xunjieli5fafe142016-03-23 23:32:541114 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271115 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541116 net_log_.bound(), callback_.callback()));
rch03b7a202016-02-05 00:54:201117
1118 SSLInfo ssl_info;
rch11565e02016-02-09 20:13:471119 EXPECT_FALSE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:201120 stream_->GetSSLInfo(&ssl_info);
rch11565e02016-02-09 20:13:471121 EXPECT_TRUE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:201122
jri78ec06a2016-03-31 18:19:401123 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521124 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rch03b7a202016-02-05 00:54:201125
rch11565e02016-02-09 20:13:471126 SSLInfo ssl_info2;
1127 stream_->GetSSLInfo(&ssl_info2);
1128 EXPECT_TRUE(ssl_info2.is_valid());
rch03b7a202016-02-05 00:54:201129}
1130
rchcd379012017-04-12 21:53:321131TEST_P(QuicHttpStreamTest, GetAlternativeService) {
1132 SetRequest("GET", "/", DEFAULT_PRIORITY);
1133 Initialize();
1134
1135 request_.method = "GET";
1136 request_.url = GURL("https://www.example.org/");
1137
1138 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271139 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
rchcd379012017-04-12 21:53:321140 net_log_.bound(), callback_.callback()));
1141
1142 AlternativeService alternative_service;
1143 EXPECT_TRUE(stream_->GetAlternativeService(&alternative_service));
1144 EXPECT_EQ(AlternativeService(kProtoQUIC, "www.example.org", 443),
1145 alternative_service);
1146
1147 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521148 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rchcd379012017-04-12 21:53:321149
1150 AlternativeService alternative_service2;
1151 EXPECT_TRUE(stream_->GetAlternativeService(&alternative_service2));
1152 EXPECT_EQ(AlternativeService(kProtoQUIC, "www.example.org", 443),
1153 alternative_service2);
1154}
1155
zhongyica364fbb2015-12-12 03:39:121156TEST_P(QuicHttpStreamTest, LogGranularQuicConnectionError) {
1157 SetRequest("GET", "/", DEFAULT_PRIORITY);
1158 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231159 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251160 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231161 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371162 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231163 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1164 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1165 &spdy_request_headers_frame_length));
fayang3bcb8b502016-12-07 21:44:371166 AddWrite(ConstructAckAndRstStreamPacket(3));
zhongyica364fbb2015-12-12 03:39:121167 Initialize();
1168
1169 request_.method = "GET";
rchcd379012017-04-12 21:53:321170 request_.url = GURL("https://www.example.org/");
zhongyica364fbb2015-12-12 03:39:121171
xunjieli5fafe142016-03-23 23:32:541172 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271173 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541174 net_log_.bound(), callback_.callback()));
zhongyica364fbb2015-12-12 03:39:121175 EXPECT_EQ(OK,
1176 stream_->SendRequest(headers_, &response_, callback_.callback()));
1177
1178 // Ack the request.
Renjie90e808e2019-01-24 07:24:041179 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011180 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1181 IsError(ERR_IO_PENDING));
zhongyica364fbb2015-12-12 03:39:121182
Ryan Hamilton8d9ee76e2018-05-29 23:52:521183 quic::QuicConnectionCloseFrame frame;
Zhongyi Shica576df2019-04-12 17:43:401184 frame.quic_error_code = quic::QUIC_PEER_GOING_AWAY;
Renjie Tangdb47d4c2019-08-27 18:56:231185 frame.extracted_error_code = quic::QUIC_PEER_GOING_AWAY;
rch1c5b74a2016-06-23 22:10:551186 session_->connection()->OnConnectionCloseFrame(frame);
zhongyica364fbb2015-12-12 03:39:121187
1188 NetErrorDetails details;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521189 EXPECT_EQ(quic::QUIC_NO_ERROR, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121190 stream_->PopulateNetErrorDetails(&details);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521191 EXPECT_EQ(quic::QUIC_PEER_GOING_AWAY, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121192}
1193
Ryan Hamiltone316e482017-08-17 02:48:531194TEST_P(QuicHttpStreamTest, LogGranularQuicErrorIfHandshakeNotConfirmed) {
Ryan Hamiltona1d1f4a2019-06-26 14:43:041195 // TODO(nharper): Figure out why this test does not send packets
1196 // when TLS is used.
1197 if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
1198 Initialize();
1199
1200 return;
1201 }
1202
rch617e0652017-04-26 17:57:511203 // By default the test setup defaults handshake to be confirmed. Manually set
1204 // it to be not confirmed.
rch617e0652017-04-26 17:57:511205 crypto_client_stream_factory_.set_handshake_mode(
Ryan Hamilton9835e662018-08-02 05:36:271206 MockCryptoClientStream::ZERO_RTT);
rch617e0652017-04-26 17:57:511207
zhongyica364fbb2015-12-12 03:39:121208 SetRequest("GET", "/", DEFAULT_PRIORITY);
1209 size_t spdy_request_headers_frame_length;
Michael Warres167db3e2019-03-01 21:38:031210 client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
Nick Harper057264a82019-09-12 23:33:491211 client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
1212 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251213 if (VersionUsesHttp3(version_.transport_version))
Nick Harper057264a82019-09-12 23:33:491214 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371215 AddWrite(InnerConstructRequestHeadersPacket(
Nick Harper057264a82019-09-12 23:33:491216 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1217 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1218 &spdy_request_headers_frame_length));
zhongyica364fbb2015-12-12 03:39:121219 Initialize();
1220
1221 request_.method = "GET";
rchcd379012017-04-12 21:53:321222 request_.url = GURL("https://www.example.org/");
zhongyica364fbb2015-12-12 03:39:121223
xunjieli5fafe142016-03-23 23:32:541224 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271225 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541226 net_log_.bound(), callback_.callback()));
zhongyica364fbb2015-12-12 03:39:121227 EXPECT_EQ(OK,
1228 stream_->SendRequest(headers_, &response_, callback_.callback()));
1229
1230 // Ack the request.
Renjie90e808e2019-01-24 07:24:041231 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011232 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1233 IsError(ERR_IO_PENDING));
zhongyica364fbb2015-12-12 03:39:121234
Ryan Hamilton8d9ee76e2018-05-29 23:52:521235 quic::QuicConnectionCloseFrame frame;
Zhongyi Shica576df2019-04-12 17:43:401236 frame.quic_error_code = quic::QUIC_PEER_GOING_AWAY;
Renjie Tangdb47d4c2019-08-27 18:56:231237 frame.extracted_error_code = quic::QUIC_PEER_GOING_AWAY;
rch1c5b74a2016-06-23 22:10:551238 session_->connection()->OnConnectionCloseFrame(frame);
zhongyica364fbb2015-12-12 03:39:121239
1240 NetErrorDetails details;
zhongyica364fbb2015-12-12 03:39:121241 stream_->PopulateNetErrorDetails(&details);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521242 EXPECT_EQ(quic::QUIC_PEER_GOING_AWAY, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121243}
1244
rch11a114a2014-09-04 23:41:591245// Regression test for http://crbug.com/409871
1246TEST_P(QuicHttpStreamTest, SessionClosedBeforeReadResponseHeaders) {
1247 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451248 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231249 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251250 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231251 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371252 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231253 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1254 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1255 &spdy_request_headers_frame_length));
rch11a114a2014-09-04 23:41:591256 Initialize();
1257
1258 request_.method = "GET";
rchcd379012017-04-12 21:53:321259 request_.url = GURL("https://www.example.org/");
rch11a114a2014-09-04 23:41:591260
xunjieli5fafe142016-03-23 23:32:541261 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271262 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541263 net_log_.bound(), callback_.callback()));
rch11a114a2014-09-04 23:41:591264
rjshaded5ced072015-12-18 19:26:021265 EXPECT_EQ(OK,
1266 stream_->SendRequest(headers_, &response_, callback_.callback()));
rch11a114a2014-09-04 23:41:591267
jri78ec06a2016-03-31 18:19:401268 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521269 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rch11a114a2014-09-04 23:41:591270
1271 EXPECT_NE(OK, stream_->ReadResponseHeaders(callback_.callback()));
sclittle1edeeb22015-09-02 20:46:101272
1273 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451274 // headers and payload.
1275 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1276 stream_->GetTotalSentBytes());
sclittle1edeeb22015-09-02 20:46:101277 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rch11a114a2014-09-04 23:41:591278}
1279
[email protected]1e960032013-12-20 19:00:201280TEST_P(QuicHttpStreamTest, SendPostRequest) {
1281 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451282 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231283 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251284 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231285 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Yixin Wange7ecc472018-03-06 19:00:251286
Victor Vasiliev076657c2019-03-12 02:46:431287 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harper23290b82019-05-02 00:02:561288 if (version_.transport_version != quic::QUIC_VERSION_99) {
Renjief49758b2019-01-11 23:32:411289 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231290 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1291 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1292 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411293 } else {
1294 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231295 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1296 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1297 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411298 }
Yixin Wange7ecc472018-03-06 19:00:251299
Renjie Tangaadb84b2019-08-31 01:00:231300 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1, 2));
[email protected]f702d572012-12-04 15:56:201301
1302 Initialize();
1303
danakjad1777e2016-04-16 00:56:421304 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:191305 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
ricea2deef682016-09-09 08:04:071306 kUploadData, strlen(kUploadData)));
rch97827ee2017-05-24 23:49:121307 upload_data_stream_ =
Jeremy Roman0579ed62017-08-29 15:56:191308 std::make_unique<ElementsUploadDataStream>(std::move(element_readers), 0);
[email protected]f702d572012-12-04 15:56:201309 request_.method = "POST";
rchcd379012017-04-12 21:53:321310 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121311 request_.upload_data_stream = upload_data_stream_.get();
Bence Békyd8a21fc32018-06-27 18:29:581312 ASSERT_THAT(request_.upload_data_stream->Init(CompletionOnceCallback(),
tfarina42834112016-09-22 13:38:201313 NetLogWithSource()),
1314 IsOk());
[email protected]f702d572012-12-04 15:56:201315
xunjieli5fafe142016-03-23 23:32:541316 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271317 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541318 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021319 EXPECT_EQ(OK,
1320 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:201321
1322 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041323 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]f702d572012-12-04 15:56:201324
1325 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071326 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451327 size_t spdy_response_headers_frame_length;
1328 ProcessPacket(ConstructResponseHeadersPacket(
1329 2, !kFin, &spdy_response_headers_frame_length));
[email protected]f702d572012-12-04 15:56:201330
rchfb47f712017-05-21 03:24:001331 // The headers have already arrived.
1332 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]cadac622013-06-11 16:46:361333 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:201334 EXPECT_EQ(200, response_.headers->response_code());
1335 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1336
1337 // Send the response body.
1338 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431339 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:411340 ProcessPacket(
Ryan Hamilton7505eb92019-06-08 00:22:171341 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
[email protected]f702d572012-12-04 15:56:201342 // Since the body has already arrived, this should return immediately.
1343 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
1344 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1345 callback_.callback()));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291346 EXPECT_EQ(0,
1347 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1348 callback_.callback()));
1349
1350 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1351 EXPECT_TRUE(AtEof());
1352
1353 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
1354 // headers and payload.
1355 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411356 strlen(kUploadData) + header.length()),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291357 stream_->GetTotalSentBytes());
1358 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411359 strlen(kResponseBody) + header2.length()),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291360 stream_->GetTotalReceivedBytes());
1361}
1362
1363TEST_P(QuicHttpStreamTest, SendPostRequestAndReceiveSoloFin) {
1364 SetRequest("POST", "/", DEFAULT_PRIORITY);
1365 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231366 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251367 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231368 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431369 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harper23290b82019-05-02 00:02:561370 if (version_.transport_version != quic::QUIC_VERSION_99) {
Renjief49758b2019-01-11 23:32:411371 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231372 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1373 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1374 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411375 } else {
1376 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231377 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1378 kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
1379 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411380 }
1381
Renjie Tangaadb84b2019-08-31 01:00:231382 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1, 2));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291383
1384 Initialize();
1385
1386 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:191387 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
Ryan Hamilton2ef0a9c2017-07-25 03:18:291388 kUploadData, strlen(kUploadData)));
1389 upload_data_stream_ =
Jeremy Roman0579ed62017-08-29 15:56:191390 std::make_unique<ElementsUploadDataStream>(std::move(element_readers), 0);
Ryan Hamilton2ef0a9c2017-07-25 03:18:291391 request_.method = "POST";
1392 request_.url = GURL("https://www.example.org/");
1393 request_.upload_data_stream = upload_data_stream_.get();
Bence Békyd8a21fc32018-06-27 18:29:581394 ASSERT_THAT(request_.upload_data_stream->Init(CompletionOnceCallback(),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291395 NetLogWithSource()),
1396 IsOk());
1397
1398 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271399 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
Ryan Hamilton2ef0a9c2017-07-25 03:18:291400 net_log_.bound(), callback_.callback()));
1401 EXPECT_EQ(OK,
1402 stream_->SendRequest(headers_, &response_, callback_.callback()));
1403
1404 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041405 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291406
1407 // Send the response headers (but not the body).
1408 SetResponse("200 OK", string());
1409 size_t spdy_response_headers_frame_length;
1410 ProcessPacket(ConstructResponseHeadersPacket(
1411 2, !kFin, &spdy_response_headers_frame_length));
1412
1413 // The headers have already arrived.
1414 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
1415 ASSERT_TRUE(response_.headers.get());
1416 EXPECT_EQ(200, response_.headers->response_code());
1417 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1418
1419 // Send the response body.
1420 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431421 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:411422 ProcessPacket(
Ryan Hamilton7505eb92019-06-08 00:22:171423 ConstructServerDataPacket(3, false, !kFin, header2 + kResponseBody));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291424 // Since the body has already arrived, this should return immediately.
1425 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
1426 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1427 callback_.callback()));
Ryan Hamilton7505eb92019-06-08 00:22:171428 ProcessPacket(ConstructServerDataPacket(4, false, kFin, ""));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291429 EXPECT_EQ(0,
1430 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1431 callback_.callback()));
[email protected]f702d572012-12-04 15:56:201432
1433 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1434 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101435
1436 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451437 // headers and payload.
1438 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411439 strlen(kUploadData) + header.length()),
sclittle1edeeb22015-09-02 20:46:101440 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451441 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411442 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101443 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:201444}
1445
[email protected]1e960032013-12-20 19:00:201446TEST_P(QuicHttpStreamTest, SendChunkedPostRequest) {
1447 SetRequest("POST", "/", DEFAULT_PRIORITY);
[email protected]c9e49a02013-02-26 05:56:471448 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:451449 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231450 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251451 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231452 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431453 std::string header = ConstructDataHeader(chunk_size);
Nick Harper23290b82019-05-02 00:02:561454 if (version_.transport_version == quic::QUIC_VERSION_99) {
Renjief49758b2019-01-11 23:32:411455 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231456 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1457 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1458 &spdy_request_headers_frame_length, {header, kUploadData}));
1459 AddWrite(ConstructClientMultipleDataFramesPacket(
1460 packet_number++, kIncludeVersion, kFin, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411461 } else {
1462 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231463 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1464 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1465 &spdy_request_headers_frame_length, {kUploadData}));
1466 AddWrite(ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin,
1467 kUploadData));
Renjief49758b2019-01-11 23:32:411468 }
1469
Renjie Tangaadb84b2019-08-31 01:00:231470 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1, 2));
[email protected]c9e49a02013-02-26 05:56:471471 Initialize();
1472
Jeremy Roman0579ed62017-08-29 15:56:191473 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121474 auto* chunked_upload_stream =
1475 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1476 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
[email protected]c9e49a02013-02-26 05:56:471477
1478 request_.method = "POST";
rchcd379012017-04-12 21:53:321479 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121480 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071481 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201482 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]c9e49a02013-02-26 05:56:471483
xunjieli5fafe142016-03-23 23:32:541484 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271485 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541486 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021487 ASSERT_EQ(ERR_IO_PENDING,
1488 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]c9e49a02013-02-26 05:56:471489
rch97827ee2017-05-24 23:49:121490 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
robpercival214763f2016-07-01 23:27:011491 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]c9e49a02013-02-26 05:56:471492
1493 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041494 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]c9e49a02013-02-26 05:56:471495
1496 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071497 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451498 size_t spdy_response_headers_frame_length;
1499 ProcessPacket(ConstructResponseHeadersPacket(
1500 2, !kFin, &spdy_response_headers_frame_length));
[email protected]c9e49a02013-02-26 05:56:471501
rchfb47f712017-05-21 03:24:001502 // The headers have already arrived.
1503 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]cadac622013-06-11 16:46:361504 ASSERT_TRUE(response_.headers.get());
[email protected]c9e49a02013-02-26 05:56:471505 EXPECT_EQ(200, response_.headers->response_code());
1506 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1507
1508 // Send the response body.
1509 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431510 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171511 ProcessPacket(
1512 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
[email protected]c9e49a02013-02-26 05:56:471513
1514 // Since the body has already arrived, this should return immediately.
1515 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1516 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1517 callback_.callback()));
1518
1519 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1520 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101521
1522 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451523 // headers and payload.
1524 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411525 strlen(kUploadData) * 2 + header.length() * 2),
sclittle1edeeb22015-09-02 20:46:101526 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451527 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411528 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101529 stream_->GetTotalReceivedBytes());
[email protected]c9e49a02013-02-26 05:56:471530}
1531
[email protected]16ba7742014-08-22 00:57:251532TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithFinalEmptyDataPacket) {
1533 SetRequest("POST", "/", DEFAULT_PRIORITY);
1534 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:451535 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231536 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251537 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231538 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431539 std::string header = ConstructDataHeader(chunk_size);
Renjief49758b2019-01-11 23:32:411540
Nick Harper23290b82019-05-02 00:02:561541 if (version_.transport_version != quic::QUIC_VERSION_99) {
Renjief49758b2019-01-11 23:32:411542 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231543 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1544 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1545 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411546 } else {
1547 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231548 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1549 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1550 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411551 }
Renjie Tangaadb84b2019-08-31 01:00:231552 AddWrite(
1553 ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin, ""));
1554 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1, 2));
[email protected]16ba7742014-08-22 00:57:251555 Initialize();
1556
Jeremy Roman0579ed62017-08-29 15:56:191557 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121558 auto* chunked_upload_stream =
1559 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1560 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
[email protected]16ba7742014-08-22 00:57:251561
1562 request_.method = "POST";
rchcd379012017-04-12 21:53:321563 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121564 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071565 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201566 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]16ba7742014-08-22 00:57:251567
xunjieli5fafe142016-03-23 23:32:541568 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271569 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541570 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021571 ASSERT_EQ(ERR_IO_PENDING,
1572 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251573
rch97827ee2017-05-24 23:49:121574 chunked_upload_stream->AppendData(nullptr, 0, true);
robpercival214763f2016-07-01 23:27:011575 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]16ba7742014-08-22 00:57:251576
Renjie90e808e2019-01-24 07:24:041577 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]16ba7742014-08-22 00:57:251578
1579 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071580 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451581 size_t spdy_response_headers_frame_length;
1582 ProcessPacket(ConstructResponseHeadersPacket(
1583 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251584
rchfb47f712017-05-21 03:24:001585 // The headers have already arrived.
1586 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]16ba7742014-08-22 00:57:251587 ASSERT_TRUE(response_.headers.get());
1588 EXPECT_EQ(200, response_.headers->response_code());
1589 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1590
1591 // Send the response body.
1592 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431593 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171594 ProcessPacket(
1595 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
[email protected]16ba7742014-08-22 00:57:251596
rchb27683c2015-07-29 23:53:501597 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251598 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1599 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1600 callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251601 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1602 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101603
1604 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451605 // headers and payload.
1606 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411607 strlen(kUploadData) + header.length()),
sclittle1edeeb22015-09-02 20:46:101608 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451609 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411610 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101611 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251612}
1613
1614TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithOneEmptyDataPacket) {
1615 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451616 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231617 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251618 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231619 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371620 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231621 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1622 kIncludeVersion, !kFin, DEFAULT_PRIORITY,
1623 &spdy_request_headers_frame_length));
1624 AddWrite(
1625 ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin, ""));
1626 AddWrite(ConstructClientAckPacket(packet_number++, 3, 1, 2));
[email protected]16ba7742014-08-22 00:57:251627 Initialize();
1628
Jeremy Roman0579ed62017-08-29 15:56:191629 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121630 auto* chunked_upload_stream =
1631 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
[email protected]16ba7742014-08-22 00:57:251632
1633 request_.method = "POST";
rchcd379012017-04-12 21:53:321634 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121635 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071636 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201637 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]16ba7742014-08-22 00:57:251638
xunjieli5fafe142016-03-23 23:32:541639 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271640 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541641 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021642 ASSERT_EQ(ERR_IO_PENDING,
1643 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251644
rch97827ee2017-05-24 23:49:121645 chunked_upload_stream->AppendData(nullptr, 0, true);
robpercival214763f2016-07-01 23:27:011646 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]16ba7742014-08-22 00:57:251647
Renjie90e808e2019-01-24 07:24:041648 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]16ba7742014-08-22 00:57:251649
1650 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071651 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451652 size_t spdy_response_headers_frame_length;
1653 ProcessPacket(ConstructResponseHeadersPacket(
1654 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251655
rchfb47f712017-05-21 03:24:001656 // The headers have already arrived.
1657 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]16ba7742014-08-22 00:57:251658 ASSERT_TRUE(response_.headers.get());
1659 EXPECT_EQ(200, response_.headers->response_code());
1660 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1661
1662 // Send the response body.
1663 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431664 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171665 ProcessPacket(
1666 ConstructServerDataPacket(3, false, kFin, header + kResponseBody));
[email protected]16ba7742014-08-22 00:57:251667
rchb27683c2015-07-29 23:53:501668 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251669 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1670 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1671 callback_.callback()));
1672
1673 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1674 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101675
1676 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451677 // headers and payload.
1678 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1679 stream_->GetTotalSentBytes());
1680 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411681 strlen(kResponseBody) + header.length()),
sclittle1edeeb22015-09-02 20:46:101682 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251683}
1684
[email protected]1e960032013-12-20 19:00:201685TEST_P(QuicHttpStreamTest, DestroyedEarly) {
1686 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451687 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231688 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251689 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231690 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371691 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231692 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1693 kIncludeVersion, kFin, DEFAULT_PRIORITY,
1694 &spdy_request_headers_frame_length));
1695 AddWrite(ConstructAckAndRstStreamPacket(packet_number++));
[email protected]63534512012-12-23 18:49:001696 Initialize();
1697
1698 request_.method = "GET";
rchcd379012017-04-12 21:53:321699 request_.url = GURL("https://www.example.org/");
[email protected]63534512012-12-23 18:49:001700
xunjieli5fafe142016-03-23 23:32:541701 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271702 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541703 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021704 EXPECT_EQ(OK,
1705 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]63534512012-12-23 18:49:001706
1707 // Ack the request.
Renjie90e808e2019-01-24 07:24:041708 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
rchfb47f712017-05-21 03:24:001709 EXPECT_THAT(stream_->ReadResponseHeaders(
Yannic Bonenberger3c96beb2019-09-03 20:41:371710 base::BindOnce(&QuicHttpStreamTest::CloseStream,
1711 base::Unretained(this), stream_.get())),
robpercival214763f2016-07-01 23:27:011712 IsError(ERR_IO_PENDING));
[email protected]63534512012-12-23 18:49:001713
1714 // Send the response with a body.
[email protected]1e960032013-12-20 19:00:201715 SetResponse("404 OK", "hello world!");
[email protected]63534512012-12-23 18:49:001716 // In the course of processing this packet, the QuicHttpStream close itself.
rchfb47f712017-05-21 03:24:001717 size_t response_size = 0;
rch1bcfddf22017-06-03 00:26:291718 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin, &response_size));
[email protected]63534512012-12-23 18:49:001719
fdoray92e35a72016-06-10 15:54:551720 base::RunLoop().RunUntilIdle();
rchb27683c2015-07-29 23:53:501721
[email protected]63534512012-12-23 18:49:001722 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101723
1724 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451725 // headers and payload.
1726 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1727 stream_->GetTotalSentBytes());
rchfb47f712017-05-21 03:24:001728 // The stream was closed after receiving the headers.
1729 EXPECT_EQ(static_cast<int64_t>(response_size),
1730 stream_->GetTotalReceivedBytes());
[email protected]63534512012-12-23 18:49:001731}
1732
[email protected]1e960032013-12-20 19:00:201733TEST_P(QuicHttpStreamTest, Priority) {
1734 SetRequest("GET", "/", MEDIUM);
sclittlec4dc1a32015-09-24 00:15:451735 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231736 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251737 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231738 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371739 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231740 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1741 kIncludeVersion, kFin, MEDIUM, &spdy_request_headers_frame_length));
[email protected]24e5bc52013-09-18 15:36:581742 Initialize();
1743
1744 request_.method = "GET";
rchcd379012017-04-12 21:53:321745 request_.url = GURL("https://www.example.org/");
[email protected]24e5bc52013-09-18 15:36:581746
Steven Valdezb4ff0412018-01-18 22:39:271747 EXPECT_EQ(OK,
1748 stream_->InitializeStream(&request_, true, MEDIUM, net_log_.bound(),
1749 callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581750
rjshaded5ced072015-12-18 19:26:021751 EXPECT_EQ(OK,
1752 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581753
[email protected]24e5bc52013-09-18 15:36:581754 // Ack the request.
Renjie90e808e2019-01-24 07:24:041755 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011756 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1757 IsError(ERR_IO_PENDING));
[email protected]24e5bc52013-09-18 15:36:581758
1759 // Send the response with a body.
[email protected]1e960032013-12-20 19:00:201760 SetResponse("404 OK", "hello world!");
rchfb47f712017-05-21 03:24:001761 size_t response_size = 0;
1762 ProcessPacket(ConstructResponseHeadersPacket(2, kFin, &response_size));
[email protected]24e5bc52013-09-18 15:36:581763
rchfb47f712017-05-21 03:24:001764 EXPECT_EQ(OK, callback_.WaitForResult());
rchb27683c2015-07-29 23:53:501765
[email protected]24e5bc52013-09-18 15:36:581766 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101767
1768 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451769 // headers and payload.
1770 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1771 stream_->GetTotalSentBytes());
rchfb47f712017-05-21 03:24:001772 EXPECT_EQ(static_cast<int64_t>(response_size),
1773 stream_->GetTotalReceivedBytes());
[email protected]24e5bc52013-09-18 15:36:581774}
1775
xunjieli8dff50b2016-07-22 14:19:061776TEST_P(QuicHttpStreamTest, SessionClosedDuringDoLoop) {
1777 SetRequest("POST", "/", DEFAULT_PRIORITY);
1778 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231779 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251780 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231781 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431782 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harper23290b82019-05-02 00:02:561783 if (version_.transport_version != quic::QUIC_VERSION_99) {
Renjief49758b2019-01-11 23:32:411784 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231785 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1786 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1787 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411788 } else {
1789 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231790 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1791 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1792 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411793 }
1794
xunjieli8dff50b2016-07-22 14:19:061795 // Second data write will result in a synchronous failure which will close
1796 // the session.
1797 AddWrite(SYNCHRONOUS, ERR_FAILED);
1798 Initialize();
1799
Jeremy Roman0579ed62017-08-29 15:56:191800 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121801 auto* chunked_upload_stream =
1802 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
xunjieli8dff50b2016-07-22 14:19:061803
1804 request_.method = "POST";
rchcd379012017-04-12 21:53:321805 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121806 request_.upload_data_stream = upload_data_stream_.get();
xunjieli8dff50b2016-07-22 14:19:061807 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201808 TestCompletionCallback().callback(), NetLogWithSource()));
xunjieli8dff50b2016-07-22 14:19:061809
1810 size_t chunk_size = strlen(kUploadData);
rch97827ee2017-05-24 23:49:121811 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
xunjieli8dff50b2016-07-22 14:19:061812 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271813 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli8dff50b2016-07-22 14:19:061814 net_log_.bound(), callback_.callback()));
1815 QuicHttpStream* stream = stream_.get();
1816 DeleteStreamCallback delete_stream_callback(std::move(stream_));
1817 // SendRequest() completes asynchronously after the final chunk is added.
Yixin Wange7ecc472018-03-06 19:00:251818 // Error does not surface yet since packet write is triggered by a packet
1819 // flusher that tries to bundle request body writes.
xunjieli8dff50b2016-07-22 14:19:061820 ASSERT_EQ(ERR_IO_PENDING,
1821 stream->SendRequest(headers_, &response_, callback_.callback()));
rch97827ee2017-05-24 23:49:121822 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
xunjieli8dff50b2016-07-22 14:19:061823 int rv = callback_.WaitForResult();
Yixin Wange7ecc472018-03-06 19:00:251824 EXPECT_EQ(OK, rv);
1825 // Error will be surfaced once an attempt to read the response occurs.
1826 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1827 stream->ReadResponseHeaders(callback_.callback()));
xunjieli8dff50b2016-07-22 14:19:061828}
1829
rtenneti15656ae2016-01-23 03:05:031830TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersComplete) {
1831 SetRequest("POST", "/", DEFAULT_PRIORITY);
Victor Vasiliev7da08172019-10-14 06:04:251832 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231833 AddWrite(ConstructInitialSettingsPacket());
rtenneti15656ae2016-01-23 03:05:031834 AddWrite(SYNCHRONOUS, ERR_FAILED);
1835 Initialize();
1836
Jeremy Roman0579ed62017-08-29 15:56:191837 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
Yixin Wange7ecc472018-03-06 19:00:251838 auto* chunked_upload_stream =
1839 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
rtenneti15656ae2016-01-23 03:05:031840
1841 request_.method = "POST";
rchcd379012017-04-12 21:53:321842 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121843 request_.upload_data_stream = upload_data_stream_.get();
rtenneti15656ae2016-01-23 03:05:031844 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201845 TestCompletionCallback().callback(), NetLogWithSource()));
rtenneti15656ae2016-01-23 03:05:031846
xunjieli5fafe142016-03-23 23:32:541847 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271848 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541849 net_log_.bound(), callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:251850 ASSERT_EQ(ERR_IO_PENDING,
rtenneti15656ae2016-01-23 03:05:031851 stream_->SendRequest(headers_, &response_, callback_.callback()));
mmenkeffff3642017-06-15 17:37:241852
Yixin Wange7ecc472018-03-06 19:00:251853 // Error will be surfaced once |upload_data_stream| triggers the next write.
1854 size_t chunk_size = strlen(kUploadData);
1855 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1856 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR, callback_.WaitForResult());
1857
1858 EXPECT_LE(0, stream_->GetTotalSentBytes());
1859 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1860}
1861
1862TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersCompleteReadResponse) {
1863 SetRequest("POST", "/", DEFAULT_PRIORITY);
Victor Vasiliev7da08172019-10-14 06:04:251864 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231865 AddWrite(ConstructInitialSettingsPacket());
Yixin Wange7ecc472018-03-06 19:00:251866 AddWrite(SYNCHRONOUS, ERR_FAILED);
1867 Initialize();
1868
1869 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
1870 auto* chunked_upload_stream =
1871 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1872
1873 request_.method = "POST";
1874 request_.url = GURL("https://www.example.org/");
1875 request_.upload_data_stream = upload_data_stream_.get();
1876
1877 size_t chunk_size = strlen(kUploadData);
1878 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1879
1880 ASSERT_EQ(OK, request_.upload_data_stream->Init(
1881 TestCompletionCallback().callback(), NetLogWithSource()));
1882
1883 ASSERT_EQ(OK,
1884 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1885 net_log_.bound(), callback_.callback()));
1886 ASSERT_EQ(OK,
1887 stream_->SendRequest(headers_, &response_, callback_.callback()));
1888
1889 // Error will be surfaced once an attempt to read the response occurs.
1890 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1891 stream_->ReadResponseHeaders(callback_.callback()));
1892
mmenkeffff3642017-06-15 17:37:241893 EXPECT_LE(0, stream_->GetTotalSentBytes());
1894 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rtenneti15656ae2016-01-23 03:05:031895}
1896
1897TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBodyComplete) {
1898 SetRequest("POST", "/", DEFAULT_PRIORITY);
1899 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231900 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251901 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231902 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:371903 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:231904 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1905 kIncludeVersion, !kFin, DEFAULT_PRIORITY,
1906 &spdy_request_headers_frame_length));
rtenneti15656ae2016-01-23 03:05:031907 AddWrite(SYNCHRONOUS, ERR_FAILED);
1908 Initialize();
1909
Jeremy Roman0579ed62017-08-29 15:56:191910 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121911 auto* chunked_upload_stream =
1912 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
rtenneti15656ae2016-01-23 03:05:031913
1914 request_.method = "POST";
rchcd379012017-04-12 21:53:321915 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121916 request_.upload_data_stream = upload_data_stream_.get();
rtenneti15656ae2016-01-23 03:05:031917 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201918 TestCompletionCallback().callback(), NetLogWithSource()));
rtenneti15656ae2016-01-23 03:05:031919
xunjieli5fafe142016-03-23 23:32:541920 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271921 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541922 net_log_.bound(), callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:251923 ASSERT_EQ(ERR_IO_PENDING,
rtenneti15656ae2016-01-23 03:05:031924 stream_->SendRequest(headers_, &response_, callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:251925
1926 size_t chunk_size = strlen(kUploadData);
1927 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1928 // Error does not surface yet since packet write is triggered by a packet
1929 // flusher that tries to bundle request body writes.
1930 ASSERT_EQ(OK, callback_.WaitForResult());
1931 // Error will be surfaced once an attempt to read the response occurs.
1932 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1933 stream_->ReadResponseHeaders(callback_.callback()));
1934
1935 EXPECT_LE(0, stream_->GetTotalSentBytes());
1936 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1937}
1938
1939TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBundledBodyComplete) {
1940 SetRequest("POST", "/", DEFAULT_PRIORITY);
1941 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:231942 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:251943 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:231944 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Victor Vasiliev076657c2019-03-12 02:46:431945 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harper23290b82019-05-02 00:02:561946 if (version_.transport_version != quic::QUIC_VERSION_99) {
Renjief49758b2019-01-11 23:32:411947 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231948 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1949 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1950 &spdy_request_headers_frame_length, {kUploadData}));
Renjief49758b2019-01-11 23:32:411951 } else {
1952 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
Renjie Tangaadb84b2019-08-31 01:00:231953 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
1954 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
1955 &spdy_request_headers_frame_length, {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411956 }
1957
Yixin Wange7ecc472018-03-06 19:00:251958 AddWrite(SYNCHRONOUS, ERR_FAILED);
1959 Initialize();
1960
1961 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
1962 auto* chunked_upload_stream =
1963 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1964
1965 request_.method = "POST";
1966 request_.url = GURL("https://www.example.org/");
1967 request_.upload_data_stream = upload_data_stream_.get();
1968
1969 size_t chunk_size = strlen(kUploadData);
1970 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
1971
1972 ASSERT_EQ(OK, request_.upload_data_stream->Init(
1973 TestCompletionCallback().callback(), NetLogWithSource()));
1974
1975 ASSERT_EQ(OK,
1976 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1977 net_log_.bound(), callback_.callback()));
1978 ASSERT_EQ(ERR_IO_PENDING,
1979 stream_->SendRequest(headers_, &response_, callback_.callback()));
1980
1981 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1982
1983 // Error does not surface yet since packet write is triggered by a packet
1984 // flusher that tries to bundle request body writes.
1985 ASSERT_EQ(OK, callback_.WaitForResult());
1986 // Error will be surfaced once an attempt to read the response occurs.
1987 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1988 stream_->ReadResponseHeaders(callback_.callback()));
1989
1990 EXPECT_LE(0, stream_->GetTotalSentBytes());
1991 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rtenneti15656ae2016-01-23 03:05:031992}
1993
ckrasic3865ee0f2016-02-29 22:04:561994TEST_P(QuicHttpStreamTest, ServerPushGetRequest) {
1995 SetRequest("GET", "/", DEFAULT_PRIORITY);
1996 Initialize();
1997
1998 // Initialize the first stream, for receiving the promise on.
1999 request_.method = "GET";
rchcd379012017-04-12 21:53:322000 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562001
xunjieli5fafe142016-03-23 23:32:542002 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272003 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542004 net_log_.bound(), callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232005 ASSERT_EQ(OK,
2006 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562007
2008 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2009 // packet, but does it matter?
2010 ReceivePromise(promise_id_);
2011 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2012
2013 request_.url = GURL(promise_url_);
2014
2015 // Make the second stream that will exercise the first step of the
2016 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272017 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2018 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2019 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562020
2021 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252022 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562023 size_t spdy_response_headers_frame_length;
2024 ProcessPacket(InnerConstructResponseHeadersPacket(
2025 1, promise_id_, false, &spdy_response_headers_frame_length));
2026
2027 // Receive the promised response body.
2028 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432029 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172030 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2031 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562032
2033 // Now sending a matching request will have successful rendezvous
2034 // with the promised stream.
Ryan Hamiltona1d1f4a2019-06-26 14:43:042035 ASSERT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
ckrasic3865ee0f2016-02-29 22:04:562036 callback_.callback()));
2037
2038 EXPECT_EQ(
2039 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2040 ->id(),
2041 promise_id_);
2042
2043 // The headers will be immediately available.
robpercival214763f2016-07-01 23:27:012044 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2045 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562046
2047 // As will be the body.
2048 EXPECT_EQ(
2049 static_cast<int>(strlen(kResponseBody)),
2050 promised_stream_->ReadResponseBody(
2051 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2052 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2053 EXPECT_TRUE(AtEof());
2054
ckrasic3865ee0f2016-02-29 22:04:562055 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2056 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412057 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562058 promised_stream_->GetTotalReceivedBytes());
2059}
2060
2061TEST_P(QuicHttpStreamTest, ServerPushGetRequestSlowResponse) {
2062 SetRequest("GET", "/", DEFAULT_PRIORITY);
2063 Initialize();
2064
2065 // Initialize the first stream, for receiving the promise on.
2066 request_.method = "GET";
rchcd379012017-04-12 21:53:322067 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562068
xunjieli5fafe142016-03-23 23:32:542069 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272070 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542071 net_log_.bound(), callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232072 ASSERT_EQ(OK,
2073 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562074
2075 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2076 // packet, but does it matter?
2077 ReceivePromise(promise_id_);
2078 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2079
2080 request_.url = GURL(promise_url_);
2081
2082 // Make the second stream that will exercise the first step of the
2083 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272084 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2085 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2086 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562087
2088 // Now sending a matching request will rendezvous with the promised
2089 // stream, but pending secondary validation.
2090 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2091 headers_, &response_, callback_.callback()));
2092
2093 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252094 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562095 size_t spdy_response_headers_frame_length;
2096 ProcessPacket(InnerConstructResponseHeadersPacket(
2097 1, promise_id_, false, &spdy_response_headers_frame_length));
2098
2099 // Receive the promised response body.
2100 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432101 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172102 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2103 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562104
fdoray92e35a72016-06-10 15:54:552105 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562106
2107 // Rendezvous should have succeeded now, so the promised stream
2108 // should point at our push stream, and we should be able read
2109 // headers and data from it.
robpercival214763f2016-07-01 23:27:012110 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562111
2112 EXPECT_EQ(
2113 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2114 ->id(),
2115 promise_id_);
2116
robpercival214763f2016-07-01 23:27:012117 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2118 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562119
2120 EXPECT_EQ(
2121 static_cast<int>(strlen(kResponseBody)),
2122 promised_stream_->ReadResponseBody(
2123 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2124
2125 // Callback should return
2126 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2127 EXPECT_TRUE(AtEof());
2128
ckrasic3865ee0f2016-02-29 22:04:562129 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2130 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412131 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562132 promised_stream_->GetTotalReceivedBytes());
2133}
2134
ckrasic2c63f9b2016-08-16 23:54:072135// Verify fix for crbug.com/637349
2136TEST_P(QuicHttpStreamTest, ServerPushCancelHttpStreamBeforeResponse) {
2137 SetRequest("GET", "/", DEFAULT_PRIORITY);
2138 Initialize();
2139
2140 // Initialize the first stream, for receiving the promise on.
2141 request_.method = "GET";
rchcd379012017-04-12 21:53:322142 request_.url = GURL("https://www.example.org/");
ckrasic2c63f9b2016-08-16 23:54:072143
2144 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272145 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
ckrasic2c63f9b2016-08-16 23:54:072146 net_log_.bound(), callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232147 ASSERT_EQ(OK,
2148 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic2c63f9b2016-08-16 23:54:072149
2150 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2151 // packet, but does it matter?
2152 ReceivePromise(promise_id_);
2153 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2154
2155 request_.url = GURL(promise_url_);
2156
2157 // Make the second stream that will exercise the first step of the
2158 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272159 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2160 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2161 callback_.callback()));
ckrasic2c63f9b2016-08-16 23:54:072162
2163 // Now sending a matching request will rendezvous with the promised
2164 // stream, but pending secondary validation.
2165 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2166 headers_, &response_, callback_.callback()));
2167
2168 base::RunLoop().RunUntilIdle();
2169
2170 // Cause of FinalValidation() crash as per bug.
2171 promised_stream_.reset();
2172
2173 // Receive the promised response headers.
2174 response_headers_ = promised_response_.Clone();
2175 size_t spdy_response_headers_frame_length;
2176 ProcessPacket(InnerConstructResponseHeadersPacket(
2177 1, promise_id_, false, &spdy_response_headers_frame_length));
2178}
2179
ckrasic3865ee0f2016-02-29 22:04:562180TEST_P(QuicHttpStreamTest, ServerPushCrossOriginOK) {
2181 SetRequest("GET", "/", DEFAULT_PRIORITY);
2182 Initialize();
2183
2184 // Initialize the first stream, for receiving the promise on.
2185 request_.method = "GET";
rchcd379012017-04-12 21:53:322186 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562187
xunjieli5fafe142016-03-23 23:32:542188 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272189 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542190 net_log_.bound(), callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232191 ASSERT_EQ(OK,
2192 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562193
2194 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2195 // packet, but does it matter?
2196
2197 push_promise_[":authority"] = "mail.example.org";
David Schinazi3f7465c2019-07-12 01:57:052198 promise_url_ =
2199 quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
ckrasic3865ee0f2016-02-29 22:04:562200
2201 ReceivePromise(promise_id_);
2202 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2203
2204 request_.url = GURL(promise_url_);
2205
2206 // Make the second stream that will exercise the first step of the
2207 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272208 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2209 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2210 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562211
2212 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252213 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562214 size_t spdy_response_headers_frame_length;
2215 ProcessPacket(InnerConstructResponseHeadersPacket(
2216 1, promise_id_, false, &spdy_response_headers_frame_length));
2217
2218 // Receive the promised response body.
2219 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432220 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172221 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2222 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562223
2224 // Now sending a matching request will have successful rendezvous
2225 // with the promised stream.
2226 EXPECT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
2227 callback_.callback()));
2228
2229 EXPECT_EQ(
2230 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2231 ->id(),
2232 promise_id_);
2233
2234 // The headers will be immediately available.
robpercival214763f2016-07-01 23:27:012235 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2236 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562237
2238 // As will be the body.
2239 EXPECT_EQ(
2240 static_cast<int>(strlen(kResponseBody)),
2241 promised_stream_->ReadResponseBody(
2242 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2243 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2244 EXPECT_TRUE(AtEof());
2245
ckrasic3865ee0f2016-02-29 22:04:562246 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2247 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412248 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562249 promised_stream_->GetTotalReceivedBytes());
2250}
2251
2252TEST_P(QuicHttpStreamTest, ServerPushCrossOriginFail) {
2253 SetRequest("GET", "/", DEFAULT_PRIORITY);
2254 Initialize();
2255
2256 // Initialize the first stream, for receiving the promise on.
2257 request_.method = "GET";
rchcd379012017-04-12 21:53:322258 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562259
xunjieli5fafe142016-03-23 23:32:542260 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272261 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542262 net_log_.bound(), callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232263 ASSERT_EQ(OK,
2264 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562265
2266 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2267 // packet, but does it matter?
2268 push_promise_[":authority"] = "www.notexample.org";
David Schinazi3f7465c2019-07-12 01:57:052269 promise_url_ =
2270 quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
ckrasic3865ee0f2016-02-29 22:04:562271
2272 ReceivePromise(promise_id_);
2273 // The promise will have been rejected because the cert doesn't
2274 // match.
2275 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
2276}
2277
2278TEST_P(QuicHttpStreamTest, ServerPushVaryCheckOK) {
2279 SetRequest("GET", "/", DEFAULT_PRIORITY);
2280 Initialize();
2281
2282 // Initialize the first stream, for receiving the promise on.
2283 request_.method = "GET";
rchcd379012017-04-12 21:53:322284 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562285
xunjieli5fafe142016-03-23 23:32:542286 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272287 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542288 net_log_.bound(), callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232289 ASSERT_EQ(OK,
2290 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562291
2292 push_promise_["accept-encoding"] = "gzip";
ckrasic3865ee0f2016-02-29 22:04:562293
2294 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2295 // packet, but does it matter?
2296 ReceivePromise(promise_id_);
2297 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2298
2299 request_.url = GURL(promise_url_);
2300
2301 // Make the second stream that will exercise the first step of the
2302 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272303 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2304 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2305 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562306
2307 headers_.SetHeader("accept-encoding", "gzip");
2308
2309 // Now sending a matching request will rendezvous with the promised
2310 // stream, but pending secondary validation.
2311 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2312 headers_, &response_, callback_.callback()));
2313
2314 // Receive the promised response headers.
2315 promised_response_["vary"] = "accept-encoding";
bnc94893a72016-06-30 13:45:252316 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562317 size_t spdy_response_headers_frame_length;
2318 ProcessPacket(InnerConstructResponseHeadersPacket(
2319 1, promise_id_, false, &spdy_response_headers_frame_length));
2320
2321 // Receive the promised response body.
2322 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432323 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172324 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2325 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562326
fdoray92e35a72016-06-10 15:54:552327 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562328
2329 // Rendezvous should have succeeded now, so the promised stream
2330 // should point at our push stream, and we should be able read
2331 // headers and data from it.
robpercival214763f2016-07-01 23:27:012332 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562333
2334 EXPECT_EQ(
2335 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2336 ->id(),
2337 promise_id_);
2338
robpercival214763f2016-07-01 23:27:012339 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2340 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562341
2342 EXPECT_EQ(
2343 static_cast<int>(strlen(kResponseBody)),
2344 promised_stream_->ReadResponseBody(
2345 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2346
2347 // Callback should return
2348 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2349 EXPECT_TRUE(AtEof());
2350
ckrasic3865ee0f2016-02-29 22:04:562351 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2352 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412353 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562354 promised_stream_->GetTotalReceivedBytes());
2355}
2356
2357TEST_P(QuicHttpStreamTest, ServerPushVaryCheckFail) {
2358 SetRequest("GET", "/", DEFAULT_PRIORITY);
2359 request_headers_[":scheme"] = "https";
2360 request_headers_[":path"] = "/bar";
2361 request_headers_["accept-encoding"] = "sdch";
2362
ckrasic3865ee0f2016-02-29 22:04:562363 Initialize();
2364
2365 // Initialize the first stream, for receiving the promise on.
2366 request_.method = "GET";
rchcd379012017-04-12 21:53:322367 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562368
xunjieli5fafe142016-03-23 23:32:542369 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272370 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542371 net_log_.bound(), callback_.callback()));
Renjie Tangaadb84b2019-08-31 01:00:232372 ASSERT_EQ(OK,
2373 stream_->SendRequest(headers_, &response_, callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562374
2375 push_promise_["accept-encoding"] = "gzip";
ckrasic3865ee0f2016-02-29 22:04:562376
2377 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2378 // packet, but does it matter?
2379 ReceivePromise(promise_id_);
2380 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2381
2382 request_.url = GURL(promise_url_);
2383
2384 // Make the second stream that will exercise the first step of the
2385 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272386 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2387 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2388 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562389
2390 headers_.SetHeader("accept-encoding", "sdch");
2391
2392 // Now sending a matching request will rendezvous with the promised
2393 // stream, but pending secondary validation.
2394 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2395 headers_, &response_, callback_.callback()));
2396
2397 // Receive the promised response headers.
2398 promised_response_["vary"] = "accept-encoding";
bnc94893a72016-06-30 13:45:252399 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562400 size_t spdy_response_headers_frame_length;
2401 ProcessPacket(InnerConstructResponseHeadersPacket(
2402 1, promise_id_, false, &spdy_response_headers_frame_length));
2403
fdoray92e35a72016-06-10 15:54:552404 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562405
2406 // Rendezvous should have failed due to vary mismatch, so the
2407 // promised stream should have been aborted, and instead we have a
2408 // new, regular client initiated stream.
robpercival214763f2016-07-01 23:27:012409 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562410
2411 // Not a server-initiated stream.
2412 EXPECT_NE(
2413 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2414 ->id(),
2415 promise_id_);
2416
2417 // Instead, a new client-initiated stream.
2418 EXPECT_EQ(
2419 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2420 ->id(),
Nick Harper23290b82019-05-02 00:02:562421 stream_id_ + quic::QuicUtils::StreamIdDelta(version_.transport_version));
ckrasic3865ee0f2016-02-29 22:04:562422
2423 // After rendezvous failure, the push stream has been cancelled.
2424 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
2425
2426 // The rest of the test verifies that the retried as
2427 // client-initiated version of |promised_stream_| works as intended.
2428
2429 // Ack the request.
Renjie90e808e2019-01-24 07:24:042430 ProcessPacket(ConstructServerAckPacket(2, 1, 1, 1));
ckrasic3865ee0f2016-02-29 22:04:562431
bnc614a92d32016-04-04 13:56:072432 SetResponse("404 Not Found", string());
ckrasic3865ee0f2016-02-29 22:04:562433 size_t spdy_response_header_frame_length;
2434 ProcessPacket(InnerConstructResponseHeadersPacket(
Nick Harper23290b82019-05-02 00:02:562435 3,
2436 stream_id_ + quic::QuicUtils::StreamIdDelta(version_.transport_version),
2437 kFin, &spdy_response_header_frame_length));
ckrasic3865ee0f2016-02-29 22:04:562438
fdoray92e35a72016-06-10 15:54:552439 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562440
robpercival214763f2016-07-01 23:27:012441 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2442 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562443 ASSERT_TRUE(response_.headers.get());
2444 EXPECT_EQ(404, response_.headers->response_code());
2445 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
2446 EXPECT_FALSE(response_.response_time.is_null());
2447 EXPECT_FALSE(response_.request_time.is_null());
2448
2449 // There is no body, so this should return immediately.
2450 EXPECT_EQ(
2451 0, promised_stream_->ReadResponseBody(
2452 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2453 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2454
2455 stream_->Close(true);
2456
2457 EXPECT_TRUE(AtEof());
ckrasic3865ee0f2016-02-29 22:04:562458}
2459
maksim.sisov84e20c92016-06-23 08:49:342460TEST_P(QuicHttpStreamTest, DataReadErrorSynchronous) {
2461 SetRequest("POST", "/", DEFAULT_PRIORITY);
2462 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232463 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252464 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232465 AddWrite(ConstructInitialSettingsPacket(packet_number++));
Yixin Wange7ecc472018-03-06 19:00:252466 AddWrite(ConstructRequestAndRstPacket(
Renjie Tangaadb84b2019-08-31 01:00:232467 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2468 kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
2469 &spdy_request_headers_frame_length, quic::QUIC_ERROR_PROCESSING_STREAM));
maksim.sisov84e20c92016-06-23 08:49:342470
2471 Initialize();
2472
Jeremy Roman0579ed62017-08-29 15:56:192473 upload_data_stream_ = std::make_unique<ReadErrorUploadDataStream>(
maksim.sisov84e20c92016-06-23 08:49:342474 ReadErrorUploadDataStream::FailureMode::SYNC);
2475 request_.method = "POST";
rchcd379012017-04-12 21:53:322476 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122477 request_.upload_data_stream = upload_data_stream_.get();
maksim.sisov84e20c92016-06-23 08:49:342478 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202479 TestCompletionCallback().callback(), NetLogWithSource()));
maksim.sisov84e20c92016-06-23 08:49:342480
2481 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272482 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
maksim.sisov84e20c92016-06-23 08:49:342483 net_log_.bound(), callback_.callback()));
2484
2485 int result = stream_->SendRequest(headers_, &response_, callback_.callback());
robpercival214763f2016-07-01 23:27:012486 EXPECT_THAT(result, IsError(ERR_FAILED));
maksim.sisov84e20c92016-06-23 08:49:342487
2488 EXPECT_TRUE(AtEof());
2489
2490 // QuicHttpStream::GetTotalSent/ReceivedBytes includes only headers.
2491 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
2492 stream_->GetTotalSentBytes());
2493 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2494}
2495
2496TEST_P(QuicHttpStreamTest, DataReadErrorAsynchronous) {
2497 SetRequest("POST", "/", DEFAULT_PRIORITY);
2498 size_t spdy_request_headers_frame_length;
Renjie Tangaadb84b2019-08-31 01:00:232499 int packet_number = 1;
Victor Vasiliev7da08172019-10-14 06:04:252500 if (VersionUsesHttp3(version_.transport_version))
Renjie Tangaadb84b2019-08-31 01:00:232501 AddWrite(ConstructInitialSettingsPacket(packet_number++));
fayang3bcb8b502016-12-07 21:44:372502 AddWrite(InnerConstructRequestHeadersPacket(
Renjie Tangaadb84b2019-08-31 01:00:232503 packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
2504 kIncludeVersion, !kFin, DEFAULT_PRIORITY,
2505 &spdy_request_headers_frame_length));
2506 AddWrite(
2507 ConstructClientRstStreamErrorPacket(packet_number++, !kIncludeVersion));
maksim.sisov84e20c92016-06-23 08:49:342508
2509 Initialize();
2510
Jeremy Roman0579ed62017-08-29 15:56:192511 upload_data_stream_ = std::make_unique<ReadErrorUploadDataStream>(
maksim.sisov84e20c92016-06-23 08:49:342512 ReadErrorUploadDataStream::FailureMode::ASYNC);
2513 request_.method = "POST";
rchcd379012017-04-12 21:53:322514 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122515 request_.upload_data_stream = upload_data_stream_.get();
maksim.sisov84e20c92016-06-23 08:49:342516 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202517 TestCompletionCallback().callback(), NetLogWithSource()));
maksim.sisov84e20c92016-06-23 08:49:342518
2519 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272520 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
maksim.sisov84e20c92016-06-23 08:49:342521 net_log_.bound(), callback_.callback()));
2522
2523 int result = stream_->SendRequest(headers_, &response_, callback_.callback());
2524
Renjie90e808e2019-01-24 07:24:042525 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
maksim.sisov84e20c92016-06-23 08:49:342526 SetResponse("200 OK", string());
2527
robpercival214763f2016-07-01 23:27:012528 EXPECT_THAT(result, IsError(ERR_IO_PENDING));
2529 EXPECT_THAT(callback_.GetResult(result), IsError(ERR_FAILED));
maksim.sisov84e20c92016-06-23 08:49:342530
2531 EXPECT_TRUE(AtEof());
2532
2533 // QuicHttpStream::GetTotalSent/ReceivedBytes includes only headers.
2534 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
2535 stream_->GetTotalSentBytes());
2536 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2537}
2538
[email protected]f702d572012-12-04 15:56:202539} // namespace test
[email protected]f702d572012-12-04 15:56:202540} // namespace net