blob: f794486316d00a3a40f83a32935e4514edd9ac2c [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"
xunjieli84adaab2016-09-20 01:12:2822#include "net/base/load_timing_info.h"
23#include "net/base/load_timing_info_test_util.h"
[email protected]f702d572012-12-04 15:56:2024#include "net/base/net_errors.h"
25#include "net/base/test_completion_callback.h"
[email protected]b2d26cfd2012-12-11 10:36:0626#include "net/base/upload_bytes_element_reader.h"
[email protected]f702d572012-12-04 15:56:2027#include "net/http/http_response_headers.h"
[email protected]5db452202014-08-19 05:22:1528#include "net/http/transport_security_state.h"
mikecirone8b85c432016-09-08 19:11:0029#include "net/log/net_log_event_type.h"
xunjieli5fafe142016-03-23 23:32:5430#include "net/log/test_net_log.h"
31#include "net/log/test_net_log_util.h"
Victor Vasiliev4f6fb892019-05-31 16:58:3132#include "net/quic/address_utils.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0833#include "net/quic/crypto/proof_verifier_chromium.h"
34#include "net/quic/mock_crypto_client_stream_factory.h"
35#include "net/quic/quic_chromium_alarm_factory.h"
36#include "net/quic/quic_chromium_connection_helper.h"
37#include "net/quic/quic_chromium_packet_reader.h"
38#include "net/quic/quic_chromium_packet_writer.h"
39#include "net/quic/quic_http_utils.h"
40#include "net/quic/quic_server_info.h"
41#include "net/quic/quic_stream_factory.h"
42#include "net/quic/quic_test_packet_maker.h"
43#include "net/quic/test_task_runner.h"
tbansalca83c002016-04-28 20:56:2844#include "net/socket/socket_performance_watcher.h"
[email protected]f702d572012-12-04 15:56:2045#include "net/socket/socket_test_util.h"
Bence Béky94658bf2018-05-11 19:22:5846#include "net/spdy/spdy_http_utils.h"
rch03b7a202016-02-05 00:54:2047#include "net/test/cert_test_util.h"
robpercival214763f2016-07-01 23:27:0148#include "net/test/gtest_util.h"
rsleevia69c79a2016-06-22 03:28:4349#include "net/test/test_data_directory.h"
Bence Béky98447b12018-05-08 03:14:0150#include "net/test/test_with_scoped_task_environment.h"
Victor Vasiliev6bb59d22019-03-08 21:34:5151#include "net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.h"
52#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
53#include "net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h"
54#include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
55#include "net/third_party/quiche/src/quic/core/http/spdy_utils.h"
56#include "net/third_party/quiche/src/quic/core/quic_connection.h"
57#include "net/third_party/quiche/src/quic/core/quic_utils.h"
58#include "net/third_party/quiche/src/quic/core/quic_write_blocked_list.h"
59#include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h"
60#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
61#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
62#include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
63#include "net/third_party/quiche/src/quic/test_tools/mock_random.h"
64#include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
65#include "net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h"
66#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
Victor Vasiliev27cc7712019-01-24 11:50:1467#include "net/third_party/quiche/src/spdy/core/spdy_frame_builder.h"
68#include "net/third_party/quiche/src/spdy/core/spdy_framer.h"
69#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
Ramin Halavati683bcaa92018-02-14 08:42:3970#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
[email protected]f702d572012-12-04 15:56:2071#include "testing/gmock/include/gmock/gmock.h"
72#include "testing/gtest/include/gtest/gtest.h"
73
bnc614a92d32016-04-04 13:56:0774using std::string;
[email protected]f702d572012-12-04 15:56:2075using testing::_;
[email protected]06ff5152013-08-29 01:03:0576using testing::AnyNumber;
77using testing::Return;
[email protected]f702d572012-12-04 15:56:2078
79namespace net {
[email protected]f702d572012-12-04 15:56:2080namespace test {
[email protected]f702d572012-12-04 15:56:2081namespace {
82
[email protected]16ba7742014-08-22 00:57:2583const char kUploadData[] = "Really nifty data!";
rch9ae5b3b2016-02-11 00:36:2984const char kDefaultServerHostName[] = "www.example.org";
rchcd379012017-04-12 21:53:3285const uint16_t kDefaultServerPort = 443;
[email protected]f702d572012-12-04 15:56:2086
Ryan Hamilton8d9ee76e2018-05-29 23:52:5287class TestQuicConnection : public quic::QuicConnection {
[email protected]f702d572012-12-04 15:56:2088 public:
Ryan Hamilton8d9ee76e2018-05-29 23:52:5289 TestQuicConnection(const quic::ParsedQuicVersionVector& versions,
90 quic::QuicConnectionId connection_id,
[email protected]f702d572012-12-04 15:56:2091 IPEndPoint address,
rch12fef552016-01-15 16:26:3192 QuicChromiumConnectionHelper* helper,
rch16c74d1d2016-04-22 06:14:0793 QuicChromiumAlarmFactory* alarm_factory,
Ryan Hamilton8d9ee76e2018-05-29 23:52:5294 quic::QuicPacketWriter* writer)
Victor Vasiliev4f6fb892019-05-31 16:58:3195 : quic::QuicConnection(connection_id,
96 ToQuicSocketAddress(address),
97 helper,
98 alarm_factory,
99 writer,
100 true /* owns_writer */,
101 quic::Perspective::IS_CLIENT,
102 versions) {}
[email protected]f702d572012-12-04 15:56:20103
Ryan Hamilton8d9ee76e2018-05-29 23:52:52104 void SetSendAlgorithm(quic::SendAlgorithmInterface* send_algorithm) {
105 quic::test::QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
[email protected]f702d572012-12-04 15:56:20106 }
107};
108
maksim.sisov84e20c92016-06-23 08:49:34109// UploadDataStream that always returns errors on data read.
110class ReadErrorUploadDataStream : public UploadDataStream {
111 public:
112 enum class FailureMode { SYNC, ASYNC };
113
114 explicit ReadErrorUploadDataStream(FailureMode mode)
115 : UploadDataStream(true, 0), async_(mode), weak_factory_(this) {}
116 ~ReadErrorUploadDataStream() override {}
117
118 private:
119 void CompleteRead() { UploadDataStream::OnReadCompleted(ERR_FAILED); }
120
121 // UploadDataStream implementation:
tfarina42834112016-09-22 13:38:20122 int InitInternal(const NetLogWithSource& net_log) override { return OK; }
maksim.sisov84e20c92016-06-23 08:49:34123
124 int ReadInternal(IOBuffer* buf, int buf_len) override {
125 if (async_ == FailureMode::ASYNC) {
126 base::ThreadTaskRunnerHandle::Get()->PostTask(
kylecharf4fe5172019-02-15 18:53:49127 FROM_HERE, base::BindOnce(&ReadErrorUploadDataStream::CompleteRead,
128 weak_factory_.GetWeakPtr()));
maksim.sisov84e20c92016-06-23 08:49:34129 return ERR_IO_PENDING;
130 }
131 return ERR_FAILED;
132 }
133
134 void ResetInternal() override {}
135
136 const FailureMode async_;
137
138 base::WeakPtrFactory<ReadErrorUploadDataStream> weak_factory_;
139
140 DISALLOW_COPY_AND_ASSIGN(ReadErrorUploadDataStream);
141};
142
Bence Béky8ddc2492018-06-13 01:02:04143// A helper class that will delete |stream| when the callback is invoked.
xunjieli8dff50b2016-07-22 14:19:06144class DeleteStreamCallback : public TestCompletionCallbackBase {
145 public:
Bence Béky8ddc2492018-06-13 01:02:04146 explicit DeleteStreamCallback(std::unique_ptr<QuicHttpStream> stream)
147 : stream_(std::move(stream)) {}
xunjieli8dff50b2016-07-22 14:19:06148
Bence Béky8ddc2492018-06-13 01:02:04149 CompletionOnceCallback callback() {
150 return base::BindOnce(&DeleteStreamCallback::DeleteStream,
151 base::Unretained(this));
152 }
xunjieli8dff50b2016-07-22 14:19:06153
154 private:
155 void DeleteStream(int result) {
156 stream_.reset();
157 SetResult(result);
158 }
159
160 std::unique_ptr<QuicHttpStream> stream_;
xunjieli8dff50b2016-07-22 14:19:06161};
162
[email protected]f702d572012-12-04 15:56:20163} // namespace
164
[email protected]24e5bc52013-09-18 15:36:58165class QuicHttpStreamPeer {
166 public:
rch08e198572017-05-09 16:56:55167 static QuicChromiumClientStream::Handle* GetQuicChromiumClientStream(
[email protected]24e5bc52013-09-18 15:36:58168 QuicHttpStream* stream) {
rch08e198572017-05-09 16:56:55169 return stream->stream_.get();
[email protected]24e5bc52013-09-18 15:36:58170 }
171};
172
Ryan Hamilton8d9ee76e2018-05-29 23:52:52173class QuicHttpStreamTest : public ::testing::TestWithParam<
Nick Harper23290b82019-05-02 00:02:56174 std::tuple<quic::ParsedQuicVersion, bool>>,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52175 public WithScopedTaskEnvironment {
rchfb47f712017-05-21 03:24:00176 public:
177 void CloseStream(QuicHttpStream* stream, int /*rv*/) { stream->Close(false); }
178
[email protected]f702d572012-12-04 15:56:20179 protected:
[email protected]1e960032013-12-20 19:00:20180 static const bool kFin = true;
181 static const bool kIncludeVersion = true;
182 static const bool kIncludeCongestionFeedback = true;
183
[email protected]f702d572012-12-04 15:56:20184 // Holds a packet to be written to the wire, and the IO mode that should
185 // be used by the mock socket when performing the write.
186 struct PacketToWrite {
Ryan Hamilton8d9ee76e2018-05-29 23:52:52187 PacketToWrite(IoMode mode, quic::QuicReceivedPacket* packet)
rjshaded5ced072015-12-18 19:26:02188 : mode(mode), packet(packet) {}
rtenneti15656ae2016-01-23 03:05:03189 PacketToWrite(IoMode mode, int rv) : mode(mode), packet(nullptr), rv(rv) {}
[email protected]f702d572012-12-04 15:56:20190 IoMode mode;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52191 quic::QuicReceivedPacket* packet;
rtenneti15656ae2016-01-23 03:05:03192 int rv;
[email protected]f702d572012-12-04 15:56:20193 };
194
195 QuicHttpStreamTest()
Yixin Wang079ad542018-01-11 04:06:05196 : version_(std::get<0>(GetParam())),
197 client_headers_include_h2_stream_dependency_(std::get<1>(GetParam())),
Ryan Hamilton8d9ee76e2018-05-29 23:52:52198 crypto_config_(quic::test::crypto_test_utils::ProofVerifierForTesting(),
199 quic::TlsClientHandshaker::CreateSslCtx()),
Victor Costan9c7302b2018-08-27 16:39:44200 read_buffer_(base::MakeRefCounted<IOBufferWithSize>(4096)),
Fan Yang32c5a112018-12-10 20:06:33201 promise_id_(GetNthServerInitiatedUnidirectionalStreamId(0)),
202 stream_id_(GetNthClientInitiatedBidirectionalStreamId(0)),
David Schinazic8281052019-01-24 06:14:17203 connection_id_(quic::test::TestConnectionId(2)),
Yixin Wang079ad542018-01-11 04:06:05204 client_maker_(version_,
alyssar2adf3ac2016-05-03 17:12:58205 connection_id_,
206 &clock_,
207 kDefaultServerHostName,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52208 quic::Perspective::IS_CLIENT,
Yixin Wang079ad542018-01-11 04:06:05209 client_headers_include_h2_stream_dependency_),
210 server_maker_(version_,
zhongyi5dbfdd42017-06-20 05:22:15211 connection_id_,
alyssar2adf3ac2016-05-03 17:12:58212 &clock_,
213 kDefaultServerHostName,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52214 quic::Perspective::IS_SERVER,
Yixin Wang079ad542018-01-11 04:06:05215 false),
ckrasic3865ee0f2016-02-29 22:04:56216 random_generator_(0),
217 response_offset_(0) {
martijn21968ea2016-02-24 18:46:20218 IPAddress ip(192, 0, 2, 33);
[email protected]f702d572012-12-04 15:56:20219 peer_addr_ = IPEndPoint(ip, 443);
220 self_addr_ = IPEndPoint(ip, 8435);
Ryan Hamilton8d9ee76e2018-05-29 23:52:52221 clock_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(20));
Ramin Halavati683bcaa92018-02-14 08:42:39222 request_.traffic_annotation =
223 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f702d572012-12-04 15:56:20224 }
225
226 ~QuicHttpStreamTest() {
Renjieba55fae2018-09-20 03:05:16227 session_->CloseSessionOnError(ERR_ABORTED, quic::QUIC_INTERNAL_ERROR,
228 quic::ConnectionCloseBehavior::SILENT_CLOSE);
[email protected]f702d572012-12-04 15:56:20229 for (size_t i = 0; i < writes_.size(); i++) {
230 delete writes_[i].packet;
231 }
232 }
233
234 // Adds a packet to the list of expected writes.
Ryan Hamilton8d9ee76e2018-05-29 23:52:52235 void AddWrite(std::unique_ptr<quic::QuicReceivedPacket> packet) {
[email protected]1e960032013-12-20 19:00:20236 writes_.push_back(PacketToWrite(SYNCHRONOUS, packet.release()));
[email protected]f702d572012-12-04 15:56:20237 }
238
rtenneti15656ae2016-01-23 03:05:03239 void AddWrite(IoMode mode, int rv) {
240 writes_.push_back(PacketToWrite(mode, rv));
241 }
242
[email protected]f702d572012-12-04 15:56:20243 // Returns the packet to be written at position |pos|.
Ryan Hamilton8d9ee76e2018-05-29 23:52:52244 quic::QuicReceivedPacket* GetWrite(size_t pos) { return writes_[pos].packet; }
[email protected]f702d572012-12-04 15:56:20245
246 bool AtEof() {
rch37de576c2015-05-17 20:28:17247 return socket_data_->AllReadDataConsumed() &&
248 socket_data_->AllWriteDataConsumed();
[email protected]f702d572012-12-04 15:56:20249 }
250
Ryan Hamilton8d9ee76e2018-05-29 23:52:52251 void ProcessPacket(std::unique_ptr<quic::QuicReceivedPacket> packet) {
Victor Vasiliev4f6fb892019-05-31 16:58:31252 connection_->ProcessUdpPacket(ToQuicSocketAddress(self_addr_),
253 ToQuicSocketAddress(peer_addr_), *packet);
[email protected]f702d572012-12-04 15:56:20254 }
255
256 // Configures the test fixture to use the list of expected writes.
257 void Initialize() {
258 mock_writes_.reset(new MockWrite[writes_.size()]);
259 for (size_t i = 0; i < writes_.size(); i++) {
rtenneti15656ae2016-01-23 03:05:03260 if (writes_[i].packet == nullptr) {
261 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].rv, i);
262 } else {
263 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].packet->data(),
264 writes_[i].packet->length());
265 }
bnc614a92d32016-04-04 13:56:07266 }
[email protected]f702d572012-12-04 15:56:20267
rtennetibe635732014-10-02 22:51:42268 socket_data_.reset(new StaticSocketDataProvider(
Ryan Sleevib8d7ea02018-05-07 20:01:01269 base::span<MockRead>(),
270 base::make_span(mock_writes_.get(), writes_.size())));
[email protected]f702d572012-12-04 15:56:20271
danakjad1777e2016-04-16 00:56:42272 std::unique_ptr<MockUDPClientSocket> socket(new MockUDPClientSocket(
xunjielib53b38c2016-03-24 15:54:36273 socket_data_.get(), net_log_.bound().net_log()));
[email protected]e13201d82012-12-12 05:00:32274 socket->Connect(peer_addr_);
[email protected]f702d572012-12-04 15:56:20275 runner_ = new TestTaskRunner(&clock_);
Ryan Hamilton8d9ee76e2018-05-29 23:52:52276 send_algorithm_ = new quic::test::MockSendAlgorithm();
rch7dd15702015-07-01 18:57:57277 EXPECT_CALL(*send_algorithm_, InRecovery()).WillRepeatedly(Return(false));
278 EXPECT_CALL(*send_algorithm_, InSlowStart()).WillRepeatedly(Return(false));
rjshaded5ced072015-12-18 19:26:02279 EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
Dan Zhangf11470172017-09-18 22:02:09280 .Times(testing::AtLeast(1));
rtenneti44f4a2e2015-08-07 14:00:07281 EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
Zhongyi Shica576df2019-04-12 17:43:40282 .WillRepeatedly(Return(quic::kMaxOutgoingPacketSize));
jokulik0e0a00c32016-06-13 21:51:58283 EXPECT_CALL(*send_algorithm_, PacingRate(_))
Ryan Hamilton8d9ee76e2018-05-29 23:52:52284 .WillRepeatedly(Return(quic::QuicBandwidth::Zero()));
Michael Warres74ee3ce2017-10-09 15:26:37285 EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true));
rtenneti44f4a2e2015-08-07 14:00:07286 EXPECT_CALL(*send_algorithm_, BandwidthEstimate())
Ryan Hamilton8d9ee76e2018-05-29 23:52:52287 .WillRepeatedly(Return(quic::QuicBandwidth::Zero()));
rch1e543ec2015-03-29 07:04:40288 EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(AnyNumber());
rch08cae032017-03-29 00:59:15289 EXPECT_CALL(*send_algorithm_, OnApplicationLimited(_)).Times(AnyNumber());
rch0d5bcf62017-05-24 22:48:45290 EXPECT_CALL(*send_algorithm_, GetCongestionControlType())
291 .Times(AnyNumber());
rch16c74d1d2016-04-22 06:14:07292 helper_.reset(
293 new QuicChromiumConnectionHelper(&clock_, &random_generator_));
294 alarm_factory_.reset(new QuicChromiumAlarmFactory(runner_.get(), &clock_));
295
Michael Warres74ee3ce2017-10-09 15:26:37296 connection_ = new TestQuicConnection(
Nick Harper23290b82019-05-02 00:02:56297 quic::test::SupportedVersions(version_), connection_id_, peer_addr_,
298 helper_.get(), alarm_factory_.get(),
Ryan Hamilton9edcf1a2017-11-22 05:55:17299 new QuicChromiumPacketWriter(
300 socket.get(), base::ThreadTaskRunnerHandle::Get().get()));
[email protected]f702d572012-12-04 15:56:20301 connection_->set_visitor(&visitor_);
[email protected]fee17f72013-02-03 07:47:41302 connection_->SetSendAlgorithm(send_algorithm_);
rch03b7a202016-02-05 00:54:20303
304 // Load a certificate that is valid for *.example.org
305 scoped_refptr<X509Certificate> test_cert(
306 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
307 EXPECT_TRUE(test_cert.get());
308
309 verify_details_.cert_verify_result.verified_cert = test_cert;
310 verify_details_.cert_verify_result.is_issued_by_known_root = true;
311 crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details_);
312
xunjieli84adaab2016-09-20 01:12:28313 base::TimeTicks dns_end = base::TimeTicks::Now();
314 base::TimeTicks dns_start = dns_end - base::TimeDelta::FromMilliseconds(1);
ckrasic4f9d88d2015-07-22 22:23:16315 session_.reset(new QuicChromiumClientSession(
xunjielib53b38c2016-03-24 15:54:36316 connection_, std::move(socket),
rtenneti1cd3b162015-09-29 02:58:28317 /*stream_factory=*/nullptr, &crypto_client_stream_factory_, &clock_,
Nick Harper89bc7212018-07-31 19:07:57318 &transport_security_state_, /*ssl_config_service=*/nullptr,
danakjad1777e2016-04-16 00:56:42319 base::WrapUnique(static_cast<QuicServerInfo*>(nullptr)),
Paul Jensen8e3c5d32018-02-19 17:06:33320 QuicSessionKey(kDefaultServerHostName, kDefaultServerPort,
321 PRIVACY_MODE_DISABLED, SocketTag()),
Zhongyi Shi757fcce2018-06-27 05:41:27322 /*require_confirmation=*/false, /*migrate_session_early_v2=*/false,
323 /*migrate_session_on_network_change_v2=*/false,
324 /*default_network=*/NetworkChangeNotifier::kInvalidNetworkHandle,
Zhongyi Shie01f2db2019-02-22 19:53:23325 quic::QuicTime::Delta::FromMilliseconds(
326 kDefaultRetransmittableOnWireTimeoutMillisecs),
Zhongyi Shi32fe14d42019-02-28 00:25:36327 /*migrate_idle_session=*/false,
Zhongyi Shic16b4102019-02-12 00:37:40328 base::TimeDelta::FromSeconds(kDefaultIdleSessionMigrationPeriodSeconds),
Zhongyi Shi73f23ca872017-12-13 18:37:13329 base::TimeDelta::FromSeconds(kMaxTimeOnNonDefaultNetworkSecs),
Zhongyi Shiee760762018-08-01 00:54:29330 kMaxMigrationsToNonDefaultNetworkOnWriteError,
Zhongyi Shi8b1e43f2017-12-13 20:46:30331 kMaxMigrationsToNonDefaultNetworkOnPathDegrading,
Zhongyi Shi5f587cc2017-11-21 23:24:17332 kQuicYieldAfterPacketsRead,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52333 quic::QuicTime::Delta::FromMilliseconds(
334 kQuicYieldAfterDurationMilliseconds),
Zhongyi Shidbce7f412019-02-01 23:16:29335 /*go_away_on_path_degrading*/ false,
Yixin Wang079ad542018-01-11 04:06:05336 client_headers_include_h2_stream_dependency_, /*cert_verify_flags=*/0,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52337 quic::test::DefaultQuicConfig(), &crypto_config_, "CONNECTION_UNKNOWN",
338 dns_start, dns_end, &push_promise_index_, nullptr,
Zhongyi Shic16b4102019-02-12 00:37:40339 base::DefaultTickClock::GetInstance(),
xunjieli84adaab2016-09-20 01:12:28340 base::ThreadTaskRunnerHandle::Get().get(),
xunjieli5fafe142016-03-23 23:32:54341 /*socket_performance_watcher=*/nullptr, net_log_.bound().net_log()));
rtennetid39bd762015-06-12 01:05:52342 session_->Initialize();
xunjieli100937eb52016-09-15 20:09:37343 TestCompletionCallback callback;
rchf0b18c8a2017-05-05 19:31:57344
rch433bf5f2017-02-14 04:10:47345 session_->CryptoConnect(callback.callback());
Ryan Hamilton6c2a2a82017-12-15 02:06:28346 stream_ = std::make_unique<QuicHttpStream>(
347 session_->CreateHandle(HostPortPair("www.example.org", 443)));
348 promised_stream_ = std::make_unique<QuicHttpStream>(
349 session_->CreateHandle(HostPortPair("www.example.org", 443)));
ckrasic3865ee0f2016-02-29 22:04:56350 push_promise_[":path"] = "/bar";
351 push_promise_[":authority"] = "www.example.org";
352 push_promise_[":version"] = "HTTP/1.1";
353 push_promise_[":method"] = "GET";
354 push_promise_[":scheme"] = "https";
355
356 promised_response_[":status"] = "200 OK";
357 promised_response_[":version"] = "HTTP/1.1";
358 promised_response_["content-type"] = "text/plain";
359
Ryan Hamilton8d9ee76e2018-05-29 23:52:52360 promise_url_ = quic::SpdyUtils::GetPromisedUrlFromHeaders(push_promise_);
[email protected]6cca996b2013-01-25 07:43:36361 }
362
bnc614a92d32016-04-04 13:56:07363 void SetRequest(const string& method,
364 const string& path,
[email protected]1e960032013-12-20 19:00:20365 RequestPriority priority) {
rchcd379012017-04-12 21:53:32366 request_headers_ = client_maker_.GetRequestHeaders(method, "https", path);
[email protected]6cca996b2013-01-25 07:43:36367 }
368
bnc614a92d32016-04-04 13:56:07369 void SetResponse(const string& status, const string& body) {
alyssar2adf3ac2016-05-03 17:12:58370 response_headers_ = server_maker_.GetResponseHeaders(status);
[email protected]92bf17c2014-03-03 21:14:03371 response_data_ = body;
[email protected]6cca996b2013-01-25 07:43:36372 }
[email protected]f702d572012-12-04 15:56:20373
Ryan Hamilton8d9ee76e2018-05-29 23:52:52374 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructDataPacket(
Fan Yangac867502019-01-28 21:10:23375 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52376 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56377 bool should_include_version,
378 bool fin,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52379 quic::QuicStreamOffset offset,
380 quic::QuicStringPiece data,
alyssar2adf3ac2016-05-03 17:12:58381 QuicTestPacketMaker* maker) {
382 return maker->MakeDataPacket(packet_number, stream_id,
ckrasic3865ee0f2016-02-29 22:04:56383 should_include_version, fin, offset, data);
384 }
385
Ryan Hamilton8d9ee76e2018-05-29 23:52:52386 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientDataPacket(
Fan Yangac867502019-01-28 21:10:23387 uint64_t packet_number,
[email protected]e8ff26842013-03-22 21:02:05388 bool should_include_version,
[email protected]f702d572012-12-04 15:56:20389 bool fin,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52390 quic::QuicStreamOffset offset,
391 quic::QuicStringPiece data) {
ckrasic3865ee0f2016-02-29 22:04:56392 return InnerConstructDataPacket(packet_number, stream_id_,
alyssar2adf3ac2016-05-03 17:12:58393 should_include_version, fin, offset, data,
394 &client_maker_);
395 }
396
Renjief49758b2019-01-11 23:32:41397 std::unique_ptr<quic::QuicReceivedPacket>
398 ConstructClientMultipleDataFramesPacket(
Fan Yangac867502019-01-28 21:10:23399 uint64_t packet_number,
Renjief49758b2019-01-11 23:32:41400 bool should_include_version,
401 bool fin,
402 quic::QuicStreamOffset offset,
403 const std::vector<std::string>& data) {
404 return client_maker_.MakeMultipleDataFramesPacket(
405 packet_number, stream_id_, should_include_version, fin, offset, data);
406 }
407
Ryan Hamilton8d9ee76e2018-05-29 23:52:52408 std::unique_ptr<quic::QuicReceivedPacket> ConstructServerDataPacket(
Fan Yangac867502019-01-28 21:10:23409 uint64_t packet_number,
alyssar2adf3ac2016-05-03 17:12:58410 bool should_include_version,
411 bool fin,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52412 quic::QuicStreamOffset offset,
413 quic::QuicStringPiece data) {
alyssar2adf3ac2016-05-03 17:12:58414 return InnerConstructDataPacket(packet_number, stream_id_,
415 should_include_version, fin, offset, data,
416 &server_maker_);
ckrasic3865ee0f2016-02-29 22:04:56417 }
418
Ryan Hamilton8d9ee76e2018-05-29 23:52:52419 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23420 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52421 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56422 bool should_include_version,
423 bool fin,
424 RequestPriority request_priority,
xunjieli100937eb52016-09-15 20:09:37425 size_t* spdy_headers_frame_length,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52426 quic::QuicStreamOffset* offset) {
Yixin Wang7a3f1b8d2018-01-17 21:40:48427 return InnerConstructRequestHeadersPacket(
428 packet_number, stream_id, should_include_version, fin, request_priority,
429 0, spdy_headers_frame_length, offset);
430 }
431
Ryan Hamilton8d9ee76e2018-05-29 23:52:52432 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23433 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52434 quic::QuicStreamId stream_id,
Yixin Wang7a3f1b8d2018-01-17 21:40:48435 bool should_include_version,
436 bool fin,
437 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52438 quic::QuicStreamId parent_stream_id,
Yixin Wang7a3f1b8d2018-01-17 21:40:48439 size_t* spdy_headers_frame_length,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52440 quic::QuicStreamOffset* offset) {
Ryan Hamilton0239aac2018-05-19 00:03:13441 spdy::SpdyPriority priority =
ckrasic3865ee0f2016-02-29 22:04:56442 ConvertRequestPriorityToQuicPriority(request_priority);
alyssar2adf3ac2016-05-03 17:12:58443 return client_maker_.MakeRequestHeadersPacket(
ckrasic3865ee0f2016-02-29 22:04:56444 packet_number, stream_id, should_include_version, fin, priority,
Yixin Wang7a3f1b8d2018-01-17 21:40:48445 std::move(request_headers_), parent_stream_id,
446 spdy_headers_frame_length, offset);
[email protected]f702d572012-12-04 15:56:20447 }
448
Ryan Hamilton8d9ee76e2018-05-29 23:52:52449 std::unique_ptr<quic::QuicReceivedPacket>
Yixin Wange7ecc472018-03-06 19:00:25450 ConstructRequestHeadersAndDataFramesPacket(
Fan Yangac867502019-01-28 21:10:23451 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52452 quic::QuicStreamId stream_id,
Yixin Wange7ecc472018-03-06 19:00:25453 bool should_include_version,
454 bool fin,
455 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52456 quic::QuicStreamId parent_stream_id,
457 quic::QuicStreamOffset* offset,
Yixin Wange7ecc472018-03-06 19:00:25458 size_t* spdy_headers_frame_length,
459 const std::vector<std::string>& data_writes) {
Ryan Hamilton0239aac2018-05-19 00:03:13460 spdy::SpdyPriority priority =
Yixin Wange7ecc472018-03-06 19:00:25461 ConvertRequestPriorityToQuicPriority(request_priority);
462 return client_maker_.MakeRequestHeadersAndMultipleDataFramesPacket(
463 packet_number, stream_id, should_include_version, fin, priority,
464 std::move(request_headers_), parent_stream_id, offset,
465 spdy_headers_frame_length, data_writes);
466 }
467
Ryan Hamilton8d9ee76e2018-05-29 23:52:52468 std::unique_ptr<quic::QuicReceivedPacket> ConstructRequestAndRstPacket(
Fan Yangac867502019-01-28 21:10:23469 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52470 quic::QuicStreamId stream_id,
Yixin Wange7ecc472018-03-06 19:00:25471 bool should_include_version,
472 bool fin,
473 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52474 quic::QuicStreamId parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25475 size_t* spdy_headers_frame_length,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52476 quic::QuicStreamOffset* header_stream_offset,
477 quic::QuicRstStreamErrorCode error_code,
Yixin Wange7ecc472018-03-06 19:00:25478 size_t bytes_written) {
Ryan Hamilton0239aac2018-05-19 00:03:13479 spdy::SpdyPriority priority =
Yixin Wange7ecc472018-03-06 19:00:25480 ConvertRequestPriorityToQuicPriority(request_priority);
481 return client_maker_.MakeRequestHeadersAndRstPacket(
482 packet_number, stream_id, should_include_version, fin, priority,
483 std::move(request_headers_), parent_stream_id,
484 spdy_headers_frame_length, header_stream_offset, error_code,
485 bytes_written);
486 }
487
Ryan Hamilton8d9ee76e2018-05-29 23:52:52488 std::unique_ptr<quic::QuicReceivedPacket> ConstructRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23489 uint64_t packet_number,
rtennetif4bdb542015-01-21 14:33:05490 bool fin,
sclittlec4dc1a32015-09-24 00:15:45491 RequestPriority request_priority,
492 size_t* spdy_headers_frame_length) {
ckrasic3865ee0f2016-02-29 22:04:56493 return InnerConstructRequestHeadersPacket(
494 packet_number, stream_id_, kIncludeVersion, fin, request_priority,
xunjieli100937eb52016-09-15 20:09:37495 spdy_headers_frame_length, nullptr);
ckrasic3865ee0f2016-02-29 22:04:56496 }
497
Ryan Hamilton8d9ee76e2018-05-29 23:52:52498 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructResponseHeadersPacket(
Fan Yangac867502019-01-28 21:10:23499 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52500 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56501 bool fin,
502 size_t* spdy_headers_frame_length) {
alyssar2adf3ac2016-05-03 17:12:58503 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26504 packet_number, stream_id, !kIncludeVersion, fin,
505 std::move(response_headers_), spdy_headers_frame_length,
506 &response_offset_);
[email protected]1e960032013-12-20 19:00:20507 }
508
Ryan Hamilton8d9ee76e2018-05-29 23:52:52509 std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseHeadersPacket(
Fan Yangac867502019-01-28 21:10:23510 uint64_t packet_number,
sclittlec4dc1a32015-09-24 00:15:45511 bool fin,
512 size_t* spdy_headers_frame_length) {
ckrasic3865ee0f2016-02-29 22:04:56513 return InnerConstructResponseHeadersPacket(packet_number, stream_id_, fin,
514 spdy_headers_frame_length);
[email protected]1e960032013-12-20 19:00:20515 }
516
Ryan Hamilton8d9ee76e2018-05-29 23:52:52517 std::unique_ptr<quic::QuicReceivedPacket>
Fan Yangac867502019-01-28 21:10:23518 ConstructResponseHeadersPacketWithOffset(uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52519 bool fin,
520 size_t* spdy_headers_frame_length,
521 quic::QuicStreamOffset* offset) {
alyssar2adf3ac2016-05-03 17:12:58522 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26523 packet_number, stream_id_, !kIncludeVersion, fin,
524 std::move(response_headers_), spdy_headers_frame_length, offset);
xunjieli34291fe12016-03-02 13:58:38525 }
526
Ryan Hamilton8d9ee76e2018-05-29 23:52:52527 std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseTrailersPacket(
Fan Yangac867502019-01-28 21:10:23528 uint64_t packet_number,
xunjieli34291fe12016-03-02 13:58:38529 bool fin,
Ryan Hamilton0239aac2018-05-19 00:03:13530 spdy::SpdyHeaderBlock trailers,
xunjieli34291fe12016-03-02 13:58:38531 size_t* spdy_headers_frame_length,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52532 quic::QuicStreamOffset* offset) {
alyssar2adf3ac2016-05-03 17:12:58533 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26534 packet_number, stream_id_, !kIncludeVersion, fin, std::move(trailers),
alyssar2adf3ac2016-05-03 17:12:58535 spdy_headers_frame_length, offset);
xunjieli34291fe12016-03-02 13:58:38536 }
537
Ryan Hamilton8d9ee76e2018-05-29 23:52:52538 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientRstStreamPacket(
Fan Yangac867502019-01-28 21:10:23539 uint64_t packet_number) {
alyssara72f5352016-10-20 12:45:16540 return client_maker_.MakeRstPacket(packet_number, true, stream_id_,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52541 quic::QUIC_RST_ACKNOWLEDGEMENT);
[email protected]06ff5152013-08-29 01:03:05542 }
543
Ryan Hamilton8d9ee76e2018-05-29 23:52:52544 std::unique_ptr<quic::QuicReceivedPacket>
Fan Yangac867502019-01-28 21:10:23545 ConstructClientRstStreamCancelledPacket(uint64_t packet_number) {
alyssar2adf3ac2016-05-03 17:12:58546 return client_maker_.MakeRstPacket(packet_number, !kIncludeVersion,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52547 stream_id_, quic::QUIC_STREAM_CANCELLED);
rtenneti6bd660b2015-07-18 00:19:53548 }
549
Ryan Hamilton8d9ee76e2018-05-29 23:52:52550 std::unique_ptr<quic::QuicReceivedPacket>
Fan Yangac867502019-01-28 21:10:23551 ConstructClientRstStreamVaryMismatchPacket(uint64_t packet_number) {
alyssar2adf3ac2016-05-03 17:12:58552 return client_maker_.MakeRstPacket(packet_number, !kIncludeVersion,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52553 promise_id_,
554 quic::QUIC_PROMISE_VARY_MISMATCH);
ckrasic3865ee0f2016-02-29 22:04:56555 }
556
Fan Yang550c6282018-06-22 18:53:25557 std::unique_ptr<quic::QuicReceivedPacket>
558 ConstructClientRstStreamVaryMismatchAndRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23559 uint64_t packet_number,
Fan Yang550c6282018-06-22 18:53:25560 quic::QuicStreamId stream_id,
561 bool should_include_version,
562 bool fin,
563 RequestPriority request_priority,
564 quic::QuicStreamId parent_stream_id,
565 size_t* spdy_headers_frame_length,
566 quic::QuicStreamOffset* offset) {
567 spdy::SpdyPriority priority =
568 ConvertRequestPriorityToQuicPriority(request_priority);
569 return client_maker_.MakeRstAndRequestHeadersPacket(
570 packet_number, should_include_version, promise_id_,
571 quic::QUIC_PROMISE_VARY_MISMATCH, stream_id, fin, priority,
572 std::move(request_headers_), parent_stream_id,
573 spdy_headers_frame_length, offset);
574 }
575
Ryan Hamilton8d9ee76e2018-05-29 23:52:52576 std::unique_ptr<quic::QuicReceivedPacket> ConstructAckAndRstStreamPacket(
Fan Yangac867502019-01-28 21:10:23577 uint64_t packet_number,
578 uint64_t largest_received,
579 uint64_t smallest_received,
580 uint64_t least_unacked) {
alyssar2adf3ac2016-05-03 17:12:58581 return client_maker_.MakeAckAndRstPacket(
Ryan Hamilton8d9ee76e2018-05-29 23:52:52582 packet_number, !kIncludeVersion, stream_id_,
583 quic::QUIC_STREAM_CANCELLED, largest_received, smallest_received,
584 least_unacked, !kIncludeCongestionFeedback);
xunjieli34291fe12016-03-02 13:58:38585 }
586
Ryan Hamilton8d9ee76e2018-05-29 23:52:52587 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientRstStreamErrorPacket(
Fan Yangac867502019-01-28 21:10:23588 uint64_t packet_number,
maksim.sisov84e20c92016-06-23 08:49:34589 bool include_version) {
590 return client_maker_.MakeRstPacket(packet_number, include_version,
591 stream_id_,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52592 quic::QUIC_ERROR_PROCESSING_STREAM);
maksim.sisov84e20c92016-06-23 08:49:34593 }
594
Ryan Hamilton8d9ee76e2018-05-29 23:52:52595 std::unique_ptr<quic::QuicReceivedPacket> ConstructAckAndRstStreamPacket(
Fan Yangac867502019-01-28 21:10:23596 uint64_t packet_number) {
Renjie90e808e2019-01-24 07:24:04597 return ConstructAckAndRstStreamPacket(packet_number, 2, 1, 2);
[email protected]c5e1aca2014-01-30 04:03:04598 }
599
Ryan Hamilton8d9ee76e2018-05-29 23:52:52600 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientAckPacket(
Fan Yangac867502019-01-28 21:10:23601 uint64_t packet_number,
602 uint64_t largest_received,
603 uint64_t smallest_received,
604 uint64_t least_unacked) {
alyssar2adf3ac2016-05-03 17:12:58605 return client_maker_.MakeAckPacket(packet_number, largest_received,
wangyix6444ffe2017-04-25 17:49:49606 smallest_received, least_unacked,
alyssar2adf3ac2016-05-03 17:12:58607 !kIncludeCongestionFeedback);
608 }
609
Ryan Hamilton8d9ee76e2018-05-29 23:52:52610 std::unique_ptr<quic::QuicReceivedPacket> ConstructServerAckPacket(
Fan Yangac867502019-01-28 21:10:23611 uint64_t packet_number,
612 uint64_t largest_received,
613 uint64_t smallest_received,
614 uint64_t least_unacked) {
alyssar2adf3ac2016-05-03 17:12:58615 return server_maker_.MakeAckPacket(packet_number, largest_received,
wangyix6444ffe2017-04-25 17:49:49616 smallest_received, least_unacked,
alyssar2adf3ac2016-05-03 17:12:58617 !kIncludeCongestionFeedback);
[email protected]63534512012-12-23 18:49:00618 }
619
Ryan Hamilton8d9ee76e2018-05-29 23:52:52620 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientPriorityPacket(
Fan Yangac867502019-01-28 21:10:23621 uint64_t packet_number,
Yixin Wangb470bc882018-02-15 18:43:57622 bool should_include_version,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52623 quic::QuicStreamId id,
624 quic::QuicStreamId parent_stream_id,
Yixin Wangb470bc882018-02-15 18:43:57625 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52626 quic::QuicStreamOffset* header_stream_offset) {
Yixin Wangb470bc882018-02-15 18:43:57627 return client_maker_.MakePriorityPacket(
628 packet_number, should_include_version, id, parent_stream_id,
629 ConvertRequestPriorityToQuicPriority(request_priority),
630 header_stream_offset);
631 }
632
Ryan Hamilton8d9ee76e2018-05-29 23:52:52633 std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket(
634 quic::QuicStreamOffset* offset) {
rch5cb522462017-04-25 20:18:36635 return client_maker_.MakeInitialSettingsPacket(1, offset);
fayang3bcb8b502016-12-07 21:44:37636 }
637
Victor Vasiliev076657c2019-03-12 02:46:43638 std::string ConstructDataHeader(size_t body_len) {
Nick Harper23290b82019-05-02 00:02:56639 if (version_.transport_version != quic::QUIC_VERSION_99) {
Renjief49758b2019-01-11 23:32:41640 return "";
641 }
642 quic::HttpEncoder encoder;
643 std::unique_ptr<char[]> buffer;
644 auto header_length = encoder.SerializeDataFrameHeader(body_len, &buffer);
Victor Vasiliev076657c2019-03-12 02:46:43645 return std::string(buffer.get(), header_length);
Renjief49758b2019-01-11 23:32:41646 }
647
Ryan Hamilton8d9ee76e2018-05-29 23:52:52648 void ReceivePromise(quic::QuicStreamId id) {
649 auto headers = quic::test::AsHeaderList(push_promise_);
rch08e198572017-05-09 16:56:55650 QuicChromiumClientStream::Handle* stream =
ckrasic3865ee0f2016-02-29 22:04:56651 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
ckrasic32b17dcd2016-10-31 06:15:35652 stream->OnPromiseHeaderList(id, headers.uncompressed_header_bytes(),
653 headers);
ckrasic3865ee0f2016-02-29 22:04:56654 }
655
xunjieli84adaab2016-09-20 01:12:28656 void ExpectLoadTimingValid(const LoadTimingInfo& load_timing_info,
xunjieli100937eb52016-09-15 20:09:37657 bool session_reused) {
658 EXPECT_EQ(session_reused, load_timing_info.socket_reused);
xunjieli84adaab2016-09-20 01:12:28659 if (session_reused) {
660 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
661 } else {
662 ExpectConnectTimingHasTimes(
663 load_timing_info.connect_timing,
664 CONNECT_TIMING_HAS_SSL_TIMES | CONNECT_TIMING_HAS_DNS_TIMES);
665 }
666 ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info);
xunjieli100937eb52016-09-15 20:09:37667 }
668
Fan Yang32c5a112018-12-10 20:06:33669 quic::QuicStreamId GetNthClientInitiatedBidirectionalStreamId(int n) {
Nick Harper23290b82019-05-02 00:02:56670 return quic::test::GetNthClientInitiatedBidirectionalStreamId(
671 version_.transport_version, n);
ckrasicbf2f59c2017-05-04 23:54:36672 }
673
Fan Yang32c5a112018-12-10 20:06:33674 quic::QuicStreamId GetNthServerInitiatedUnidirectionalStreamId(int n) {
Nick Harper23290b82019-05-02 00:02:56675 return quic::test::GetNthServerInitiatedUnidirectionalStreamId(
676 version_.transport_version, n);
ckrasicbf2f59c2017-05-04 23:54:36677 }
678
Nick Harper23290b82019-05-02 00:02:56679 const quic::ParsedQuicVersion version_;
Yixin Wang079ad542018-01-11 04:06:05680 const bool client_headers_include_h2_stream_dependency_;
681
xunjieli5fafe142016-03-23 23:32:54682 BoundTestNetLog net_log_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52683 quic::test::MockSendAlgorithm* send_algorithm_;
[email protected]f702d572012-12-04 15:56:20684 scoped_refptr<TestTaskRunner> runner_;
danakjad1777e2016-04-16 00:56:42685 std::unique_ptr<MockWrite[]> mock_writes_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52686 quic::MockClock clock_;
[email protected]f702d572012-12-04 15:56:20687 TestQuicConnection* connection_;
danakjad1777e2016-04-16 00:56:42688 std::unique_ptr<QuicChromiumConnectionHelper> helper_;
rch16c74d1d2016-04-22 06:14:07689 std::unique_ptr<QuicChromiumAlarmFactory> alarm_factory_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52690 testing::StrictMock<quic::test::MockQuicConnectionVisitor> visitor_;
rch97827ee2017-05-24 23:49:12691 std::unique_ptr<UploadDataStream> upload_data_stream_;
danakjad1777e2016-04-16 00:56:42692 std::unique_ptr<QuicHttpStream> stream_;
[email protected]5db452202014-08-19 05:22:15693 TransportSecurityState transport_security_state_;
danakjad1777e2016-04-16 00:56:42694 std::unique_ptr<QuicChromiumClientSession> session_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52695 quic::QuicCryptoClientConfig crypto_config_;
[email protected]f702d572012-12-04 15:56:20696 TestCompletionCallback callback_;
697 HttpRequestInfo request_;
698 HttpRequestHeaders headers_;
699 HttpResponseInfo response_;
700 scoped_refptr<IOBufferWithSize> read_buffer_;
Ryan Hamilton0239aac2018-05-19 00:03:13701 spdy::SpdyHeaderBlock request_headers_;
702 spdy::SpdyHeaderBlock response_headers_;
bnc614a92d32016-04-04 13:56:07703 string request_data_;
704 string response_data_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52705 quic::QuicClientPushPromiseIndex push_promise_index_;
[email protected]f702d572012-12-04 15:56:20706
ckrasic3865ee0f2016-02-29 22:04:56707 // For server push testing
danakjad1777e2016-04-16 00:56:42708 std::unique_ptr<QuicHttpStream> promised_stream_;
Ryan Hamilton0239aac2018-05-19 00:03:13709 spdy::SpdyHeaderBlock push_promise_;
710 spdy::SpdyHeaderBlock promised_response_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52711 const quic::QuicStreamId promise_id_;
ckrasic3865ee0f2016-02-29 22:04:56712 string promise_url_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52713 const quic::QuicStreamId stream_id_;
ckrasic3865ee0f2016-02-29 22:04:56714
Ryan Hamilton8d9ee76e2018-05-29 23:52:52715 const quic::QuicConnectionId connection_id_;
alyssar2adf3ac2016-05-03 17:12:58716 QuicTestPacketMaker client_maker_;
717 QuicTestPacketMaker server_maker_;
[email protected]f702d572012-12-04 15:56:20718 IPEndPoint self_addr_;
719 IPEndPoint peer_addr_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52720 quic::test::MockRandom random_generator_;
rch03b7a202016-02-05 00:54:20721 ProofVerifyDetailsChromium verify_details_;
[email protected]e8ff26842013-03-22 21:02:05722 MockCryptoClientStreamFactory crypto_client_stream_factory_;
danakjad1777e2016-04-16 00:56:42723 std::unique_ptr<StaticSocketDataProvider> socket_data_;
[email protected]f702d572012-12-04 15:56:20724 std::vector<PacketToWrite> writes_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52725 quic::QuicStreamOffset response_offset_;
[email protected]f702d572012-12-04 15:56:20726};
727
Victor Costane635086f2019-01-27 05:20:30728INSTANTIATE_TEST_SUITE_P(
Bence Békyce380cb2018-04-26 23:39:55729 VersionIncludeStreamDependencySequence,
Yixin Wang079ad542018-01-11 04:06:05730 QuicHttpStreamTest,
Victor Vasiliev5d6cdc22019-05-28 20:37:43731 ::testing::Combine(::testing::ValuesIn(quic::AllVersionsExcept99()),
Nick Harper23290b82019-05-02 00:02:56732 ::testing::Bool()));
[email protected]1e960032013-12-20 19:00:20733
734TEST_P(QuicHttpStreamTest, RenewStreamForAuth) {
[email protected]ed3fc15d2013-03-08 18:37:44735 Initialize();
rtennetibe635732014-10-02 22:51:42736 EXPECT_EQ(nullptr, stream_->RenewStreamForAuth());
[email protected]f702d572012-12-04 15:56:20737}
738
mmenkebd84c392015-09-02 14:12:34739TEST_P(QuicHttpStreamTest, CanReuseConnection) {
[email protected]ed3fc15d2013-03-08 18:37:44740 Initialize();
mmenkebd84c392015-09-02 14:12:34741 EXPECT_FALSE(stream_->CanReuseConnection());
[email protected]f702d572012-12-04 15:56:20742}
743
jri231c2972016-03-08 19:50:11744TEST_P(QuicHttpStreamTest, DisableConnectionMigrationForStream) {
Zhongyi Shibb28b1f2018-07-18 02:41:26745 request_.load_flags |= LOAD_DISABLE_CONNECTION_MIGRATION_TO_CELLULAR;
jri231c2972016-03-08 19:50:11746 Initialize();
xunjieli5fafe142016-03-23 23:32:54747 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27748 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:54749 net_log_.bound(), callback_.callback()));
rch08e198572017-05-09 16:56:55750 QuicChromiumClientStream::Handle* client_stream =
jri231c2972016-03-08 19:50:11751 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
Zhongyi Shibb28b1f2018-07-18 02:41:26752 EXPECT_FALSE(client_stream->can_migrate_to_cellular_network());
jri231c2972016-03-08 19:50:11753}
754
[email protected]1e960032013-12-20 19:00:20755TEST_P(QuicHttpStreamTest, GetRequest) {
756 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:45757 size_t spdy_request_header_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52758 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:36759 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:37760 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33761 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
ckrasicbf2f59c2017-05-04 23:54:36762 DEFAULT_PRIORITY, &spdy_request_header_frame_length,
763 &header_stream_offset));
fayang3bcb8b502016-12-07 21:44:37764
[email protected]f702d572012-12-04 15:56:20765 Initialize();
766
767 request_.method = "GET";
rchcd379012017-04-12 21:53:32768 request_.url = GURL("https://www.example.org/");
[email protected]f702d572012-12-04 15:56:20769
xunjieli100937eb52016-09-15 20:09:37770 // Make sure getting load timing from the stream early does not crash.
771 LoadTimingInfo load_timing_info;
772 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
773
xunjieli5fafe142016-03-23 23:32:54774 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27775 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:54776 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:02777 EXPECT_EQ(OK,
778 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20779
780 // Ack the request.
Renjie90e808e2019-01-24 07:24:04781 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]f702d572012-12-04 15:56:20782
robpercival214763f2016-07-01 23:27:01783 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
784 IsError(ERR_IO_PENDING));
[email protected]f702d572012-12-04 15:56:20785
bnc614a92d32016-04-04 13:56:07786 SetResponse("404 Not Found", string());
sclittlec4dc1a32015-09-24 00:15:45787 size_t spdy_response_header_frame_length;
788 ProcessPacket(ConstructResponseHeadersPacket(
789 2, kFin, &spdy_response_header_frame_length));
[email protected]f702d572012-12-04 15:56:20790
791 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:01792 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]cadac622013-06-11 16:46:36793 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:20794 EXPECT_EQ(404, response_.headers->response_code());
795 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
[email protected]6ed67432014-06-24 01:53:53796 EXPECT_FALSE(response_.response_time.is_null());
797 EXPECT_FALSE(response_.request_time.is_null());
[email protected]f702d572012-12-04 15:56:20798
799 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:02800 EXPECT_EQ(0,
801 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
802 callback_.callback()));
[email protected]f702d572012-12-04 15:56:20803 EXPECT_TRUE(stream_->IsResponseBodyComplete());
804 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:10805
xunjieli100937eb52016-09-15 20:09:37806 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
xunjieli84adaab2016-09-20 01:12:28807 ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
xunjieli100937eb52016-09-15 20:09:37808
sclittle1edeeb22015-09-02 20:46:10809 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:45810 // headers and payload.
811 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
812 stream_->GetTotalSentBytes());
813 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length),
814 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:20815}
816
xunjieli100937eb52016-09-15 20:09:37817TEST_P(QuicHttpStreamTest, LoadTimingTwoRequests) {
818 SetRequest("GET", "/", DEFAULT_PRIORITY);
819 size_t spdy_request_header_frame_length;
820
Ryan Hamilton8d9ee76e2018-05-29 23:52:52821 quic::QuicStreamOffset offset = 0;
rch5cb522462017-04-25 20:18:36822 AddWrite(ConstructInitialSettingsPacket(&offset));
xunjieli100937eb52016-09-15 20:09:37823 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33824 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
ckrasicbf2f59c2017-05-04 23:54:36825 DEFAULT_PRIORITY, &spdy_request_header_frame_length, &offset));
xunjieli100937eb52016-09-15 20:09:37826
827 // SetRequest() again for second request as |request_headers_| was moved.
828 SetRequest("GET", "/", DEFAULT_PRIORITY);
829 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33830 3, GetNthClientInitiatedBidirectionalStreamId(1), kIncludeVersion, kFin,
831 DEFAULT_PRIORITY, GetNthClientInitiatedBidirectionalStreamId(0),
Yixin Wang7a3f1b8d2018-01-17 21:40:48832 &spdy_request_header_frame_length, &offset));
Renjie90e808e2019-01-24 07:24:04833 AddWrite(ConstructClientAckPacket(4, 3, 1, 2)); // Ack the responses.
xunjieli100937eb52016-09-15 20:09:37834
835 Initialize();
836
837 request_.method = "GET";
rchcd379012017-04-12 21:53:32838 request_.url = GURL("https://www.example.org/");
xunjieli100937eb52016-09-15 20:09:37839 // Start first request.
840 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27841 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli100937eb52016-09-15 20:09:37842 net_log_.bound(), callback_.callback()));
843 EXPECT_EQ(OK,
844 stream_->SendRequest(headers_, &response_, callback_.callback()));
845
846 // Start a second request.
Ryan Hamilton6c2a2a82017-12-15 02:06:28847 QuicHttpStream stream2(
848 session_->CreateHandle(HostPortPair("www.example.org", 443)));
xunjieli100937eb52016-09-15 20:09:37849 TestCompletionCallback callback2;
850 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27851 stream2.InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli100937eb52016-09-15 20:09:37852 net_log_.bound(), callback2.callback()));
853 EXPECT_EQ(OK,
854 stream2.SendRequest(headers_, &response_, callback2.callback()));
855
856 // Ack both requests.
Renjie90e808e2019-01-24 07:24:04857 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
xunjieli100937eb52016-09-15 20:09:37858
859 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
860 IsError(ERR_IO_PENDING));
861 size_t spdy_response_header_frame_length;
862 SetResponse("200 OK", string());
863 ProcessPacket(InnerConstructResponseHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33864 2, GetNthClientInitiatedBidirectionalStreamId(0), kFin,
ckrasicbf2f59c2017-05-04 23:54:36865 &spdy_response_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37866
867 // Now that the headers have been processed, the callback will return.
868 EXPECT_THAT(callback_.WaitForResult(), IsOk());
869 EXPECT_EQ(200, response_.headers->response_code());
870
871 // There is no body, so this should return immediately.
872 EXPECT_EQ(0,
873 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
874 callback_.callback()));
875 EXPECT_TRUE(stream_->IsResponseBodyComplete());
876
877 LoadTimingInfo load_timing_info;
878 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
xunjieli84adaab2016-09-20 01:12:28879 ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
xunjieli100937eb52016-09-15 20:09:37880
881 // SetResponse() again for second request as |response_headers_| was moved.
882 SetResponse("200 OK", string());
883 EXPECT_THAT(stream2.ReadResponseHeaders(callback2.callback()),
884 IsError(ERR_IO_PENDING));
885
886 ProcessPacket(InnerConstructResponseHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33887 3, GetNthClientInitiatedBidirectionalStreamId(1), kFin,
ckrasicbf2f59c2017-05-04 23:54:36888 &spdy_response_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37889
890 EXPECT_THAT(callback2.WaitForResult(), IsOk());
891
892 // There is no body, so this should return immediately.
893 EXPECT_EQ(0,
894 stream2.ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
895 callback2.callback()));
896 EXPECT_TRUE(stream2.IsResponseBodyComplete());
897
898 LoadTimingInfo load_timing_info2;
899 EXPECT_TRUE(stream2.GetLoadTimingInfo(&load_timing_info2));
xunjieli84adaab2016-09-20 01:12:28900 ExpectLoadTimingValid(load_timing_info2, /*session_reused=*/true);
xunjieli100937eb52016-09-15 20:09:37901}
902
xunjieli34291fe12016-03-02 13:58:38903// QuicHttpStream does not currently support trailers. It should ignore
904// trailers upon receiving them.
905TEST_P(QuicHttpStreamTest, GetRequestWithTrailers) {
906 SetRequest("GET", "/", DEFAULT_PRIORITY);
907 size_t spdy_request_header_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52908 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:36909 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:37910 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33911 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
ckrasicbf2f59c2017-05-04 23:54:36912 DEFAULT_PRIORITY, &spdy_request_header_frame_length,
913 &header_stream_offset));
Renjie90e808e2019-01-24 07:24:04914 AddWrite(ConstructClientAckPacket(3, 3, 1, 2)); // Ack the data packet.
xunjieli34291fe12016-03-02 13:58:38915
916 Initialize();
917
918 request_.method = "GET";
rchcd379012017-04-12 21:53:32919 request_.url = GURL("https://www.example.org/");
xunjieli34291fe12016-03-02 13:58:38920
xunjieli5fafe142016-03-23 23:32:54921 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27922 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:54923 net_log_.bound(), callback_.callback()));
924
xunjieli34291fe12016-03-02 13:58:38925 EXPECT_EQ(OK,
926 stream_->SendRequest(headers_, &response_, callback_.callback()));
xunjieli34291fe12016-03-02 13:58:38927 // Ack the request.
Renjie90e808e2019-01-24 07:24:04928 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
xunjieli34291fe12016-03-02 13:58:38929
robpercival214763f2016-07-01 23:27:01930 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
931 IsError(ERR_IO_PENDING));
xunjieli34291fe12016-03-02 13:58:38932
bnc614a92d32016-04-04 13:56:07933 SetResponse("200 OK", string());
xunjieli34291fe12016-03-02 13:58:38934
935 // Send the response headers.
936 size_t spdy_response_header_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52937 quic::QuicStreamOffset offset = 0;
xunjieli34291fe12016-03-02 13:58:38938 ProcessPacket(ConstructResponseHeadersPacketWithOffset(
939 2, !kFin, &spdy_response_header_frame_length, &offset));
940 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:01941 EXPECT_THAT(callback_.WaitForResult(), IsOk());
xunjieli34291fe12016-03-02 13:58:38942 ASSERT_TRUE(response_.headers.get());
943 EXPECT_EQ(200, response_.headers->response_code());
944 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
945 EXPECT_FALSE(response_.response_time.is_null());
946 EXPECT_FALSE(response_.request_time.is_null());
947
948 // Send the response body.
949 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:43950 std::string header = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:41951 ProcessPacket(ConstructServerDataPacket(3, false, !kFin, /*offset=*/0,
952 header + kResponseBody));
Ryan Hamilton0239aac2018-05-19 00:03:13953 spdy::SpdyHeaderBlock trailers;
xunjieli34291fe12016-03-02 13:58:38954 size_t spdy_trailers_frame_length;
955 trailers["foo"] = "bar";
Ryan Hamilton8d9ee76e2018-05-29 23:52:52956 trailers[quic::kFinalOffsetHeaderKey] =
Raul Tambre8c1981d2019-02-08 02:22:26957 base::NumberToString(strlen(kResponseBody) + header.length());
xunjieli34291fe12016-03-02 13:58:38958 ProcessPacket(ConstructResponseTrailersPacket(
bnc086b39e12016-06-24 13:05:26959 4, kFin, std::move(trailers), &spdy_trailers_frame_length, &offset));
xunjieli34291fe12016-03-02 13:58:38960
961 // Make sure trailers are processed.
fdoray92e35a72016-06-10 15:54:55962 base::RunLoop().RunUntilIdle();
xunjieli34291fe12016-03-02 13:58:38963
964 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
965 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
966 callback_.callback()));
967 EXPECT_TRUE(stream_->IsResponseBodyComplete());
968
969 EXPECT_EQ(OK,
970 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
971 callback_.callback()));
972
973 EXPECT_TRUE(stream_->IsResponseBodyComplete());
974 EXPECT_TRUE(AtEof());
975
976 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
977 // headers and payload.
978 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
979 stream_->GetTotalSentBytes());
Renjief49758b2019-01-11 23:32:41980 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length +
981 strlen(kResponseBody) + header.length() +
982 +spdy_trailers_frame_length),
983 stream_->GetTotalReceivedBytes());
xunjieli5fafe142016-03-23 23:32:54984 // Check that NetLog was filled as expected.
985 TestNetLogEntry::List entries;
986 net_log_.GetEntries(&entries);
987 size_t pos = ExpectLogContainsSomewhere(
988 entries, /*min_offset=*/0,
mikecirone8b85c432016-09-08 19:11:00989 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
990 NetLogEventPhase::NONE);
xunjieli5fafe142016-03-23 23:32:54991 pos = ExpectLogContainsSomewhere(
992 entries, /*min_offset=*/pos,
mikecirone8b85c432016-09-08 19:11:00993 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
994 NetLogEventPhase::NONE);
xunjieli5fafe142016-03-23 23:32:54995 ExpectLogContainsSomewhere(
996 entries, /*min_offset=*/pos,
mikecirone8b85c432016-09-08 19:11:00997 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
998 NetLogEventPhase::NONE);
xunjieli34291fe12016-03-02 13:58:38999}
1000
[email protected]3e7dca62013-09-10 16:14:231001// Regression test for http://crbug.com/288128
[email protected]1e960032013-12-20 19:00:201002TEST_P(QuicHttpStreamTest, GetRequestLargeResponse) {
1003 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451004 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521005 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361006 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:371007 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:331008 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
ckrasicbf2f59c2017-05-04 23:54:361009 DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
1010 &header_stream_offset));
[email protected]3e7dca62013-09-10 16:14:231011 Initialize();
1012
1013 request_.method = "GET";
rchcd379012017-04-12 21:53:321014 request_.url = GURL("https://www.example.org/");
[email protected]3e7dca62013-09-10 16:14:231015
xunjieli5fafe142016-03-23 23:32:541016 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271017 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541018 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021019 EXPECT_EQ(OK,
1020 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:231021
1022 // Ack the request.
Renjie90e808e2019-01-24 07:24:041023 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]3e7dca62013-09-10 16:14:231024
robpercival214763f2016-07-01 23:27:011025 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1026 IsError(ERR_IO_PENDING));
[email protected]3e7dca62013-09-10 16:14:231027
bnc086b39e12016-06-24 13:05:261028 response_headers_[":status"] = "200 OK";
1029 response_headers_[":version"] = "HTTP/1.1";
1030 response_headers_["content-type"] = "text/plain";
1031 response_headers_["big6"] = string(1000, 'x'); // Lots of x's.
[email protected]3e7dca62013-09-10 16:14:231032
sclittlec4dc1a32015-09-24 00:15:451033 size_t spdy_response_headers_frame_length;
1034 ProcessPacket(ConstructResponseHeadersPacket(
1035 2, kFin, &spdy_response_headers_frame_length));
[email protected]3e7dca62013-09-10 16:14:231036
1037 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:011038 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]3e7dca62013-09-10 16:14:231039 ASSERT_TRUE(response_.headers.get());
1040 EXPECT_EQ(200, response_.headers->response_code());
1041 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1042
1043 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:021044 EXPECT_EQ(0,
1045 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1046 callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:231047 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1048 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101049
1050 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451051 // headers and payload.
1052 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1053 stream_->GetTotalSentBytes());
1054 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length),
1055 stream_->GetTotalReceivedBytes());
[email protected]3e7dca62013-09-10 16:14:231056}
1057
rchf9f103cbc2014-08-30 05:28:041058// Regression test for http://crbug.com/409101
1059TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendRequest) {
1060 SetRequest("GET", "/", DEFAULT_PRIORITY);
1061 Initialize();
1062
1063 request_.method = "GET";
rchcd379012017-04-12 21:53:321064 request_.url = GURL("https://www.example.org/");
rchf9f103cbc2014-08-30 05:28:041065
xunjieli5fafe142016-03-23 23:32:541066 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271067 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541068 net_log_.bound(), callback_.callback()));
rchf9f103cbc2014-08-30 05:28:041069
jri78ec06a2016-03-31 18:19:401070 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521071 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rchf9f103cbc2014-08-30 05:28:041072
1073 EXPECT_EQ(ERR_CONNECTION_CLOSED,
rjshaded5ced072015-12-18 19:26:021074 stream_->SendRequest(headers_, &response_, callback_.callback()));
sclittle1edeeb22015-09-02 20:46:101075
1076 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1077 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rchf9f103cbc2014-08-30 05:28:041078}
1079
rch03b7a202016-02-05 00:54:201080// Regression test for http://crbug.com/584441
1081TEST_P(QuicHttpStreamTest, GetSSLInfoAfterSessionClosed) {
1082 SetRequest("GET", "/", DEFAULT_PRIORITY);
1083 Initialize();
1084
1085 request_.method = "GET";
rchcd379012017-04-12 21:53:321086 request_.url = GURL("https://www.example.org/");
rch03b7a202016-02-05 00:54:201087
xunjieli5fafe142016-03-23 23:32:541088 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271089 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541090 net_log_.bound(), callback_.callback()));
rch03b7a202016-02-05 00:54:201091
1092 SSLInfo ssl_info;
rch11565e02016-02-09 20:13:471093 EXPECT_FALSE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:201094 stream_->GetSSLInfo(&ssl_info);
rch11565e02016-02-09 20:13:471095 EXPECT_TRUE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:201096
jri78ec06a2016-03-31 18:19:401097 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521098 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rch03b7a202016-02-05 00:54:201099
rch11565e02016-02-09 20:13:471100 SSLInfo ssl_info2;
1101 stream_->GetSSLInfo(&ssl_info2);
1102 EXPECT_TRUE(ssl_info2.is_valid());
rch03b7a202016-02-05 00:54:201103}
1104
rchcd379012017-04-12 21:53:321105TEST_P(QuicHttpStreamTest, GetAlternativeService) {
1106 SetRequest("GET", "/", DEFAULT_PRIORITY);
1107 Initialize();
1108
1109 request_.method = "GET";
1110 request_.url = GURL("https://www.example.org/");
1111
1112 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271113 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
rchcd379012017-04-12 21:53:321114 net_log_.bound(), callback_.callback()));
1115
1116 AlternativeService alternative_service;
1117 EXPECT_TRUE(stream_->GetAlternativeService(&alternative_service));
1118 EXPECT_EQ(AlternativeService(kProtoQUIC, "www.example.org", 443),
1119 alternative_service);
1120
1121 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521122 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rchcd379012017-04-12 21:53:321123
1124 AlternativeService alternative_service2;
1125 EXPECT_TRUE(stream_->GetAlternativeService(&alternative_service2));
1126 EXPECT_EQ(AlternativeService(kProtoQUIC, "www.example.org", 443),
1127 alternative_service2);
1128}
1129
zhongyica364fbb2015-12-12 03:39:121130TEST_P(QuicHttpStreamTest, LogGranularQuicConnectionError) {
1131 SetRequest("GET", "/", DEFAULT_PRIORITY);
1132 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521133 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361134 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:371135 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:331136 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
ckrasicbf2f59c2017-05-04 23:54:361137 DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
1138 &header_stream_offset));
fayang3bcb8b502016-12-07 21:44:371139 AddWrite(ConstructAckAndRstStreamPacket(3));
zhongyica364fbb2015-12-12 03:39:121140 Initialize();
1141
1142 request_.method = "GET";
rchcd379012017-04-12 21:53:321143 request_.url = GURL("https://www.example.org/");
zhongyica364fbb2015-12-12 03:39:121144
xunjieli5fafe142016-03-23 23:32:541145 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271146 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541147 net_log_.bound(), callback_.callback()));
zhongyica364fbb2015-12-12 03:39:121148 EXPECT_EQ(OK,
1149 stream_->SendRequest(headers_, &response_, callback_.callback()));
1150
1151 // Ack the request.
Renjie90e808e2019-01-24 07:24:041152 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011153 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1154 IsError(ERR_IO_PENDING));
zhongyica364fbb2015-12-12 03:39:121155
Ryan Hamilton8d9ee76e2018-05-29 23:52:521156 quic::QuicConnectionCloseFrame frame;
Zhongyi Shica576df2019-04-12 17:43:401157 frame.quic_error_code = quic::QUIC_PEER_GOING_AWAY;
rch1c5b74a2016-06-23 22:10:551158 session_->connection()->OnConnectionCloseFrame(frame);
zhongyica364fbb2015-12-12 03:39:121159
1160 NetErrorDetails details;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521161 EXPECT_EQ(quic::QUIC_NO_ERROR, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121162 stream_->PopulateNetErrorDetails(&details);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521163 EXPECT_EQ(quic::QUIC_PEER_GOING_AWAY, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121164}
1165
Ryan Hamiltone316e482017-08-17 02:48:531166TEST_P(QuicHttpStreamTest, LogGranularQuicErrorIfHandshakeNotConfirmed) {
rch617e0652017-04-26 17:57:511167 // By default the test setup defaults handshake to be confirmed. Manually set
1168 // it to be not confirmed.
rch617e0652017-04-26 17:57:511169 crypto_client_stream_factory_.set_handshake_mode(
Ryan Hamilton9835e662018-08-02 05:36:271170 MockCryptoClientStream::ZERO_RTT);
rch617e0652017-04-26 17:57:511171
zhongyica364fbb2015-12-12 03:39:121172 SetRequest("GET", "/", DEFAULT_PRIORITY);
1173 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521174 quic::QuicStreamOffset header_stream_offset = 0;
Michael Warres167db3e2019-03-01 21:38:031175 client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
fayang3bcb8b502016-12-07 21:44:371176 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:331177 1, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
ckrasicbf2f59c2017-05-04 23:54:361178 DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
1179 &header_stream_offset));
zhongyica364fbb2015-12-12 03:39:121180 Initialize();
1181
1182 request_.method = "GET";
rchcd379012017-04-12 21:53:321183 request_.url = GURL("https://www.example.org/");
zhongyica364fbb2015-12-12 03:39:121184
xunjieli5fafe142016-03-23 23:32:541185 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271186 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541187 net_log_.bound(), callback_.callback()));
zhongyica364fbb2015-12-12 03:39:121188 EXPECT_EQ(OK,
1189 stream_->SendRequest(headers_, &response_, callback_.callback()));
1190
1191 // Ack the request.
Renjie90e808e2019-01-24 07:24:041192 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011193 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1194 IsError(ERR_IO_PENDING));
zhongyica364fbb2015-12-12 03:39:121195
Ryan Hamilton8d9ee76e2018-05-29 23:52:521196 quic::QuicConnectionCloseFrame frame;
Zhongyi Shica576df2019-04-12 17:43:401197 frame.quic_error_code = quic::QUIC_PEER_GOING_AWAY;
rch1c5b74a2016-06-23 22:10:551198 session_->connection()->OnConnectionCloseFrame(frame);
zhongyica364fbb2015-12-12 03:39:121199
1200 NetErrorDetails details;
zhongyica364fbb2015-12-12 03:39:121201 stream_->PopulateNetErrorDetails(&details);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521202 EXPECT_EQ(quic::QUIC_PEER_GOING_AWAY, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121203}
1204
rch11a114a2014-09-04 23:41:591205// Regression test for http://crbug.com/409871
1206TEST_P(QuicHttpStreamTest, SessionClosedBeforeReadResponseHeaders) {
1207 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451208 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521209 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361210 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:371211 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:331212 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
ckrasicbf2f59c2017-05-04 23:54:361213 DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
1214 &header_stream_offset));
rch11a114a2014-09-04 23:41:591215 Initialize();
1216
1217 request_.method = "GET";
rchcd379012017-04-12 21:53:321218 request_.url = GURL("https://www.example.org/");
rch11a114a2014-09-04 23:41:591219
xunjieli5fafe142016-03-23 23:32:541220 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271221 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541222 net_log_.bound(), callback_.callback()));
rch11a114a2014-09-04 23:41:591223
rjshaded5ced072015-12-18 19:26:021224 EXPECT_EQ(OK,
1225 stream_->SendRequest(headers_, &response_, callback_.callback()));
rch11a114a2014-09-04 23:41:591226
jri78ec06a2016-03-31 18:19:401227 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521228 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rch11a114a2014-09-04 23:41:591229
1230 EXPECT_NE(OK, stream_->ReadResponseHeaders(callback_.callback()));
sclittle1edeeb22015-09-02 20:46:101231
1232 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451233 // headers and payload.
1234 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1235 stream_->GetTotalSentBytes());
sclittle1edeeb22015-09-02 20:46:101236 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rch11a114a2014-09-04 23:41:591237}
1238
[email protected]1e960032013-12-20 19:00:201239TEST_P(QuicHttpStreamTest, SendPostRequest) {
1240 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451241 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521242 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361243 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
Yixin Wange7ecc472018-03-06 19:00:251244
Victor Vasiliev076657c2019-03-12 02:46:431245 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harper23290b82019-05-02 00:02:561246 if (version_.transport_version != quic::QUIC_VERSION_99) {
Renjief49758b2019-01-11 23:32:411247 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1248 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
1249 DEFAULT_PRIORITY, 0, &header_stream_offset,
1250 &spdy_request_headers_frame_length, {kUploadData}));
1251 } else {
1252 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1253 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
1254 DEFAULT_PRIORITY, 0, &header_stream_offset,
1255 &spdy_request_headers_frame_length, {header, kUploadData}));
1256 }
Yixin Wange7ecc472018-03-06 19:00:251257
Renjie90e808e2019-01-24 07:24:041258 AddWrite(ConstructClientAckPacket(3, 3, 1, 2));
[email protected]f702d572012-12-04 15:56:201259
1260 Initialize();
1261
danakjad1777e2016-04-16 00:56:421262 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:191263 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
ricea2deef682016-09-09 08:04:071264 kUploadData, strlen(kUploadData)));
rch97827ee2017-05-24 23:49:121265 upload_data_stream_ =
Jeremy Roman0579ed62017-08-29 15:56:191266 std::make_unique<ElementsUploadDataStream>(std::move(element_readers), 0);
[email protected]f702d572012-12-04 15:56:201267 request_.method = "POST";
rchcd379012017-04-12 21:53:321268 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121269 request_.upload_data_stream = upload_data_stream_.get();
Bence Békyd8a21fc32018-06-27 18:29:581270 ASSERT_THAT(request_.upload_data_stream->Init(CompletionOnceCallback(),
tfarina42834112016-09-22 13:38:201271 NetLogWithSource()),
1272 IsOk());
[email protected]f702d572012-12-04 15:56:201273
xunjieli5fafe142016-03-23 23:32:541274 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271275 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541276 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021277 EXPECT_EQ(OK,
1278 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:201279
1280 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041281 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]f702d572012-12-04 15:56:201282
1283 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071284 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451285 size_t spdy_response_headers_frame_length;
1286 ProcessPacket(ConstructResponseHeadersPacket(
1287 2, !kFin, &spdy_response_headers_frame_length));
[email protected]f702d572012-12-04 15:56:201288
rchfb47f712017-05-21 03:24:001289 // The headers have already arrived.
1290 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]cadac622013-06-11 16:46:361291 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:201292 EXPECT_EQ(200, response_.headers->response_code());
1293 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1294
1295 // Send the response body.
1296 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431297 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:411298 ProcessPacket(
1299 ConstructServerDataPacket(3, false, kFin, 0, header2 + kResponseBody));
[email protected]f702d572012-12-04 15:56:201300 // Since the body has already arrived, this should return immediately.
1301 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
1302 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1303 callback_.callback()));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291304 EXPECT_EQ(0,
1305 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1306 callback_.callback()));
1307
1308 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1309 EXPECT_TRUE(AtEof());
1310
1311 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
1312 // headers and payload.
1313 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411314 strlen(kUploadData) + header.length()),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291315 stream_->GetTotalSentBytes());
1316 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411317 strlen(kResponseBody) + header2.length()),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291318 stream_->GetTotalReceivedBytes());
1319}
1320
1321TEST_P(QuicHttpStreamTest, SendPostRequestAndReceiveSoloFin) {
1322 SetRequest("POST", "/", DEFAULT_PRIORITY);
1323 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521324 quic::QuicStreamOffset header_stream_offset = 0;
Ryan Hamilton2ef0a9c2017-07-25 03:18:291325 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
Victor Vasiliev076657c2019-03-12 02:46:431326 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harper23290b82019-05-02 00:02:561327 if (version_.transport_version != quic::QUIC_VERSION_99) {
Renjief49758b2019-01-11 23:32:411328 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1329 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
1330 DEFAULT_PRIORITY, 0, &header_stream_offset,
1331 &spdy_request_headers_frame_length, {kUploadData}));
1332 } else {
1333 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1334 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
1335 DEFAULT_PRIORITY, 0, &header_stream_offset,
1336 &spdy_request_headers_frame_length, {header, kUploadData}));
1337 }
1338
Renjie90e808e2019-01-24 07:24:041339 AddWrite(ConstructClientAckPacket(3, 3, 1, 2));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291340
1341 Initialize();
1342
1343 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:191344 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
Ryan Hamilton2ef0a9c2017-07-25 03:18:291345 kUploadData, strlen(kUploadData)));
1346 upload_data_stream_ =
Jeremy Roman0579ed62017-08-29 15:56:191347 std::make_unique<ElementsUploadDataStream>(std::move(element_readers), 0);
Ryan Hamilton2ef0a9c2017-07-25 03:18:291348 request_.method = "POST";
1349 request_.url = GURL("https://www.example.org/");
1350 request_.upload_data_stream = upload_data_stream_.get();
Bence Békyd8a21fc32018-06-27 18:29:581351 ASSERT_THAT(request_.upload_data_stream->Init(CompletionOnceCallback(),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291352 NetLogWithSource()),
1353 IsOk());
1354
1355 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271356 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
Ryan Hamilton2ef0a9c2017-07-25 03:18:291357 net_log_.bound(), callback_.callback()));
1358 EXPECT_EQ(OK,
1359 stream_->SendRequest(headers_, &response_, callback_.callback()));
1360
1361 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041362 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291363
1364 // Send the response headers (but not the body).
1365 SetResponse("200 OK", string());
1366 size_t spdy_response_headers_frame_length;
1367 ProcessPacket(ConstructResponseHeadersPacket(
1368 2, !kFin, &spdy_response_headers_frame_length));
1369
1370 // The headers have already arrived.
1371 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
1372 ASSERT_TRUE(response_.headers.get());
1373 EXPECT_EQ(200, response_.headers->response_code());
1374 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1375
1376 // Send the response body.
1377 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431378 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:411379 ProcessPacket(
1380 ConstructServerDataPacket(3, false, !kFin, 0, header2 + kResponseBody));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291381 // Since the body has already arrived, this should return immediately.
1382 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
1383 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1384 callback_.callback()));
Renjief49758b2019-01-11 23:32:411385 ProcessPacket(ConstructServerDataPacket(
1386 4, false, kFin, base::size(kResponseBody) - 1 + header2.length(), ""));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291387 EXPECT_EQ(0,
1388 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1389 callback_.callback()));
[email protected]f702d572012-12-04 15:56:201390
1391 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1392 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101393
1394 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451395 // headers and payload.
1396 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411397 strlen(kUploadData) + header.length()),
sclittle1edeeb22015-09-02 20:46:101398 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451399 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411400 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101401 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:201402}
1403
[email protected]1e960032013-12-20 19:00:201404TEST_P(QuicHttpStreamTest, SendChunkedPostRequest) {
1405 SetRequest("POST", "/", DEFAULT_PRIORITY);
[email protected]c9e49a02013-02-26 05:56:471406 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:451407 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521408 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361409 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
Victor Vasiliev076657c2019-03-12 02:46:431410 std::string header = ConstructDataHeader(chunk_size);
Nick Harper23290b82019-05-02 00:02:561411 if (version_.transport_version == quic::QUIC_VERSION_99) {
Renjief49758b2019-01-11 23:32:411412 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1413 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
1414 !kFin, DEFAULT_PRIORITY, 0, &header_stream_offset,
1415 &spdy_request_headers_frame_length, {header, kUploadData}));
1416 AddWrite(ConstructClientMultipleDataFramesPacket(
1417 3, kIncludeVersion, kFin, header.length() + chunk_size,
1418 {header, kUploadData}));
1419 } else {
1420 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1421 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
1422 !kFin, DEFAULT_PRIORITY, 0, &header_stream_offset,
1423 &spdy_request_headers_frame_length, {kUploadData}));
1424 AddWrite(ConstructClientDataPacket(3, kIncludeVersion, kFin, chunk_size,
1425 kUploadData));
1426 }
1427
Renjie90e808e2019-01-24 07:24:041428 AddWrite(ConstructClientAckPacket(4, 3, 1, 2));
[email protected]c9e49a02013-02-26 05:56:471429 Initialize();
1430
Jeremy Roman0579ed62017-08-29 15:56:191431 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121432 auto* chunked_upload_stream =
1433 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1434 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
[email protected]c9e49a02013-02-26 05:56:471435
1436 request_.method = "POST";
rchcd379012017-04-12 21:53:321437 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121438 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071439 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201440 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]c9e49a02013-02-26 05:56:471441
xunjieli5fafe142016-03-23 23:32:541442 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271443 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541444 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021445 ASSERT_EQ(ERR_IO_PENDING,
1446 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]c9e49a02013-02-26 05:56:471447
rch97827ee2017-05-24 23:49:121448 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
robpercival214763f2016-07-01 23:27:011449 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]c9e49a02013-02-26 05:56:471450
1451 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041452 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]c9e49a02013-02-26 05:56:471453
1454 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071455 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451456 size_t spdy_response_headers_frame_length;
1457 ProcessPacket(ConstructResponseHeadersPacket(
1458 2, !kFin, &spdy_response_headers_frame_length));
[email protected]c9e49a02013-02-26 05:56:471459
rchfb47f712017-05-21 03:24:001460 // The headers have already arrived.
1461 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]cadac622013-06-11 16:46:361462 ASSERT_TRUE(response_.headers.get());
[email protected]c9e49a02013-02-26 05:56:471463 EXPECT_EQ(200, response_.headers->response_code());
1464 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1465
1466 // Send the response body.
1467 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431468 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
alyssar2adf3ac2016-05-03 17:12:581469 ProcessPacket(ConstructServerDataPacket(
Renjief49758b2019-01-11 23:32:411470 3, false, kFin, response_data_.length(), header2 + kResponseBody));
[email protected]c9e49a02013-02-26 05:56:471471
1472 // Since the body has already arrived, this should return immediately.
1473 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1474 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1475 callback_.callback()));
1476
1477 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1478 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101479
1480 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451481 // headers and payload.
1482 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411483 strlen(kUploadData) * 2 + header.length() * 2),
sclittle1edeeb22015-09-02 20:46:101484 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451485 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411486 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101487 stream_->GetTotalReceivedBytes());
[email protected]c9e49a02013-02-26 05:56:471488}
1489
[email protected]16ba7742014-08-22 00:57:251490TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithFinalEmptyDataPacket) {
1491 SetRequest("POST", "/", DEFAULT_PRIORITY);
1492 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:451493 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521494 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361495 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
Victor Vasiliev076657c2019-03-12 02:46:431496 std::string header = ConstructDataHeader(chunk_size);
Renjief49758b2019-01-11 23:32:411497
Nick Harper23290b82019-05-02 00:02:561498 if (version_.transport_version != quic::QUIC_VERSION_99) {
Renjief49758b2019-01-11 23:32:411499 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1500 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
1501 !kFin, DEFAULT_PRIORITY, 0, &header_stream_offset,
1502 &spdy_request_headers_frame_length, {kUploadData}));
1503 } else {
1504 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1505 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
1506 !kFin, DEFAULT_PRIORITY, 0, &header_stream_offset,
1507 &spdy_request_headers_frame_length, {header, kUploadData}));
1508 }
1509 AddWrite(ConstructClientDataPacket(3, kIncludeVersion, kFin,
1510 chunk_size + header.length(), ""));
Renjie90e808e2019-01-24 07:24:041511 AddWrite(ConstructClientAckPacket(4, 3, 1, 2));
[email protected]16ba7742014-08-22 00:57:251512 Initialize();
1513
Jeremy Roman0579ed62017-08-29 15:56:191514 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121515 auto* chunked_upload_stream =
1516 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1517 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
[email protected]16ba7742014-08-22 00:57:251518
1519 request_.method = "POST";
rchcd379012017-04-12 21:53:321520 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121521 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071522 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201523 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]16ba7742014-08-22 00:57:251524
xunjieli5fafe142016-03-23 23:32:541525 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271526 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541527 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021528 ASSERT_EQ(ERR_IO_PENDING,
1529 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251530
rch97827ee2017-05-24 23:49:121531 chunked_upload_stream->AppendData(nullptr, 0, true);
robpercival214763f2016-07-01 23:27:011532 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]16ba7742014-08-22 00:57:251533
Renjie90e808e2019-01-24 07:24:041534 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]16ba7742014-08-22 00:57:251535
1536 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071537 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451538 size_t spdy_response_headers_frame_length;
1539 ProcessPacket(ConstructResponseHeadersPacket(
1540 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251541
rchfb47f712017-05-21 03:24:001542 // The headers have already arrived.
1543 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]16ba7742014-08-22 00:57:251544 ASSERT_TRUE(response_.headers.get());
1545 EXPECT_EQ(200, response_.headers->response_code());
1546 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1547
1548 // Send the response body.
1549 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431550 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
alyssar2adf3ac2016-05-03 17:12:581551 ProcessPacket(ConstructServerDataPacket(
Renjief49758b2019-01-11 23:32:411552 3, false, kFin, response_data_.length(), header2 + kResponseBody));
[email protected]16ba7742014-08-22 00:57:251553
rchb27683c2015-07-29 23:53:501554 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251555 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1556 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1557 callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251558 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1559 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101560
1561 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451562 // headers and payload.
1563 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411564 strlen(kUploadData) + header.length()),
sclittle1edeeb22015-09-02 20:46:101565 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451566 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411567 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101568 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251569}
1570
1571TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithOneEmptyDataPacket) {
1572 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451573 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521574 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361575 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:371576 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:331577 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, !kFin,
ckrasicbf2f59c2017-05-04 23:54:361578 DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
1579 &header_stream_offset));
fayang3bcb8b502016-12-07 21:44:371580 AddWrite(ConstructClientDataPacket(3, kIncludeVersion, kFin, 0, ""));
Renjie90e808e2019-01-24 07:24:041581 AddWrite(ConstructClientAckPacket(4, 3, 1, 2));
[email protected]16ba7742014-08-22 00:57:251582 Initialize();
1583
Jeremy Roman0579ed62017-08-29 15:56:191584 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121585 auto* chunked_upload_stream =
1586 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
[email protected]16ba7742014-08-22 00:57:251587
1588 request_.method = "POST";
rchcd379012017-04-12 21:53:321589 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121590 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071591 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201592 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]16ba7742014-08-22 00:57:251593
xunjieli5fafe142016-03-23 23:32:541594 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271595 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541596 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021597 ASSERT_EQ(ERR_IO_PENDING,
1598 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251599
rch97827ee2017-05-24 23:49:121600 chunked_upload_stream->AppendData(nullptr, 0, true);
robpercival214763f2016-07-01 23:27:011601 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]16ba7742014-08-22 00:57:251602
Renjie90e808e2019-01-24 07:24:041603 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]16ba7742014-08-22 00:57:251604
1605 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071606 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451607 size_t spdy_response_headers_frame_length;
1608 ProcessPacket(ConstructResponseHeadersPacket(
1609 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251610
rchfb47f712017-05-21 03:24:001611 // The headers have already arrived.
1612 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]16ba7742014-08-22 00:57:251613 ASSERT_TRUE(response_.headers.get());
1614 EXPECT_EQ(200, response_.headers->response_code());
1615 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1616
1617 // Send the response body.
1618 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431619 std::string header = ConstructDataHeader(strlen(kResponseBody));
alyssar2adf3ac2016-05-03 17:12:581620 ProcessPacket(ConstructServerDataPacket(
Renjief49758b2019-01-11 23:32:411621 3, false, kFin, response_data_.length(), header + kResponseBody));
[email protected]16ba7742014-08-22 00:57:251622
rchb27683c2015-07-29 23:53:501623 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251624 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1625 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1626 callback_.callback()));
1627
1628 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1629 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101630
1631 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451632 // headers and payload.
1633 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1634 stream_->GetTotalSentBytes());
1635 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411636 strlen(kResponseBody) + header.length()),
sclittle1edeeb22015-09-02 20:46:101637 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251638}
1639
[email protected]1e960032013-12-20 19:00:201640TEST_P(QuicHttpStreamTest, DestroyedEarly) {
1641 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451642 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521643 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361644 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:371645 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:331646 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
ckrasicbf2f59c2017-05-04 23:54:361647 DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
1648 &header_stream_offset));
fayang3bcb8b502016-12-07 21:44:371649 AddWrite(ConstructAckAndRstStreamPacket(3));
[email protected]63534512012-12-23 18:49:001650 Initialize();
1651
1652 request_.method = "GET";
rchcd379012017-04-12 21:53:321653 request_.url = GURL("https://www.example.org/");
[email protected]63534512012-12-23 18:49:001654
xunjieli5fafe142016-03-23 23:32:541655 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271656 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541657 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021658 EXPECT_EQ(OK,
1659 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]63534512012-12-23 18:49:001660
1661 // Ack the request.
Renjie90e808e2019-01-24 07:24:041662 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
rchfb47f712017-05-21 03:24:001663 EXPECT_THAT(stream_->ReadResponseHeaders(
1664 base::Bind(&QuicHttpStreamTest::CloseStream,
1665 base::Unretained(this), stream_.get())),
robpercival214763f2016-07-01 23:27:011666 IsError(ERR_IO_PENDING));
[email protected]63534512012-12-23 18:49:001667
1668 // Send the response with a body.
[email protected]1e960032013-12-20 19:00:201669 SetResponse("404 OK", "hello world!");
[email protected]63534512012-12-23 18:49:001670 // In the course of processing this packet, the QuicHttpStream close itself.
rchfb47f712017-05-21 03:24:001671 size_t response_size = 0;
rch1bcfddf22017-06-03 00:26:291672 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin, &response_size));
[email protected]63534512012-12-23 18:49:001673
fdoray92e35a72016-06-10 15:54:551674 base::RunLoop().RunUntilIdle();
rchb27683c2015-07-29 23:53:501675
[email protected]63534512012-12-23 18:49:001676 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101677
1678 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451679 // headers and payload.
1680 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1681 stream_->GetTotalSentBytes());
rchfb47f712017-05-21 03:24:001682 // The stream was closed after receiving the headers.
1683 EXPECT_EQ(static_cast<int64_t>(response_size),
1684 stream_->GetTotalReceivedBytes());
[email protected]63534512012-12-23 18:49:001685}
1686
[email protected]1e960032013-12-20 19:00:201687TEST_P(QuicHttpStreamTest, Priority) {
1688 SetRequest("GET", "/", MEDIUM);
sclittlec4dc1a32015-09-24 00:15:451689 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521690 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361691 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:371692 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:331693 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
1694 MEDIUM, &spdy_request_headers_frame_length, &header_stream_offset));
[email protected]24e5bc52013-09-18 15:36:581695 Initialize();
1696
1697 request_.method = "GET";
rchcd379012017-04-12 21:53:321698 request_.url = GURL("https://www.example.org/");
[email protected]24e5bc52013-09-18 15:36:581699
Steven Valdezb4ff0412018-01-18 22:39:271700 EXPECT_EQ(OK,
1701 stream_->InitializeStream(&request_, true, MEDIUM, net_log_.bound(),
1702 callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581703
rjshaded5ced072015-12-18 19:26:021704 EXPECT_EQ(OK,
1705 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581706
[email protected]24e5bc52013-09-18 15:36:581707 // Ack the request.
Renjie90e808e2019-01-24 07:24:041708 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011709 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1710 IsError(ERR_IO_PENDING));
[email protected]24e5bc52013-09-18 15:36:581711
1712 // Send the response with a body.
[email protected]1e960032013-12-20 19:00:201713 SetResponse("404 OK", "hello world!");
rchfb47f712017-05-21 03:24:001714 size_t response_size = 0;
1715 ProcessPacket(ConstructResponseHeadersPacket(2, kFin, &response_size));
[email protected]24e5bc52013-09-18 15:36:581716
rchfb47f712017-05-21 03:24:001717 EXPECT_EQ(OK, callback_.WaitForResult());
rchb27683c2015-07-29 23:53:501718
[email protected]24e5bc52013-09-18 15:36:581719 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101720
1721 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451722 // headers and payload.
1723 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1724 stream_->GetTotalSentBytes());
rchfb47f712017-05-21 03:24:001725 EXPECT_EQ(static_cast<int64_t>(response_size),
1726 stream_->GetTotalReceivedBytes());
[email protected]24e5bc52013-09-18 15:36:581727}
1728
xunjieli8dff50b2016-07-22 14:19:061729TEST_P(QuicHttpStreamTest, SessionClosedDuringDoLoop) {
1730 SetRequest("POST", "/", DEFAULT_PRIORITY);
1731 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521732 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361733 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
Victor Vasiliev076657c2019-03-12 02:46:431734 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harper23290b82019-05-02 00:02:561735 if (version_.transport_version != quic::QUIC_VERSION_99) {
Renjief49758b2019-01-11 23:32:411736 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1737 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
1738 !kFin, DEFAULT_PRIORITY, 0, &header_stream_offset,
1739 &spdy_request_headers_frame_length, {kUploadData}));
1740 } else {
1741 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1742 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
1743 !kFin, DEFAULT_PRIORITY, 0, &header_stream_offset,
1744 &spdy_request_headers_frame_length, {header, kUploadData}));
1745 }
1746
xunjieli8dff50b2016-07-22 14:19:061747 // Second data write will result in a synchronous failure which will close
1748 // the session.
1749 AddWrite(SYNCHRONOUS, ERR_FAILED);
1750 Initialize();
1751
Jeremy Roman0579ed62017-08-29 15:56:191752 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121753 auto* chunked_upload_stream =
1754 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
xunjieli8dff50b2016-07-22 14:19:061755
1756 request_.method = "POST";
rchcd379012017-04-12 21:53:321757 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121758 request_.upload_data_stream = upload_data_stream_.get();
xunjieli8dff50b2016-07-22 14:19:061759 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201760 TestCompletionCallback().callback(), NetLogWithSource()));
xunjieli8dff50b2016-07-22 14:19:061761
1762 size_t chunk_size = strlen(kUploadData);
rch97827ee2017-05-24 23:49:121763 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
xunjieli8dff50b2016-07-22 14:19:061764 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271765 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli8dff50b2016-07-22 14:19:061766 net_log_.bound(), callback_.callback()));
1767 QuicHttpStream* stream = stream_.get();
1768 DeleteStreamCallback delete_stream_callback(std::move(stream_));
1769 // SendRequest() completes asynchronously after the final chunk is added.
Yixin Wange7ecc472018-03-06 19:00:251770 // Error does not surface yet since packet write is triggered by a packet
1771 // flusher that tries to bundle request body writes.
xunjieli8dff50b2016-07-22 14:19:061772 ASSERT_EQ(ERR_IO_PENDING,
1773 stream->SendRequest(headers_, &response_, callback_.callback()));
rch97827ee2017-05-24 23:49:121774 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
xunjieli8dff50b2016-07-22 14:19:061775 int rv = callback_.WaitForResult();
Yixin Wange7ecc472018-03-06 19:00:251776 EXPECT_EQ(OK, rv);
1777 // Error will be surfaced once an attempt to read the response occurs.
1778 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1779 stream->ReadResponseHeaders(callback_.callback()));
xunjieli8dff50b2016-07-22 14:19:061780}
1781
rtenneti15656ae2016-01-23 03:05:031782TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersComplete) {
1783 SetRequest("POST", "/", DEFAULT_PRIORITY);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521784 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361785 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
rtenneti15656ae2016-01-23 03:05:031786 AddWrite(SYNCHRONOUS, ERR_FAILED);
1787 Initialize();
1788
Jeremy Roman0579ed62017-08-29 15:56:191789 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
Yixin Wange7ecc472018-03-06 19:00:251790 auto* chunked_upload_stream =
1791 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
rtenneti15656ae2016-01-23 03:05:031792
1793 request_.method = "POST";
rchcd379012017-04-12 21:53:321794 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121795 request_.upload_data_stream = upload_data_stream_.get();
rtenneti15656ae2016-01-23 03:05:031796 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201797 TestCompletionCallback().callback(), NetLogWithSource()));
rtenneti15656ae2016-01-23 03:05:031798
xunjieli5fafe142016-03-23 23:32:541799 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271800 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541801 net_log_.bound(), callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:251802 ASSERT_EQ(ERR_IO_PENDING,
rtenneti15656ae2016-01-23 03:05:031803 stream_->SendRequest(headers_, &response_, callback_.callback()));
mmenkeffff3642017-06-15 17:37:241804
Yixin Wange7ecc472018-03-06 19:00:251805 // Error will be surfaced once |upload_data_stream| triggers the next write.
1806 size_t chunk_size = strlen(kUploadData);
1807 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1808 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR, callback_.WaitForResult());
1809
1810 EXPECT_LE(0, stream_->GetTotalSentBytes());
1811 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1812}
1813
1814TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersCompleteReadResponse) {
1815 SetRequest("POST", "/", DEFAULT_PRIORITY);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521816 quic::QuicStreamOffset header_stream_offset = 0;
Yixin Wange7ecc472018-03-06 19:00:251817 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
1818 AddWrite(SYNCHRONOUS, ERR_FAILED);
1819 Initialize();
1820
1821 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
1822 auto* chunked_upload_stream =
1823 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1824
1825 request_.method = "POST";
1826 request_.url = GURL("https://www.example.org/");
1827 request_.upload_data_stream = upload_data_stream_.get();
1828
1829 size_t chunk_size = strlen(kUploadData);
1830 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1831
1832 ASSERT_EQ(OK, request_.upload_data_stream->Init(
1833 TestCompletionCallback().callback(), NetLogWithSource()));
1834
1835 ASSERT_EQ(OK,
1836 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1837 net_log_.bound(), callback_.callback()));
1838 ASSERT_EQ(OK,
1839 stream_->SendRequest(headers_, &response_, callback_.callback()));
1840
1841 // Error will be surfaced once an attempt to read the response occurs.
1842 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1843 stream_->ReadResponseHeaders(callback_.callback()));
1844
mmenkeffff3642017-06-15 17:37:241845 EXPECT_LE(0, stream_->GetTotalSentBytes());
1846 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rtenneti15656ae2016-01-23 03:05:031847}
1848
1849TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBodyComplete) {
1850 SetRequest("POST", "/", DEFAULT_PRIORITY);
1851 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521852 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361853 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:371854 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:331855 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, !kFin,
ckrasicbf2f59c2017-05-04 23:54:361856 DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
1857 &header_stream_offset));
rtenneti15656ae2016-01-23 03:05:031858 AddWrite(SYNCHRONOUS, ERR_FAILED);
1859 Initialize();
1860
Jeremy Roman0579ed62017-08-29 15:56:191861 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121862 auto* chunked_upload_stream =
1863 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
rtenneti15656ae2016-01-23 03:05:031864
1865 request_.method = "POST";
rchcd379012017-04-12 21:53:321866 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121867 request_.upload_data_stream = upload_data_stream_.get();
rtenneti15656ae2016-01-23 03:05:031868 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201869 TestCompletionCallback().callback(), NetLogWithSource()));
rtenneti15656ae2016-01-23 03:05:031870
xunjieli5fafe142016-03-23 23:32:541871 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271872 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541873 net_log_.bound(), callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:251874 ASSERT_EQ(ERR_IO_PENDING,
rtenneti15656ae2016-01-23 03:05:031875 stream_->SendRequest(headers_, &response_, callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:251876
1877 size_t chunk_size = strlen(kUploadData);
1878 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1879 // Error does not surface yet since packet write is triggered by a packet
1880 // flusher that tries to bundle request body writes.
1881 ASSERT_EQ(OK, callback_.WaitForResult());
1882 // Error will be surfaced once an attempt to read the response occurs.
1883 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1884 stream_->ReadResponseHeaders(callback_.callback()));
1885
1886 EXPECT_LE(0, stream_->GetTotalSentBytes());
1887 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1888}
1889
1890TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBundledBodyComplete) {
1891 SetRequest("POST", "/", DEFAULT_PRIORITY);
1892 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521893 quic::QuicStreamOffset header_stream_offset = 0;
Yixin Wange7ecc472018-03-06 19:00:251894 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
Victor Vasiliev076657c2019-03-12 02:46:431895 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harper23290b82019-05-02 00:02:561896 if (version_.transport_version != quic::QUIC_VERSION_99) {
Renjief49758b2019-01-11 23:32:411897 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1898 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
1899 !kFin, DEFAULT_PRIORITY, 0, &header_stream_offset,
1900 &spdy_request_headers_frame_length, {kUploadData}));
1901 } else {
1902 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1903 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
1904 !kFin, DEFAULT_PRIORITY, 0, &header_stream_offset,
1905 &spdy_request_headers_frame_length, {header, kUploadData}));
1906 }
1907
Yixin Wange7ecc472018-03-06 19:00:251908 AddWrite(SYNCHRONOUS, ERR_FAILED);
1909 Initialize();
1910
1911 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
1912 auto* chunked_upload_stream =
1913 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1914
1915 request_.method = "POST";
1916 request_.url = GURL("https://www.example.org/");
1917 request_.upload_data_stream = upload_data_stream_.get();
1918
1919 size_t chunk_size = strlen(kUploadData);
1920 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
1921
1922 ASSERT_EQ(OK, request_.upload_data_stream->Init(
1923 TestCompletionCallback().callback(), NetLogWithSource()));
1924
1925 ASSERT_EQ(OK,
1926 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1927 net_log_.bound(), callback_.callback()));
1928 ASSERT_EQ(ERR_IO_PENDING,
1929 stream_->SendRequest(headers_, &response_, callback_.callback()));
1930
1931 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1932
1933 // Error does not surface yet since packet write is triggered by a packet
1934 // flusher that tries to bundle request body writes.
1935 ASSERT_EQ(OK, callback_.WaitForResult());
1936 // Error will be surfaced once an attempt to read the response occurs.
1937 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1938 stream_->ReadResponseHeaders(callback_.callback()));
1939
1940 EXPECT_LE(0, stream_->GetTotalSentBytes());
1941 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rtenneti15656ae2016-01-23 03:05:031942}
1943
ckrasic3865ee0f2016-02-29 22:04:561944TEST_P(QuicHttpStreamTest, ServerPushGetRequest) {
1945 SetRequest("GET", "/", DEFAULT_PRIORITY);
1946 Initialize();
1947
1948 // Initialize the first stream, for receiving the promise on.
1949 request_.method = "GET";
rchcd379012017-04-12 21:53:321950 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:561951
xunjieli5fafe142016-03-23 23:32:541952 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271953 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541954 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561955
1956 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
1957 // packet, but does it matter?
1958 ReceivePromise(promise_id_);
1959 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
1960
1961 request_.url = GURL(promise_url_);
1962
1963 // Make the second stream that will exercise the first step of the
1964 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:271965 EXPECT_EQ(OK, promised_stream_->InitializeStream(
1966 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
1967 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561968
1969 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:251970 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:561971 size_t spdy_response_headers_frame_length;
1972 ProcessPacket(InnerConstructResponseHeadersPacket(
1973 1, promise_id_, false, &spdy_response_headers_frame_length));
1974
1975 // Receive the promised response body.
1976 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431977 std::string header = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:411978 ProcessPacket(InnerConstructDataPacket(
1979 2, promise_id_, false, kFin, 0, header + kResponseBody, &server_maker_));
ckrasic3865ee0f2016-02-29 22:04:561980
1981 // Now sending a matching request will have successful rendezvous
1982 // with the promised stream.
1983 EXPECT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
1984 callback_.callback()));
1985
1986 EXPECT_EQ(
1987 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
1988 ->id(),
1989 promise_id_);
1990
1991 // The headers will be immediately available.
robpercival214763f2016-07-01 23:27:011992 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
1993 IsOk());
ckrasic3865ee0f2016-02-29 22:04:561994
1995 // As will be the body.
1996 EXPECT_EQ(
1997 static_cast<int>(strlen(kResponseBody)),
1998 promised_stream_->ReadResponseBody(
1999 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2000 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2001 EXPECT_TRUE(AtEof());
2002
2003 EXPECT_EQ(0, stream_->GetTotalSentBytes());
2004 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2005 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2006 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412007 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562008 promised_stream_->GetTotalReceivedBytes());
2009}
2010
2011TEST_P(QuicHttpStreamTest, ServerPushGetRequestSlowResponse) {
2012 SetRequest("GET", "/", DEFAULT_PRIORITY);
2013 Initialize();
2014
2015 // Initialize the first stream, for receiving the promise on.
2016 request_.method = "GET";
rchcd379012017-04-12 21:53:322017 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562018
xunjieli5fafe142016-03-23 23:32:542019 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272020 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542021 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562022
2023 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2024 // packet, but does it matter?
2025 ReceivePromise(promise_id_);
2026 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2027
2028 request_.url = GURL(promise_url_);
2029
2030 // Make the second stream that will exercise the first step of the
2031 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272032 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2033 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2034 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562035
2036 // Now sending a matching request will rendezvous with the promised
2037 // stream, but pending secondary validation.
2038 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2039 headers_, &response_, callback_.callback()));
2040
2041 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252042 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562043 size_t spdy_response_headers_frame_length;
2044 ProcessPacket(InnerConstructResponseHeadersPacket(
2045 1, promise_id_, false, &spdy_response_headers_frame_length));
2046
2047 // Receive the promised response body.
2048 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432049 std::string header = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:412050 ProcessPacket(InnerConstructDataPacket(
2051 2, promise_id_, false, kFin, 0, header + kResponseBody, &server_maker_));
ckrasic3865ee0f2016-02-29 22:04:562052
fdoray92e35a72016-06-10 15:54:552053 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562054
2055 // Rendezvous should have succeeded now, so the promised stream
2056 // should point at our push stream, and we should be able read
2057 // headers and data from it.
robpercival214763f2016-07-01 23:27:012058 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562059
2060 EXPECT_EQ(
2061 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2062 ->id(),
2063 promise_id_);
2064
robpercival214763f2016-07-01 23:27:012065 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2066 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562067
2068 EXPECT_EQ(
2069 static_cast<int>(strlen(kResponseBody)),
2070 promised_stream_->ReadResponseBody(
2071 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2072
2073 // Callback should return
2074 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2075 EXPECT_TRUE(AtEof());
2076
2077 EXPECT_EQ(0, stream_->GetTotalSentBytes());
2078 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2079 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2080 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412081 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562082 promised_stream_->GetTotalReceivedBytes());
2083}
2084
ckrasic2c63f9b2016-08-16 23:54:072085// Verify fix for crbug.com/637349
2086TEST_P(QuicHttpStreamTest, ServerPushCancelHttpStreamBeforeResponse) {
2087 SetRequest("GET", "/", DEFAULT_PRIORITY);
2088 Initialize();
2089
2090 // Initialize the first stream, for receiving the promise on.
2091 request_.method = "GET";
rchcd379012017-04-12 21:53:322092 request_.url = GURL("https://www.example.org/");
ckrasic2c63f9b2016-08-16 23:54:072093
2094 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272095 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
ckrasic2c63f9b2016-08-16 23:54:072096 net_log_.bound(), callback_.callback()));
2097
2098 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2099 // packet, but does it matter?
2100 ReceivePromise(promise_id_);
2101 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2102
2103 request_.url = GURL(promise_url_);
2104
2105 // Make the second stream that will exercise the first step of the
2106 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272107 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2108 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2109 callback_.callback()));
ckrasic2c63f9b2016-08-16 23:54:072110
2111 // Now sending a matching request will rendezvous with the promised
2112 // stream, but pending secondary validation.
2113 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2114 headers_, &response_, callback_.callback()));
2115
2116 base::RunLoop().RunUntilIdle();
2117
2118 // Cause of FinalValidation() crash as per bug.
2119 promised_stream_.reset();
2120
2121 // Receive the promised response headers.
2122 response_headers_ = promised_response_.Clone();
2123 size_t spdy_response_headers_frame_length;
2124 ProcessPacket(InnerConstructResponseHeadersPacket(
2125 1, promise_id_, false, &spdy_response_headers_frame_length));
2126}
2127
ckrasic3865ee0f2016-02-29 22:04:562128TEST_P(QuicHttpStreamTest, ServerPushCrossOriginOK) {
2129 SetRequest("GET", "/", DEFAULT_PRIORITY);
2130 Initialize();
2131
2132 // Initialize the first stream, for receiving the promise on.
2133 request_.method = "GET";
rchcd379012017-04-12 21:53:322134 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562135
xunjieli5fafe142016-03-23 23:32:542136 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272137 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542138 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562139
2140 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2141 // packet, but does it matter?
2142
2143 push_promise_[":authority"] = "mail.example.org";
Ryan Hamilton8d9ee76e2018-05-29 23:52:522144 promise_url_ = quic::SpdyUtils::GetPromisedUrlFromHeaders(push_promise_);
ckrasic3865ee0f2016-02-29 22:04:562145
2146 ReceivePromise(promise_id_);
2147 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2148
2149 request_.url = GURL(promise_url_);
2150
2151 // Make the second stream that will exercise the first step of the
2152 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272153 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2154 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2155 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562156
2157 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252158 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562159 size_t spdy_response_headers_frame_length;
2160 ProcessPacket(InnerConstructResponseHeadersPacket(
2161 1, promise_id_, false, &spdy_response_headers_frame_length));
2162
2163 // Receive the promised response body.
2164 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432165 std::string header = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:412166 ProcessPacket(InnerConstructDataPacket(
2167 2, promise_id_, false, kFin, 0, header + kResponseBody, &server_maker_));
ckrasic3865ee0f2016-02-29 22:04:562168
2169 // Now sending a matching request will have successful rendezvous
2170 // with the promised stream.
2171 EXPECT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
2172 callback_.callback()));
2173
2174 EXPECT_EQ(
2175 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2176 ->id(),
2177 promise_id_);
2178
2179 // The headers will be immediately available.
robpercival214763f2016-07-01 23:27:012180 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2181 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562182
2183 // As will be the body.
2184 EXPECT_EQ(
2185 static_cast<int>(strlen(kResponseBody)),
2186 promised_stream_->ReadResponseBody(
2187 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2188 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2189 EXPECT_TRUE(AtEof());
2190
2191 EXPECT_EQ(0, stream_->GetTotalSentBytes());
2192 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2193 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2194 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412195 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562196 promised_stream_->GetTotalReceivedBytes());
2197}
2198
2199TEST_P(QuicHttpStreamTest, ServerPushCrossOriginFail) {
2200 SetRequest("GET", "/", DEFAULT_PRIORITY);
2201 Initialize();
2202
2203 // Initialize the first stream, for receiving the promise on.
2204 request_.method = "GET";
rchcd379012017-04-12 21:53:322205 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562206
xunjieli5fafe142016-03-23 23:32:542207 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272208 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542209 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562210
2211 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2212 // packet, but does it matter?
2213 push_promise_[":authority"] = "www.notexample.org";
Ryan Hamilton8d9ee76e2018-05-29 23:52:522214 promise_url_ = quic::SpdyUtils::GetPromisedUrlFromHeaders(push_promise_);
ckrasic3865ee0f2016-02-29 22:04:562215
2216 ReceivePromise(promise_id_);
2217 // The promise will have been rejected because the cert doesn't
2218 // match.
2219 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
2220}
2221
2222TEST_P(QuicHttpStreamTest, ServerPushVaryCheckOK) {
2223 SetRequest("GET", "/", DEFAULT_PRIORITY);
2224 Initialize();
2225
2226 // Initialize the first stream, for receiving the promise on.
2227 request_.method = "GET";
rchcd379012017-04-12 21:53:322228 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562229
xunjieli5fafe142016-03-23 23:32:542230 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272231 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542232 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562233
2234 push_promise_["accept-encoding"] = "gzip";
ckrasic3865ee0f2016-02-29 22:04:562235
2236 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2237 // packet, but does it matter?
2238 ReceivePromise(promise_id_);
2239 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2240
2241 request_.url = GURL(promise_url_);
2242
2243 // Make the second stream that will exercise the first step of the
2244 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272245 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2246 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2247 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562248
2249 headers_.SetHeader("accept-encoding", "gzip");
2250
2251 // Now sending a matching request will rendezvous with the promised
2252 // stream, but pending secondary validation.
2253 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2254 headers_, &response_, callback_.callback()));
2255
2256 // Receive the promised response headers.
2257 promised_response_["vary"] = "accept-encoding";
bnc94893a72016-06-30 13:45:252258 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562259 size_t spdy_response_headers_frame_length;
2260 ProcessPacket(InnerConstructResponseHeadersPacket(
2261 1, promise_id_, false, &spdy_response_headers_frame_length));
2262
2263 // Receive the promised response body.
2264 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432265 std::string header = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:412266 ProcessPacket(InnerConstructDataPacket(
2267 2, promise_id_, false, kFin, 0, header + kResponseBody, &server_maker_));
ckrasic3865ee0f2016-02-29 22:04:562268
fdoray92e35a72016-06-10 15:54:552269 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562270
2271 // Rendezvous should have succeeded now, so the promised stream
2272 // should point at our push stream, and we should be able read
2273 // headers and data from it.
robpercival214763f2016-07-01 23:27:012274 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562275
2276 EXPECT_EQ(
2277 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2278 ->id(),
2279 promise_id_);
2280
robpercival214763f2016-07-01 23:27:012281 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2282 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562283
2284 EXPECT_EQ(
2285 static_cast<int>(strlen(kResponseBody)),
2286 promised_stream_->ReadResponseBody(
2287 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2288
2289 // Callback should return
2290 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2291 EXPECT_TRUE(AtEof());
2292
2293 EXPECT_EQ(0, stream_->GetTotalSentBytes());
2294 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2295 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2296 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412297 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562298 promised_stream_->GetTotalReceivedBytes());
2299}
2300
2301TEST_P(QuicHttpStreamTest, ServerPushVaryCheckFail) {
2302 SetRequest("GET", "/", DEFAULT_PRIORITY);
2303 request_headers_[":scheme"] = "https";
2304 request_headers_[":path"] = "/bar";
2305 request_headers_["accept-encoding"] = "sdch";
2306
2307 size_t spdy_request_header_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:522308 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:362309 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
Yixin Wangb470bc882018-02-15 18:43:572310
Fan Yangac867502019-01-28 21:10:232311 uint64_t client_packet_number = 2;
Yixin Wangb470bc882018-02-15 18:43:572312 if (client_headers_include_h2_stream_dependency_ &&
Nick Harper23290b82019-05-02 00:02:562313 version_.transport_version >= quic::QUIC_VERSION_43) {
Yixin Wangb470bc882018-02-15 18:43:572314 AddWrite(ConstructClientPriorityPacket(
2315 client_packet_number++, kIncludeVersion, promise_id_, 0,
2316 DEFAULT_PRIORITY, &header_stream_offset));
2317 }
Michael Warresabba8b7d2018-07-20 22:50:272318 AddWrite(ConstructClientRstStreamVaryMismatchAndRequestHeadersPacket(
Victor Vasiliev4a6798e2019-03-06 02:26:092319 client_packet_number++,
Nick Harper23290b82019-05-02 00:02:562320 stream_id_ + quic::QuicUtils::StreamIdDelta(version_.transport_version),
2321 !kIncludeVersion, kFin, DEFAULT_PRIORITY, promise_id_,
2322 &spdy_request_header_frame_length, &header_stream_offset));
Renjie90e808e2019-01-24 07:24:042323 AddWrite(ConstructClientAckPacket(client_packet_number++, 3, 1, 2));
Yixin Wangb470bc882018-02-15 18:43:572324 AddWrite(ConstructClientRstStreamCancelledPacket(client_packet_number++));
2325
ckrasic3865ee0f2016-02-29 22:04:562326 Initialize();
2327
2328 // Initialize the first stream, for receiving the promise on.
2329 request_.method = "GET";
rchcd379012017-04-12 21:53:322330 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562331
xunjieli5fafe142016-03-23 23:32:542332 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272333 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542334 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562335
2336 push_promise_["accept-encoding"] = "gzip";
ckrasic3865ee0f2016-02-29 22:04:562337
2338 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2339 // packet, but does it matter?
2340 ReceivePromise(promise_id_);
2341 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2342
2343 request_.url = GURL(promise_url_);
2344
2345 // Make the second stream that will exercise the first step of the
2346 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272347 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2348 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2349 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562350
2351 headers_.SetHeader("accept-encoding", "sdch");
2352
2353 // Now sending a matching request will rendezvous with the promised
2354 // stream, but pending secondary validation.
2355 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2356 headers_, &response_, callback_.callback()));
2357
2358 // Receive the promised response headers.
2359 promised_response_["vary"] = "accept-encoding";
bnc94893a72016-06-30 13:45:252360 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562361 size_t spdy_response_headers_frame_length;
2362 ProcessPacket(InnerConstructResponseHeadersPacket(
2363 1, promise_id_, false, &spdy_response_headers_frame_length));
2364
fdoray92e35a72016-06-10 15:54:552365 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562366
2367 // Rendezvous should have failed due to vary mismatch, so the
2368 // promised stream should have been aborted, and instead we have a
2369 // new, regular client initiated stream.
robpercival214763f2016-07-01 23:27:012370 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562371
2372 // Not a server-initiated stream.
2373 EXPECT_NE(
2374 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2375 ->id(),
2376 promise_id_);
2377
2378 // Instead, a new client-initiated stream.
2379 EXPECT_EQ(
2380 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2381 ->id(),
Nick Harper23290b82019-05-02 00:02:562382 stream_id_ + quic::QuicUtils::StreamIdDelta(version_.transport_version));
ckrasic3865ee0f2016-02-29 22:04:562383
2384 // After rendezvous failure, the push stream has been cancelled.
2385 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
2386
2387 // The rest of the test verifies that the retried as
2388 // client-initiated version of |promised_stream_| works as intended.
2389
2390 // Ack the request.
Renjie90e808e2019-01-24 07:24:042391 ProcessPacket(ConstructServerAckPacket(2, 1, 1, 1));
ckrasic3865ee0f2016-02-29 22:04:562392
bnc614a92d32016-04-04 13:56:072393 SetResponse("404 Not Found", string());
ckrasic3865ee0f2016-02-29 22:04:562394 size_t spdy_response_header_frame_length;
2395 ProcessPacket(InnerConstructResponseHeadersPacket(
Nick Harper23290b82019-05-02 00:02:562396 3,
2397 stream_id_ + quic::QuicUtils::StreamIdDelta(version_.transport_version),
2398 kFin, &spdy_response_header_frame_length));
ckrasic3865ee0f2016-02-29 22:04:562399
fdoray92e35a72016-06-10 15:54:552400 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562401
robpercival214763f2016-07-01 23:27:012402 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2403 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562404 ASSERT_TRUE(response_.headers.get());
2405 EXPECT_EQ(404, response_.headers->response_code());
2406 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
2407 EXPECT_FALSE(response_.response_time.is_null());
2408 EXPECT_FALSE(response_.request_time.is_null());
2409
2410 // There is no body, so this should return immediately.
2411 EXPECT_EQ(
2412 0, promised_stream_->ReadResponseBody(
2413 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2414 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2415
2416 stream_->Close(true);
2417
2418 EXPECT_TRUE(AtEof());
2419
2420 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
2421 // headers and payload.
2422 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
2423 promised_stream_->GetTotalSentBytes());
2424 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length),
2425 promised_stream_->GetTotalReceivedBytes());
2426}
2427
maksim.sisov84e20c92016-06-23 08:49:342428TEST_P(QuicHttpStreamTest, DataReadErrorSynchronous) {
2429 SetRequest("POST", "/", DEFAULT_PRIORITY);
2430 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:522431 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:362432 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
Yixin Wange7ecc472018-03-06 19:00:252433 AddWrite(ConstructRequestAndRstPacket(
Fan Yang32c5a112018-12-10 20:06:332434 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, !kFin,
Yixin Wange7ecc472018-03-06 19:00:252435 DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
Ryan Hamilton8d9ee76e2018-05-29 23:52:522436 &header_stream_offset, quic::QUIC_ERROR_PROCESSING_STREAM, 0));
maksim.sisov84e20c92016-06-23 08:49:342437
2438 Initialize();
2439
Jeremy Roman0579ed62017-08-29 15:56:192440 upload_data_stream_ = std::make_unique<ReadErrorUploadDataStream>(
maksim.sisov84e20c92016-06-23 08:49:342441 ReadErrorUploadDataStream::FailureMode::SYNC);
2442 request_.method = "POST";
rchcd379012017-04-12 21:53:322443 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122444 request_.upload_data_stream = upload_data_stream_.get();
maksim.sisov84e20c92016-06-23 08:49:342445 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202446 TestCompletionCallback().callback(), NetLogWithSource()));
maksim.sisov84e20c92016-06-23 08:49:342447
2448 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272449 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
maksim.sisov84e20c92016-06-23 08:49:342450 net_log_.bound(), callback_.callback()));
2451
2452 int result = stream_->SendRequest(headers_, &response_, callback_.callback());
robpercival214763f2016-07-01 23:27:012453 EXPECT_THAT(result, IsError(ERR_FAILED));
maksim.sisov84e20c92016-06-23 08:49:342454
2455 EXPECT_TRUE(AtEof());
2456
2457 // QuicHttpStream::GetTotalSent/ReceivedBytes includes only headers.
2458 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
2459 stream_->GetTotalSentBytes());
2460 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2461}
2462
2463TEST_P(QuicHttpStreamTest, DataReadErrorAsynchronous) {
2464 SetRequest("POST", "/", DEFAULT_PRIORITY);
2465 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:522466 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:362467 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:372468 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:332469 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, !kFin,
ckrasicbf2f59c2017-05-04 23:54:362470 DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
2471 &header_stream_offset));
fayang3bcb8b502016-12-07 21:44:372472 AddWrite(ConstructClientRstStreamErrorPacket(3, !kIncludeVersion));
maksim.sisov84e20c92016-06-23 08:49:342473
2474 Initialize();
2475
Jeremy Roman0579ed62017-08-29 15:56:192476 upload_data_stream_ = std::make_unique<ReadErrorUploadDataStream>(
maksim.sisov84e20c92016-06-23 08:49:342477 ReadErrorUploadDataStream::FailureMode::ASYNC);
2478 request_.method = "POST";
rchcd379012017-04-12 21:53:322479 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122480 request_.upload_data_stream = upload_data_stream_.get();
maksim.sisov84e20c92016-06-23 08:49:342481 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202482 TestCompletionCallback().callback(), NetLogWithSource()));
maksim.sisov84e20c92016-06-23 08:49:342483
2484 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272485 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
maksim.sisov84e20c92016-06-23 08:49:342486 net_log_.bound(), callback_.callback()));
2487
2488 int result = stream_->SendRequest(headers_, &response_, callback_.callback());
2489
Renjie90e808e2019-01-24 07:24:042490 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
maksim.sisov84e20c92016-06-23 08:49:342491 SetResponse("200 OK", string());
2492
robpercival214763f2016-07-01 23:27:012493 EXPECT_THAT(result, IsError(ERR_IO_PENDING));
2494 EXPECT_THAT(callback_.GetResult(result), IsError(ERR_FAILED));
maksim.sisov84e20c92016-06-23 08:49:342495
2496 EXPECT_TRUE(AtEof());
2497
2498 // QuicHttpStream::GetTotalSent/ReceivedBytes includes only headers.
2499 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
2500 stream_->GetTotalSentBytes());
2501 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2502}
2503
[email protected]f702d572012-12-04 15:56:202504} // namespace test
[email protected]f702d572012-12-04 15:56:202505} // namespace net