blob: 0c0ba6ca02cdb55a3649dd9281d96a9abf0181fd [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"
Ryan Hamiltona1d1f4a2019-06-26 14:43:0435#include "net/quic/platform/impl/quic_test_impl.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0836#include "net/quic/quic_chromium_alarm_factory.h"
37#include "net/quic/quic_chromium_connection_helper.h"
38#include "net/quic/quic_chromium_packet_reader.h"
39#include "net/quic/quic_chromium_packet_writer.h"
40#include "net/quic/quic_http_utils.h"
41#include "net/quic/quic_server_info.h"
42#include "net/quic/quic_stream_factory.h"
43#include "net/quic/quic_test_packet_maker.h"
Ryan Hamilton0d65a8c2019-06-07 00:46:0244#include "net/quic/quic_test_packet_printer.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0845#include "net/quic/test_task_runner.h"
tbansalca83c002016-04-28 20:56:2846#include "net/socket/socket_performance_watcher.h"
[email protected]f702d572012-12-04 15:56:2047#include "net/socket/socket_test_util.h"
Bence Béky94658bf2018-05-11 19:22:5848#include "net/spdy/spdy_http_utils.h"
rch03b7a202016-02-05 00:54:2049#include "net/test/cert_test_util.h"
robpercival214763f2016-07-01 23:27:0150#include "net/test/gtest_util.h"
rsleevia69c79a2016-06-22 03:28:4351#include "net/test/test_data_directory.h"
Bence Béky98447b12018-05-08 03:14:0152#include "net/test/test_with_scoped_task_environment.h"
Victor Vasiliev6bb59d22019-03-08 21:34:5153#include "net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.h"
54#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
55#include "net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h"
56#include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
David Schinazi3f7465c2019-07-12 01:57:0557#include "net/third_party/quiche/src/quic/core/http/spdy_server_push_utils.h"
Victor Vasiliev6bb59d22019-03-08 21:34:5158#include "net/third_party/quiche/src/quic/core/quic_connection.h"
59#include "net/third_party/quiche/src/quic/core/quic_utils.h"
60#include "net/third_party/quiche/src/quic/core/quic_write_blocked_list.h"
Ryan Hamiltona1d1f4a2019-06-26 14:43:0461#include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h"
62#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
Victor Vasiliev6bb59d22019-03-08 21:34:5163#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
64#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
65#include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
66#include "net/third_party/quiche/src/quic/test_tools/mock_random.h"
67#include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
68#include "net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h"
69#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
Victor Vasiliev27cc7712019-01-24 11:50:1470#include "net/third_party/quiche/src/spdy/core/spdy_frame_builder.h"
71#include "net/third_party/quiche/src/spdy/core/spdy_framer.h"
72#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
Ramin Halavati683bcaa92018-02-14 08:42:3973#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
[email protected]f702d572012-12-04 15:56:2074#include "testing/gmock/include/gmock/gmock.h"
75#include "testing/gtest/include/gtest/gtest.h"
76
bnc614a92d32016-04-04 13:56:0777using std::string;
[email protected]f702d572012-12-04 15:56:2078using testing::_;
[email protected]06ff5152013-08-29 01:03:0579using testing::AnyNumber;
80using testing::Return;
[email protected]f702d572012-12-04 15:56:2081
82namespace net {
[email protected]f702d572012-12-04 15:56:2083namespace test {
[email protected]f702d572012-12-04 15:56:2084namespace {
85
[email protected]16ba7742014-08-22 00:57:2586const char kUploadData[] = "Really nifty data!";
rch9ae5b3b2016-02-11 00:36:2987const char kDefaultServerHostName[] = "www.example.org";
rchcd379012017-04-12 21:53:3288const uint16_t kDefaultServerPort = 443;
[email protected]f702d572012-12-04 15:56:2089
Ryan Hamilton8d9ee76e2018-05-29 23:52:5290class TestQuicConnection : public quic::QuicConnection {
[email protected]f702d572012-12-04 15:56:2091 public:
Ryan Hamilton8d9ee76e2018-05-29 23:52:5292 TestQuicConnection(const quic::ParsedQuicVersionVector& versions,
93 quic::QuicConnectionId connection_id,
[email protected]f702d572012-12-04 15:56:2094 IPEndPoint address,
rch12fef552016-01-15 16:26:3195 QuicChromiumConnectionHelper* helper,
rch16c74d1d2016-04-22 06:14:0796 QuicChromiumAlarmFactory* alarm_factory,
Ryan Hamilton8d9ee76e2018-05-29 23:52:5297 quic::QuicPacketWriter* writer)
Victor Vasiliev4f6fb892019-05-31 16:58:3198 : quic::QuicConnection(connection_id,
99 ToQuicSocketAddress(address),
100 helper,
101 alarm_factory,
102 writer,
103 true /* owns_writer */,
104 quic::Perspective::IS_CLIENT,
105 versions) {}
[email protected]f702d572012-12-04 15:56:20106
Ryan Hamilton8d9ee76e2018-05-29 23:52:52107 void SetSendAlgorithm(quic::SendAlgorithmInterface* send_algorithm) {
108 quic::test::QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
[email protected]f702d572012-12-04 15:56:20109 }
110};
111
maksim.sisov84e20c92016-06-23 08:49:34112// UploadDataStream that always returns errors on data read.
113class ReadErrorUploadDataStream : public UploadDataStream {
114 public:
115 enum class FailureMode { SYNC, ASYNC };
116
117 explicit ReadErrorUploadDataStream(FailureMode mode)
Jeremy Romand54000b22019-07-08 18:40:16118 : UploadDataStream(true, 0), async_(mode) {}
maksim.sisov84e20c92016-06-23 08:49:34119 ~ReadErrorUploadDataStream() override {}
120
121 private:
122 void CompleteRead() { UploadDataStream::OnReadCompleted(ERR_FAILED); }
123
124 // UploadDataStream implementation:
tfarina42834112016-09-22 13:38:20125 int InitInternal(const NetLogWithSource& net_log) override { return OK; }
maksim.sisov84e20c92016-06-23 08:49:34126
127 int ReadInternal(IOBuffer* buf, int buf_len) override {
128 if (async_ == FailureMode::ASYNC) {
129 base::ThreadTaskRunnerHandle::Get()->PostTask(
kylecharf4fe5172019-02-15 18:53:49130 FROM_HERE, base::BindOnce(&ReadErrorUploadDataStream::CompleteRead,
131 weak_factory_.GetWeakPtr()));
maksim.sisov84e20c92016-06-23 08:49:34132 return ERR_IO_PENDING;
133 }
134 return ERR_FAILED;
135 }
136
137 void ResetInternal() override {}
138
139 const FailureMode async_;
140
Jeremy Romand54000b22019-07-08 18:40:16141 base::WeakPtrFactory<ReadErrorUploadDataStream> weak_factory_{this};
maksim.sisov84e20c92016-06-23 08:49:34142
143 DISALLOW_COPY_AND_ASSIGN(ReadErrorUploadDataStream);
144};
145
Bence Béky8ddc2492018-06-13 01:02:04146// A helper class that will delete |stream| when the callback is invoked.
xunjieli8dff50b2016-07-22 14:19:06147class DeleteStreamCallback : public TestCompletionCallbackBase {
148 public:
Bence Béky8ddc2492018-06-13 01:02:04149 explicit DeleteStreamCallback(std::unique_ptr<QuicHttpStream> stream)
150 : stream_(std::move(stream)) {}
xunjieli8dff50b2016-07-22 14:19:06151
Bence Béky8ddc2492018-06-13 01:02:04152 CompletionOnceCallback callback() {
153 return base::BindOnce(&DeleteStreamCallback::DeleteStream,
154 base::Unretained(this));
155 }
xunjieli8dff50b2016-07-22 14:19:06156
157 private:
158 void DeleteStream(int result) {
159 stream_.reset();
160 SetResult(result);
161 }
162
163 std::unique_ptr<QuicHttpStream> stream_;
xunjieli8dff50b2016-07-22 14:19:06164};
165
[email protected]f702d572012-12-04 15:56:20166} // namespace
167
[email protected]24e5bc52013-09-18 15:36:58168class QuicHttpStreamPeer {
169 public:
rch08e198572017-05-09 16:56:55170 static QuicChromiumClientStream::Handle* GetQuicChromiumClientStream(
[email protected]24e5bc52013-09-18 15:36:58171 QuicHttpStream* stream) {
rch08e198572017-05-09 16:56:55172 return stream->stream_.get();
[email protected]24e5bc52013-09-18 15:36:58173 }
174};
175
Ryan Hamilton8d9ee76e2018-05-29 23:52:52176class QuicHttpStreamTest : public ::testing::TestWithParam<
Nick Harper23290b82019-05-02 00:02:56177 std::tuple<quic::ParsedQuicVersion, bool>>,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52178 public WithScopedTaskEnvironment {
rchfb47f712017-05-21 03:24:00179 public:
180 void CloseStream(QuicHttpStream* stream, int /*rv*/) { stream->Close(false); }
181
[email protected]f702d572012-12-04 15:56:20182 protected:
[email protected]1e960032013-12-20 19:00:20183 static const bool kFin = true;
184 static const bool kIncludeVersion = true;
185 static const bool kIncludeCongestionFeedback = true;
186
[email protected]f702d572012-12-04 15:56:20187 // Holds a packet to be written to the wire, and the IO mode that should
188 // be used by the mock socket when performing the write.
189 struct PacketToWrite {
Ryan Hamilton8d9ee76e2018-05-29 23:52:52190 PacketToWrite(IoMode mode, quic::QuicReceivedPacket* packet)
rjshaded5ced072015-12-18 19:26:02191 : mode(mode), packet(packet) {}
rtenneti15656ae2016-01-23 03:05:03192 PacketToWrite(IoMode mode, int rv) : mode(mode), packet(nullptr), rv(rv) {}
[email protected]f702d572012-12-04 15:56:20193 IoMode mode;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52194 quic::QuicReceivedPacket* packet;
rtenneti15656ae2016-01-23 03:05:03195 int rv;
[email protected]f702d572012-12-04 15:56:20196 };
197
198 QuicHttpStreamTest()
Yixin Wang079ad542018-01-11 04:06:05199 : version_(std::get<0>(GetParam())),
200 client_headers_include_h2_stream_dependency_(std::get<1>(GetParam())),
Nick Harpera598fc5f2019-06-21 08:46:50201 crypto_config_(
202 quic::test::crypto_test_utils::ProofVerifierForTesting()),
Victor Costan9c7302b2018-08-27 16:39:44203 read_buffer_(base::MakeRefCounted<IOBufferWithSize>(4096)),
Fan Yang32c5a112018-12-10 20:06:33204 promise_id_(GetNthServerInitiatedUnidirectionalStreamId(0)),
205 stream_id_(GetNthClientInitiatedBidirectionalStreamId(0)),
David Schinazic8281052019-01-24 06:14:17206 connection_id_(quic::test::TestConnectionId(2)),
Yixin Wang079ad542018-01-11 04:06:05207 client_maker_(version_,
alyssar2adf3ac2016-05-03 17:12:58208 connection_id_,
209 &clock_,
210 kDefaultServerHostName,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52211 quic::Perspective::IS_CLIENT,
Yixin Wang079ad542018-01-11 04:06:05212 client_headers_include_h2_stream_dependency_),
213 server_maker_(version_,
zhongyi5dbfdd42017-06-20 05:22:15214 connection_id_,
alyssar2adf3ac2016-05-03 17:12:58215 &clock_,
216 kDefaultServerHostName,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52217 quic::Perspective::IS_SERVER,
Yixin Wang079ad542018-01-11 04:06:05218 false),
ckrasic3865ee0f2016-02-29 22:04:56219 random_generator_(0),
Ryan Hamilton0d65a8c2019-06-07 00:46:02220 printer_(version_) {
Ryan Hamiltona1d1f4a2019-06-26 14:43:04221 SetQuicFlag(FLAGS_quic_supports_tls_handshake, true);
martijn21968ea2016-02-24 18:46:20222 IPAddress ip(192, 0, 2, 33);
[email protected]f702d572012-12-04 15:56:20223 peer_addr_ = IPEndPoint(ip, 443);
224 self_addr_ = IPEndPoint(ip, 8435);
Ryan Hamilton8d9ee76e2018-05-29 23:52:52225 clock_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(20));
Ramin Halavati683bcaa92018-02-14 08:42:39226 request_.traffic_annotation =
227 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f702d572012-12-04 15:56:20228 }
229
230 ~QuicHttpStreamTest() {
Renjieba55fae2018-09-20 03:05:16231 session_->CloseSessionOnError(ERR_ABORTED, quic::QUIC_INTERNAL_ERROR,
232 quic::ConnectionCloseBehavior::SILENT_CLOSE);
[email protected]f702d572012-12-04 15:56:20233 for (size_t i = 0; i < writes_.size(); i++) {
234 delete writes_[i].packet;
235 }
236 }
237
238 // Adds a packet to the list of expected writes.
Ryan Hamilton8d9ee76e2018-05-29 23:52:52239 void AddWrite(std::unique_ptr<quic::QuicReceivedPacket> packet) {
[email protected]1e960032013-12-20 19:00:20240 writes_.push_back(PacketToWrite(SYNCHRONOUS, packet.release()));
[email protected]f702d572012-12-04 15:56:20241 }
242
rtenneti15656ae2016-01-23 03:05:03243 void AddWrite(IoMode mode, int rv) {
244 writes_.push_back(PacketToWrite(mode, rv));
245 }
246
[email protected]f702d572012-12-04 15:56:20247 // Returns the packet to be written at position |pos|.
Ryan Hamilton8d9ee76e2018-05-29 23:52:52248 quic::QuicReceivedPacket* GetWrite(size_t pos) { return writes_[pos].packet; }
[email protected]f702d572012-12-04 15:56:20249
250 bool AtEof() {
rch37de576c2015-05-17 20:28:17251 return socket_data_->AllReadDataConsumed() &&
252 socket_data_->AllWriteDataConsumed();
[email protected]f702d572012-12-04 15:56:20253 }
254
Ryan Hamilton8d9ee76e2018-05-29 23:52:52255 void ProcessPacket(std::unique_ptr<quic::QuicReceivedPacket> packet) {
Victor Vasiliev4f6fb892019-05-31 16:58:31256 connection_->ProcessUdpPacket(ToQuicSocketAddress(self_addr_),
257 ToQuicSocketAddress(peer_addr_), *packet);
[email protected]f702d572012-12-04 15:56:20258 }
259
260 // Configures the test fixture to use the list of expected writes.
261 void Initialize() {
262 mock_writes_.reset(new MockWrite[writes_.size()]);
263 for (size_t i = 0; i < writes_.size(); i++) {
rtenneti15656ae2016-01-23 03:05:03264 if (writes_[i].packet == nullptr) {
265 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].rv, i);
266 } else {
267 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].packet->data(),
268 writes_[i].packet->length());
269 }
bnc614a92d32016-04-04 13:56:07270 }
[email protected]f702d572012-12-04 15:56:20271
rtennetibe635732014-10-02 22:51:42272 socket_data_.reset(new StaticSocketDataProvider(
Ryan Sleevib8d7ea02018-05-07 20:01:01273 base::span<MockRead>(),
274 base::make_span(mock_writes_.get(), writes_.size())));
Ryan Hamilton0d65a8c2019-06-07 00:46:02275 socket_data_->set_printer(&printer_);
[email protected]f702d572012-12-04 15:56:20276
danakjad1777e2016-04-16 00:56:42277 std::unique_ptr<MockUDPClientSocket> socket(new MockUDPClientSocket(
xunjielib53b38c2016-03-24 15:54:36278 socket_data_.get(), net_log_.bound().net_log()));
[email protected]e13201d82012-12-12 05:00:32279 socket->Connect(peer_addr_);
[email protected]f702d572012-12-04 15:56:20280 runner_ = new TestTaskRunner(&clock_);
Ryan Hamilton8d9ee76e2018-05-29 23:52:52281 send_algorithm_ = new quic::test::MockSendAlgorithm();
rch7dd15702015-07-01 18:57:57282 EXPECT_CALL(*send_algorithm_, InRecovery()).WillRepeatedly(Return(false));
283 EXPECT_CALL(*send_algorithm_, InSlowStart()).WillRepeatedly(Return(false));
rjshaded5ced072015-12-18 19:26:02284 EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
Dan Zhangf11470172017-09-18 22:02:09285 .Times(testing::AtLeast(1));
Ryan Hamiltona1d1f4a2019-06-26 14:43:04286 EXPECT_CALL(*send_algorithm_, OnCongestionEvent(_, _, _, _, _))
287 .Times(AnyNumber());
rtenneti44f4a2e2015-08-07 14:00:07288 EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
Zhongyi Shica576df2019-04-12 17:43:40289 .WillRepeatedly(Return(quic::kMaxOutgoingPacketSize));
jokulik0e0a00c32016-06-13 21:51:58290 EXPECT_CALL(*send_algorithm_, PacingRate(_))
Ryan Hamilton8d9ee76e2018-05-29 23:52:52291 .WillRepeatedly(Return(quic::QuicBandwidth::Zero()));
Michael Warres74ee3ce2017-10-09 15:26:37292 EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true));
rtenneti44f4a2e2015-08-07 14:00:07293 EXPECT_CALL(*send_algorithm_, BandwidthEstimate())
Ryan Hamilton8d9ee76e2018-05-29 23:52:52294 .WillRepeatedly(Return(quic::QuicBandwidth::Zero()));
rch1e543ec2015-03-29 07:04:40295 EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(AnyNumber());
rch08cae032017-03-29 00:59:15296 EXPECT_CALL(*send_algorithm_, OnApplicationLimited(_)).Times(AnyNumber());
rch0d5bcf62017-05-24 22:48:45297 EXPECT_CALL(*send_algorithm_, GetCongestionControlType())
298 .Times(AnyNumber());
rch16c74d1d2016-04-22 06:14:07299 helper_.reset(
300 new QuicChromiumConnectionHelper(&clock_, &random_generator_));
301 alarm_factory_.reset(new QuicChromiumAlarmFactory(runner_.get(), &clock_));
302
Michael Warres74ee3ce2017-10-09 15:26:37303 connection_ = new TestQuicConnection(
Nick Harper23290b82019-05-02 00:02:56304 quic::test::SupportedVersions(version_), connection_id_, peer_addr_,
305 helper_.get(), alarm_factory_.get(),
Ryan Hamilton9edcf1a2017-11-22 05:55:17306 new QuicChromiumPacketWriter(
307 socket.get(), base::ThreadTaskRunnerHandle::Get().get()));
[email protected]f702d572012-12-04 15:56:20308 connection_->set_visitor(&visitor_);
[email protected]fee17f72013-02-03 07:47:41309 connection_->SetSendAlgorithm(send_algorithm_);
rch03b7a202016-02-05 00:54:20310
311 // Load a certificate that is valid for *.example.org
312 scoped_refptr<X509Certificate> test_cert(
313 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
314 EXPECT_TRUE(test_cert.get());
315
316 verify_details_.cert_verify_result.verified_cert = test_cert;
317 verify_details_.cert_verify_result.is_issued_by_known_root = true;
318 crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details_);
319
xunjieli84adaab2016-09-20 01:12:28320 base::TimeTicks dns_end = base::TimeTicks::Now();
321 base::TimeTicks dns_start = dns_end - base::TimeDelta::FromMilliseconds(1);
ckrasic4f9d88d2015-07-22 22:23:16322 session_.reset(new QuicChromiumClientSession(
xunjielib53b38c2016-03-24 15:54:36323 connection_, std::move(socket),
rtenneti1cd3b162015-09-29 02:58:28324 /*stream_factory=*/nullptr, &crypto_client_stream_factory_, &clock_,
Nick Harper89bc7212018-07-31 19:07:57325 &transport_security_state_, /*ssl_config_service=*/nullptr,
danakjad1777e2016-04-16 00:56:42326 base::WrapUnique(static_cast<QuicServerInfo*>(nullptr)),
Paul Jensen8e3c5d32018-02-19 17:06:33327 QuicSessionKey(kDefaultServerHostName, kDefaultServerPort,
328 PRIVACY_MODE_DISABLED, SocketTag()),
Zhongyi Shi757fcce2018-06-27 05:41:27329 /*require_confirmation=*/false, /*migrate_session_early_v2=*/false,
330 /*migrate_session_on_network_change_v2=*/false,
331 /*default_network=*/NetworkChangeNotifier::kInvalidNetworkHandle,
Zhongyi Shie01f2db2019-02-22 19:53:23332 quic::QuicTime::Delta::FromMilliseconds(
333 kDefaultRetransmittableOnWireTimeoutMillisecs),
Zhongyi Shi32fe14d42019-02-28 00:25:36334 /*migrate_idle_session=*/false,
Zhongyi Shic16b4102019-02-12 00:37:40335 base::TimeDelta::FromSeconds(kDefaultIdleSessionMigrationPeriodSeconds),
Zhongyi Shi73f23ca872017-12-13 18:37:13336 base::TimeDelta::FromSeconds(kMaxTimeOnNonDefaultNetworkSecs),
Zhongyi Shiee760762018-08-01 00:54:29337 kMaxMigrationsToNonDefaultNetworkOnWriteError,
Zhongyi Shi8b1e43f2017-12-13 20:46:30338 kMaxMigrationsToNonDefaultNetworkOnPathDegrading,
Zhongyi Shi5f587cc2017-11-21 23:24:17339 kQuicYieldAfterPacketsRead,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52340 quic::QuicTime::Delta::FromMilliseconds(
341 kQuicYieldAfterDurationMilliseconds),
Zhongyi Shidbce7f412019-02-01 23:16:29342 /*go_away_on_path_degrading*/ false,
Yixin Wang079ad542018-01-11 04:06:05343 client_headers_include_h2_stream_dependency_, /*cert_verify_flags=*/0,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52344 quic::test::DefaultQuicConfig(), &crypto_config_, "CONNECTION_UNKNOWN",
345 dns_start, dns_end, &push_promise_index_, nullptr,
Zhongyi Shic16b4102019-02-12 00:37:40346 base::DefaultTickClock::GetInstance(),
xunjieli84adaab2016-09-20 01:12:28347 base::ThreadTaskRunnerHandle::Get().get(),
xunjieli5fafe142016-03-23 23:32:54348 /*socket_performance_watcher=*/nullptr, net_log_.bound().net_log()));
rtennetid39bd762015-06-12 01:05:52349 session_->Initialize();
xunjieli100937eb52016-09-15 20:09:37350 TestCompletionCallback callback;
rchf0b18c8a2017-05-05 19:31:57351
rch433bf5f2017-02-14 04:10:47352 session_->CryptoConnect(callback.callback());
Ryan Hamilton6c2a2a82017-12-15 02:06:28353 stream_ = std::make_unique<QuicHttpStream>(
354 session_->CreateHandle(HostPortPair("www.example.org", 443)));
355 promised_stream_ = std::make_unique<QuicHttpStream>(
356 session_->CreateHandle(HostPortPair("www.example.org", 443)));
ckrasic3865ee0f2016-02-29 22:04:56357 push_promise_[":path"] = "/bar";
358 push_promise_[":authority"] = "www.example.org";
359 push_promise_[":version"] = "HTTP/1.1";
360 push_promise_[":method"] = "GET";
361 push_promise_[":scheme"] = "https";
362
363 promised_response_[":status"] = "200 OK";
364 promised_response_[":version"] = "HTTP/1.1";
365 promised_response_["content-type"] = "text/plain";
366
David Schinazi3f7465c2019-07-12 01:57:05367 promise_url_ =
368 quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
[email protected]6cca996b2013-01-25 07:43:36369 }
370
bnc614a92d32016-04-04 13:56:07371 void SetRequest(const string& method,
372 const string& path,
[email protected]1e960032013-12-20 19:00:20373 RequestPriority priority) {
rchcd379012017-04-12 21:53:32374 request_headers_ = client_maker_.GetRequestHeaders(method, "https", path);
[email protected]6cca996b2013-01-25 07:43:36375 }
376
bnc614a92d32016-04-04 13:56:07377 void SetResponse(const string& status, const string& body) {
alyssar2adf3ac2016-05-03 17:12:58378 response_headers_ = server_maker_.GetResponseHeaders(status);
[email protected]92bf17c2014-03-03 21:14:03379 response_data_ = body;
[email protected]6cca996b2013-01-25 07:43:36380 }
[email protected]f702d572012-12-04 15:56:20381
Ryan Hamilton8d9ee76e2018-05-29 23:52:52382 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructDataPacket(
Fan Yangac867502019-01-28 21:10:23383 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52384 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56385 bool should_include_version,
386 bool fin,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52387 quic::QuicStringPiece data,
alyssar2adf3ac2016-05-03 17:12:58388 QuicTestPacketMaker* maker) {
389 return maker->MakeDataPacket(packet_number, stream_id,
Ryan Hamilton7505eb92019-06-08 00:22:17390 should_include_version, fin, data);
ckrasic3865ee0f2016-02-29 22:04:56391 }
392
Ryan Hamilton8d9ee76e2018-05-29 23:52:52393 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientDataPacket(
Fan Yangac867502019-01-28 21:10:23394 uint64_t packet_number,
[email protected]e8ff26842013-03-22 21:02:05395 bool should_include_version,
[email protected]f702d572012-12-04 15:56:20396 bool fin,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52397 quic::QuicStringPiece data) {
Ryan Hamilton7505eb92019-06-08 00:22:17398 return client_maker_.MakeDataPacket(packet_number, stream_id_,
399 should_include_version, fin, data);
alyssar2adf3ac2016-05-03 17:12:58400 }
401
Renjief49758b2019-01-11 23:32:41402 std::unique_ptr<quic::QuicReceivedPacket>
403 ConstructClientMultipleDataFramesPacket(
Fan Yangac867502019-01-28 21:10:23404 uint64_t packet_number,
Renjief49758b2019-01-11 23:32:41405 bool should_include_version,
406 bool fin,
Renjief49758b2019-01-11 23:32:41407 const std::vector<std::string>& data) {
408 return client_maker_.MakeMultipleDataFramesPacket(
Ryan Hamilton7505eb92019-06-08 00:22:17409 packet_number, stream_id_, should_include_version, fin, data);
Renjief49758b2019-01-11 23:32:41410 }
411
Ryan Hamilton8d9ee76e2018-05-29 23:52:52412 std::unique_ptr<quic::QuicReceivedPacket> ConstructServerDataPacket(
Fan Yangac867502019-01-28 21:10:23413 uint64_t packet_number,
alyssar2adf3ac2016-05-03 17:12:58414 bool should_include_version,
415 bool fin,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52416 quic::QuicStringPiece data) {
Ryan Hamilton7505eb92019-06-08 00:22:17417 return server_maker_.MakeDataPacket(packet_number, stream_id_,
418 should_include_version, fin, data);
ckrasic3865ee0f2016-02-29 22:04:56419 }
420
Ryan Hamilton8d9ee76e2018-05-29 23:52:52421 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23422 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52423 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56424 bool should_include_version,
425 bool fin,
426 RequestPriority request_priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02427 size_t* spdy_headers_frame_length) {
Yixin Wang7a3f1b8d2018-01-17 21:40:48428 return InnerConstructRequestHeadersPacket(
429 packet_number, stream_id, should_include_version, fin, request_priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02430 0, spdy_headers_frame_length);
Yixin Wang7a3f1b8d2018-01-17 21:40:48431 }
432
Ryan Hamilton8d9ee76e2018-05-29 23:52:52433 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23434 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52435 quic::QuicStreamId stream_id,
Yixin Wang7a3f1b8d2018-01-17 21:40:48436 bool should_include_version,
437 bool fin,
438 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52439 quic::QuicStreamId parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02440 size_t* spdy_headers_frame_length) {
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,
Ryan Hamilton0d65a8c2019-06-07 00:46:02446 spdy_headers_frame_length);
[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,
Yixin Wange7ecc472018-03-06 19:00:25457 size_t* spdy_headers_frame_length,
458 const std::vector<std::string>& data_writes) {
Ryan Hamilton0239aac2018-05-19 00:03:13459 spdy::SpdyPriority priority =
Yixin Wange7ecc472018-03-06 19:00:25460 ConvertRequestPriorityToQuicPriority(request_priority);
461 return client_maker_.MakeRequestHeadersAndMultipleDataFramesPacket(
462 packet_number, stream_id, should_include_version, fin, priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02463 std::move(request_headers_), parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25464 spdy_headers_frame_length, data_writes);
465 }
466
Ryan Hamilton8d9ee76e2018-05-29 23:52:52467 std::unique_ptr<quic::QuicReceivedPacket> ConstructRequestAndRstPacket(
Fan Yangac867502019-01-28 21:10:23468 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52469 quic::QuicStreamId stream_id,
Yixin Wange7ecc472018-03-06 19:00:25470 bool should_include_version,
471 bool fin,
472 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52473 quic::QuicStreamId parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25474 size_t* spdy_headers_frame_length,
Ryan Hamiltonb5d4c5a2019-06-21 22:08:41475 quic::QuicRstStreamErrorCode error_code) {
Ryan Hamilton0239aac2018-05-19 00:03:13476 spdy::SpdyPriority priority =
Yixin Wange7ecc472018-03-06 19:00:25477 ConvertRequestPriorityToQuicPriority(request_priority);
478 return client_maker_.MakeRequestHeadersAndRstPacket(
479 packet_number, stream_id, should_include_version, fin, priority,
480 std::move(request_headers_), parent_stream_id,
Ryan Hamiltonb5d4c5a2019-06-21 22:08:41481 spdy_headers_frame_length, error_code);
Yixin Wange7ecc472018-03-06 19:00:25482 }
483
Ryan Hamilton8d9ee76e2018-05-29 23:52:52484 std::unique_ptr<quic::QuicReceivedPacket> ConstructRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23485 uint64_t packet_number,
rtennetif4bdb542015-01-21 14:33:05486 bool fin,
sclittlec4dc1a32015-09-24 00:15:45487 RequestPriority request_priority,
488 size_t* spdy_headers_frame_length) {
ckrasic3865ee0f2016-02-29 22:04:56489 return InnerConstructRequestHeadersPacket(
490 packet_number, stream_id_, kIncludeVersion, fin, request_priority,
Ryan Hamilton0d65a8c2019-06-07 00:46:02491 spdy_headers_frame_length);
ckrasic3865ee0f2016-02-29 22:04:56492 }
493
Ryan Hamilton8d9ee76e2018-05-29 23:52:52494 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructResponseHeadersPacket(
Fan Yangac867502019-01-28 21:10:23495 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52496 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56497 bool fin,
498 size_t* spdy_headers_frame_length) {
alyssar2adf3ac2016-05-03 17:12:58499 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26500 packet_number, stream_id, !kIncludeVersion, fin,
Ryan Hamilton0d65a8c2019-06-07 00:46:02501 std::move(response_headers_), spdy_headers_frame_length);
[email protected]1e960032013-12-20 19:00:20502 }
503
Ryan Hamilton8d9ee76e2018-05-29 23:52:52504 std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseHeadersPacket(
Fan Yangac867502019-01-28 21:10:23505 uint64_t packet_number,
sclittlec4dc1a32015-09-24 00:15:45506 bool fin,
507 size_t* spdy_headers_frame_length) {
ckrasic3865ee0f2016-02-29 22:04:56508 return InnerConstructResponseHeadersPacket(packet_number, stream_id_, fin,
509 spdy_headers_frame_length);
[email protected]1e960032013-12-20 19:00:20510 }
511
Ryan Hamilton8d9ee76e2018-05-29 23:52:52512 std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseTrailersPacket(
Fan Yangac867502019-01-28 21:10:23513 uint64_t packet_number,
xunjieli34291fe12016-03-02 13:58:38514 bool fin,
Ryan Hamilton0239aac2018-05-19 00:03:13515 spdy::SpdyHeaderBlock trailers,
Ryan Hamilton0d65a8c2019-06-07 00:46:02516 size_t* spdy_headers_frame_length) {
alyssar2adf3ac2016-05-03 17:12:58517 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26518 packet_number, stream_id_, !kIncludeVersion, fin, std::move(trailers),
Ryan Hamilton0d65a8c2019-06-07 00:46:02519 spdy_headers_frame_length);
xunjieli34291fe12016-03-02 13:58:38520 }
521
Ryan Hamilton8d9ee76e2018-05-29 23:52:52522 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientRstStreamPacket(
Fan Yangac867502019-01-28 21:10:23523 uint64_t packet_number) {
alyssara72f5352016-10-20 12:45:16524 return client_maker_.MakeRstPacket(packet_number, true, stream_id_,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52525 quic::QUIC_RST_ACKNOWLEDGEMENT);
[email protected]06ff5152013-08-29 01:03:05526 }
527
Ryan Hamilton8d9ee76e2018-05-29 23:52:52528 std::unique_ptr<quic::QuicReceivedPacket>
Fan Yangac867502019-01-28 21:10:23529 ConstructClientRstStreamCancelledPacket(uint64_t packet_number) {
alyssar2adf3ac2016-05-03 17:12:58530 return client_maker_.MakeRstPacket(packet_number, !kIncludeVersion,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52531 stream_id_, quic::QUIC_STREAM_CANCELLED);
rtenneti6bd660b2015-07-18 00:19:53532 }
533
Ryan Hamilton8d9ee76e2018-05-29 23:52:52534 std::unique_ptr<quic::QuicReceivedPacket>
Fan Yangac867502019-01-28 21:10:23535 ConstructClientRstStreamVaryMismatchPacket(uint64_t packet_number) {
alyssar2adf3ac2016-05-03 17:12:58536 return client_maker_.MakeRstPacket(packet_number, !kIncludeVersion,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52537 promise_id_,
538 quic::QUIC_PROMISE_VARY_MISMATCH);
ckrasic3865ee0f2016-02-29 22:04:56539 }
540
Fan Yang550c6282018-06-22 18:53:25541 std::unique_ptr<quic::QuicReceivedPacket>
542 ConstructClientRstStreamVaryMismatchAndRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23543 uint64_t packet_number,
Fan Yang550c6282018-06-22 18:53:25544 quic::QuicStreamId stream_id,
545 bool should_include_version,
546 bool fin,
547 RequestPriority request_priority,
548 quic::QuicStreamId parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02549 size_t* spdy_headers_frame_length) {
Fan Yang550c6282018-06-22 18:53:25550 spdy::SpdyPriority priority =
551 ConvertRequestPriorityToQuicPriority(request_priority);
552 return client_maker_.MakeRstAndRequestHeadersPacket(
553 packet_number, should_include_version, promise_id_,
554 quic::QUIC_PROMISE_VARY_MISMATCH, stream_id, fin, priority,
555 std::move(request_headers_), parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02556 spdy_headers_frame_length);
Fan Yang550c6282018-06-22 18:53:25557 }
558
Ryan Hamilton8d9ee76e2018-05-29 23:52:52559 std::unique_ptr<quic::QuicReceivedPacket> ConstructAckAndRstStreamPacket(
Fan Yangac867502019-01-28 21:10:23560 uint64_t packet_number,
561 uint64_t largest_received,
562 uint64_t smallest_received,
563 uint64_t least_unacked) {
alyssar2adf3ac2016-05-03 17:12:58564 return client_maker_.MakeAckAndRstPacket(
Ryan Hamilton8d9ee76e2018-05-29 23:52:52565 packet_number, !kIncludeVersion, stream_id_,
566 quic::QUIC_STREAM_CANCELLED, largest_received, smallest_received,
567 least_unacked, !kIncludeCongestionFeedback);
xunjieli34291fe12016-03-02 13:58:38568 }
569
Ryan Hamilton8d9ee76e2018-05-29 23:52:52570 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientRstStreamErrorPacket(
Fan Yangac867502019-01-28 21:10:23571 uint64_t packet_number,
maksim.sisov84e20c92016-06-23 08:49:34572 bool include_version) {
573 return client_maker_.MakeRstPacket(packet_number, include_version,
574 stream_id_,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52575 quic::QUIC_ERROR_PROCESSING_STREAM);
maksim.sisov84e20c92016-06-23 08:49:34576 }
577
Ryan Hamilton8d9ee76e2018-05-29 23:52:52578 std::unique_ptr<quic::QuicReceivedPacket> ConstructAckAndRstStreamPacket(
Fan Yangac867502019-01-28 21:10:23579 uint64_t packet_number) {
Renjie90e808e2019-01-24 07:24:04580 return ConstructAckAndRstStreamPacket(packet_number, 2, 1, 2);
[email protected]c5e1aca2014-01-30 04:03:04581 }
582
Ryan Hamilton8d9ee76e2018-05-29 23:52:52583 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientAckPacket(
Fan Yangac867502019-01-28 21:10:23584 uint64_t packet_number,
585 uint64_t largest_received,
586 uint64_t smallest_received,
587 uint64_t least_unacked) {
alyssar2adf3ac2016-05-03 17:12:58588 return client_maker_.MakeAckPacket(packet_number, largest_received,
wangyix6444ffe2017-04-25 17:49:49589 smallest_received, least_unacked,
alyssar2adf3ac2016-05-03 17:12:58590 !kIncludeCongestionFeedback);
591 }
592
Ryan Hamilton8d9ee76e2018-05-29 23:52:52593 std::unique_ptr<quic::QuicReceivedPacket> ConstructServerAckPacket(
Fan Yangac867502019-01-28 21:10:23594 uint64_t packet_number,
595 uint64_t largest_received,
596 uint64_t smallest_received,
597 uint64_t least_unacked) {
alyssar2adf3ac2016-05-03 17:12:58598 return server_maker_.MakeAckPacket(packet_number, largest_received,
wangyix6444ffe2017-04-25 17:49:49599 smallest_received, least_unacked,
alyssar2adf3ac2016-05-03 17:12:58600 !kIncludeCongestionFeedback);
[email protected]63534512012-12-23 18:49:00601 }
602
Ryan Hamilton8d9ee76e2018-05-29 23:52:52603 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientPriorityPacket(
Fan Yangac867502019-01-28 21:10:23604 uint64_t packet_number,
Yixin Wangb470bc882018-02-15 18:43:57605 bool should_include_version,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52606 quic::QuicStreamId id,
607 quic::QuicStreamId parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02608 RequestPriority request_priority) {
Yixin Wangb470bc882018-02-15 18:43:57609 return client_maker_.MakePriorityPacket(
610 packet_number, should_include_version, id, parent_stream_id,
Ryan Hamilton0d65a8c2019-06-07 00:46:02611 ConvertRequestPriorityToQuicPriority(request_priority));
Yixin Wangb470bc882018-02-15 18:43:57612 }
613
Ryan Hamilton0d65a8c2019-06-07 00:46:02614 std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket() {
615 return client_maker_.MakeInitialSettingsPacket(1);
fayang3bcb8b502016-12-07 21:44:37616 }
617
Victor Vasiliev076657c2019-03-12 02:46:43618 std::string ConstructDataHeader(size_t body_len) {
Nick Harper23290b82019-05-02 00:02:56619 if (version_.transport_version != quic::QUIC_VERSION_99) {
Renjief49758b2019-01-11 23:32:41620 return "";
621 }
622 quic::HttpEncoder encoder;
623 std::unique_ptr<char[]> buffer;
624 auto header_length = encoder.SerializeDataFrameHeader(body_len, &buffer);
Victor Vasiliev076657c2019-03-12 02:46:43625 return std::string(buffer.get(), header_length);
Renjief49758b2019-01-11 23:32:41626 }
627
Ryan Hamilton8d9ee76e2018-05-29 23:52:52628 void ReceivePromise(quic::QuicStreamId id) {
629 auto headers = quic::test::AsHeaderList(push_promise_);
rch08e198572017-05-09 16:56:55630 QuicChromiumClientStream::Handle* stream =
ckrasic3865ee0f2016-02-29 22:04:56631 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
ckrasic32b17dcd2016-10-31 06:15:35632 stream->OnPromiseHeaderList(id, headers.uncompressed_header_bytes(),
633 headers);
ckrasic3865ee0f2016-02-29 22:04:56634 }
635
xunjieli84adaab2016-09-20 01:12:28636 void ExpectLoadTimingValid(const LoadTimingInfo& load_timing_info,
xunjieli100937eb52016-09-15 20:09:37637 bool session_reused) {
638 EXPECT_EQ(session_reused, load_timing_info.socket_reused);
xunjieli84adaab2016-09-20 01:12:28639 if (session_reused) {
640 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
641 } else {
642 ExpectConnectTimingHasTimes(
643 load_timing_info.connect_timing,
644 CONNECT_TIMING_HAS_SSL_TIMES | CONNECT_TIMING_HAS_DNS_TIMES);
645 }
646 ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info);
xunjieli100937eb52016-09-15 20:09:37647 }
648
Fan Yang32c5a112018-12-10 20:06:33649 quic::QuicStreamId GetNthClientInitiatedBidirectionalStreamId(int n) {
Nick Harper23290b82019-05-02 00:02:56650 return quic::test::GetNthClientInitiatedBidirectionalStreamId(
651 version_.transport_version, n);
ckrasicbf2f59c2017-05-04 23:54:36652 }
653
Fan Yang32c5a112018-12-10 20:06:33654 quic::QuicStreamId GetNthServerInitiatedUnidirectionalStreamId(int n) {
Nick Harper23290b82019-05-02 00:02:56655 return quic::test::GetNthServerInitiatedUnidirectionalStreamId(
656 version_.transport_version, n);
ckrasicbf2f59c2017-05-04 23:54:36657 }
658
Ryan Hamiltona1d1f4a2019-06-26 14:43:04659 QuicFlagSaver saver_;
660
Nick Harper23290b82019-05-02 00:02:56661 const quic::ParsedQuicVersion version_;
Yixin Wang079ad542018-01-11 04:06:05662 const bool client_headers_include_h2_stream_dependency_;
663
xunjieli5fafe142016-03-23 23:32:54664 BoundTestNetLog net_log_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52665 quic::test::MockSendAlgorithm* send_algorithm_;
[email protected]f702d572012-12-04 15:56:20666 scoped_refptr<TestTaskRunner> runner_;
danakjad1777e2016-04-16 00:56:42667 std::unique_ptr<MockWrite[]> mock_writes_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52668 quic::MockClock clock_;
[email protected]f702d572012-12-04 15:56:20669 TestQuicConnection* connection_;
danakjad1777e2016-04-16 00:56:42670 std::unique_ptr<QuicChromiumConnectionHelper> helper_;
rch16c74d1d2016-04-22 06:14:07671 std::unique_ptr<QuicChromiumAlarmFactory> alarm_factory_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52672 testing::StrictMock<quic::test::MockQuicConnectionVisitor> visitor_;
rch97827ee2017-05-24 23:49:12673 std::unique_ptr<UploadDataStream> upload_data_stream_;
danakjad1777e2016-04-16 00:56:42674 std::unique_ptr<QuicHttpStream> stream_;
[email protected]5db452202014-08-19 05:22:15675 TransportSecurityState transport_security_state_;
danakjad1777e2016-04-16 00:56:42676 std::unique_ptr<QuicChromiumClientSession> session_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52677 quic::QuicCryptoClientConfig crypto_config_;
[email protected]f702d572012-12-04 15:56:20678 TestCompletionCallback callback_;
679 HttpRequestInfo request_;
680 HttpRequestHeaders headers_;
681 HttpResponseInfo response_;
682 scoped_refptr<IOBufferWithSize> read_buffer_;
Ryan Hamilton0239aac2018-05-19 00:03:13683 spdy::SpdyHeaderBlock request_headers_;
684 spdy::SpdyHeaderBlock response_headers_;
bnc614a92d32016-04-04 13:56:07685 string request_data_;
686 string response_data_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52687 quic::QuicClientPushPromiseIndex push_promise_index_;
[email protected]f702d572012-12-04 15:56:20688
ckrasic3865ee0f2016-02-29 22:04:56689 // For server push testing
danakjad1777e2016-04-16 00:56:42690 std::unique_ptr<QuicHttpStream> promised_stream_;
Ryan Hamilton0239aac2018-05-19 00:03:13691 spdy::SpdyHeaderBlock push_promise_;
692 spdy::SpdyHeaderBlock promised_response_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52693 const quic::QuicStreamId promise_id_;
ckrasic3865ee0f2016-02-29 22:04:56694 string promise_url_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52695 const quic::QuicStreamId stream_id_;
ckrasic3865ee0f2016-02-29 22:04:56696
Ryan Hamilton8d9ee76e2018-05-29 23:52:52697 const quic::QuicConnectionId connection_id_;
alyssar2adf3ac2016-05-03 17:12:58698 QuicTestPacketMaker client_maker_;
699 QuicTestPacketMaker server_maker_;
[email protected]f702d572012-12-04 15:56:20700 IPEndPoint self_addr_;
701 IPEndPoint peer_addr_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52702 quic::test::MockRandom random_generator_;
rch03b7a202016-02-05 00:54:20703 ProofVerifyDetailsChromium verify_details_;
[email protected]e8ff26842013-03-22 21:02:05704 MockCryptoClientStreamFactory crypto_client_stream_factory_;
danakjad1777e2016-04-16 00:56:42705 std::unique_ptr<StaticSocketDataProvider> socket_data_;
Ryan Hamilton0d65a8c2019-06-07 00:46:02706 QuicPacketPrinter printer_;
[email protected]f702d572012-12-04 15:56:20707 std::vector<PacketToWrite> writes_;
708};
709
Victor Costane635086f2019-01-27 05:20:30710INSTANTIATE_TEST_SUITE_P(
Bence Békyce380cb2018-04-26 23:39:55711 VersionIncludeStreamDependencySequence,
Yixin Wang079ad542018-01-11 04:06:05712 QuicHttpStreamTest,
Ryan Hamiltona1d1f4a2019-06-26 14:43:04713 ::testing::Combine(::testing::ValuesIn(quic::AllSupportedVersions()),
Nick Harper23290b82019-05-02 00:02:56714 ::testing::Bool()));
[email protected]1e960032013-12-20 19:00:20715
716TEST_P(QuicHttpStreamTest, RenewStreamForAuth) {
[email protected]ed3fc15d2013-03-08 18:37:44717 Initialize();
rtennetibe635732014-10-02 22:51:42718 EXPECT_EQ(nullptr, stream_->RenewStreamForAuth());
[email protected]f702d572012-12-04 15:56:20719}
720
mmenkebd84c392015-09-02 14:12:34721TEST_P(QuicHttpStreamTest, CanReuseConnection) {
[email protected]ed3fc15d2013-03-08 18:37:44722 Initialize();
mmenkebd84c392015-09-02 14:12:34723 EXPECT_FALSE(stream_->CanReuseConnection());
[email protected]f702d572012-12-04 15:56:20724}
725
jri231c2972016-03-08 19:50:11726TEST_P(QuicHttpStreamTest, DisableConnectionMigrationForStream) {
Zhongyi Shibb28b1f2018-07-18 02:41:26727 request_.load_flags |= LOAD_DISABLE_CONNECTION_MIGRATION_TO_CELLULAR;
jri231c2972016-03-08 19:50:11728 Initialize();
xunjieli5fafe142016-03-23 23:32:54729 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27730 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:54731 net_log_.bound(), callback_.callback()));
rch08e198572017-05-09 16:56:55732 QuicChromiumClientStream::Handle* client_stream =
jri231c2972016-03-08 19:50:11733 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
Zhongyi Shibb28b1f2018-07-18 02:41:26734 EXPECT_FALSE(client_stream->can_migrate_to_cellular_network());
jri231c2972016-03-08 19:50:11735}
736
[email protected]1e960032013-12-20 19:00:20737TEST_P(QuicHttpStreamTest, GetRequest) {
738 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:45739 size_t spdy_request_header_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:02740 AddWrite(ConstructInitialSettingsPacket());
fayang3bcb8b502016-12-07 21:44:37741 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33742 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:02743 DEFAULT_PRIORITY, &spdy_request_header_frame_length));
fayang3bcb8b502016-12-07 21:44:37744
[email protected]f702d572012-12-04 15:56:20745 Initialize();
746
747 request_.method = "GET";
rchcd379012017-04-12 21:53:32748 request_.url = GURL("https://www.example.org/");
[email protected]f702d572012-12-04 15:56:20749
xunjieli100937eb52016-09-15 20:09:37750 // Make sure getting load timing from the stream early does not crash.
751 LoadTimingInfo load_timing_info;
752 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
753
xunjieli5fafe142016-03-23 23:32:54754 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27755 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:54756 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:02757 EXPECT_EQ(OK,
758 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20759
760 // Ack the request.
Renjie90e808e2019-01-24 07:24:04761 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]f702d572012-12-04 15:56:20762
robpercival214763f2016-07-01 23:27:01763 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
764 IsError(ERR_IO_PENDING));
[email protected]f702d572012-12-04 15:56:20765
bnc614a92d32016-04-04 13:56:07766 SetResponse("404 Not Found", string());
sclittlec4dc1a32015-09-24 00:15:45767 size_t spdy_response_header_frame_length;
768 ProcessPacket(ConstructResponseHeadersPacket(
769 2, kFin, &spdy_response_header_frame_length));
[email protected]f702d572012-12-04 15:56:20770
771 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:01772 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]cadac622013-06-11 16:46:36773 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:20774 EXPECT_EQ(404, response_.headers->response_code());
775 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
[email protected]6ed67432014-06-24 01:53:53776 EXPECT_FALSE(response_.response_time.is_null());
777 EXPECT_FALSE(response_.request_time.is_null());
[email protected]f702d572012-12-04 15:56:20778
779 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:02780 EXPECT_EQ(0,
781 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
782 callback_.callback()));
[email protected]f702d572012-12-04 15:56:20783 EXPECT_TRUE(stream_->IsResponseBodyComplete());
784 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:10785
xunjieli100937eb52016-09-15 20:09:37786 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
xunjieli84adaab2016-09-20 01:12:28787 ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
xunjieli100937eb52016-09-15 20:09:37788
sclittle1edeeb22015-09-02 20:46:10789 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:45790 // headers and payload.
791 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
792 stream_->GetTotalSentBytes());
793 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length),
794 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:20795}
796
xunjieli100937eb52016-09-15 20:09:37797TEST_P(QuicHttpStreamTest, LoadTimingTwoRequests) {
798 SetRequest("GET", "/", DEFAULT_PRIORITY);
799 size_t spdy_request_header_frame_length;
800
Ryan Hamilton0d65a8c2019-06-07 00:46:02801 AddWrite(ConstructInitialSettingsPacket());
xunjieli100937eb52016-09-15 20:09:37802 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33803 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:02804 DEFAULT_PRIORITY, &spdy_request_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37805
806 // SetRequest() again for second request as |request_headers_| was moved.
807 SetRequest("GET", "/", DEFAULT_PRIORITY);
808 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33809 3, GetNthClientInitiatedBidirectionalStreamId(1), kIncludeVersion, kFin,
810 DEFAULT_PRIORITY, GetNthClientInitiatedBidirectionalStreamId(0),
Ryan Hamilton0d65a8c2019-06-07 00:46:02811 &spdy_request_header_frame_length));
Renjie90e808e2019-01-24 07:24:04812 AddWrite(ConstructClientAckPacket(4, 3, 1, 2)); // Ack the responses.
xunjieli100937eb52016-09-15 20:09:37813
814 Initialize();
815
816 request_.method = "GET";
rchcd379012017-04-12 21:53:32817 request_.url = GURL("https://www.example.org/");
xunjieli100937eb52016-09-15 20:09:37818 // Start first request.
819 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27820 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli100937eb52016-09-15 20:09:37821 net_log_.bound(), callback_.callback()));
822 EXPECT_EQ(OK,
823 stream_->SendRequest(headers_, &response_, callback_.callback()));
824
825 // Start a second request.
Ryan Hamilton6c2a2a82017-12-15 02:06:28826 QuicHttpStream stream2(
827 session_->CreateHandle(HostPortPair("www.example.org", 443)));
xunjieli100937eb52016-09-15 20:09:37828 TestCompletionCallback callback2;
829 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27830 stream2.InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli100937eb52016-09-15 20:09:37831 net_log_.bound(), callback2.callback()));
832 EXPECT_EQ(OK,
833 stream2.SendRequest(headers_, &response_, callback2.callback()));
834
835 // Ack both requests.
Renjie90e808e2019-01-24 07:24:04836 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
xunjieli100937eb52016-09-15 20:09:37837
838 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
839 IsError(ERR_IO_PENDING));
840 size_t spdy_response_header_frame_length;
841 SetResponse("200 OK", string());
842 ProcessPacket(InnerConstructResponseHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33843 2, GetNthClientInitiatedBidirectionalStreamId(0), kFin,
ckrasicbf2f59c2017-05-04 23:54:36844 &spdy_response_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37845
846 // Now that the headers have been processed, the callback will return.
847 EXPECT_THAT(callback_.WaitForResult(), IsOk());
848 EXPECT_EQ(200, response_.headers->response_code());
849
850 // There is no body, so this should return immediately.
851 EXPECT_EQ(0,
852 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
853 callback_.callback()));
854 EXPECT_TRUE(stream_->IsResponseBodyComplete());
855
856 LoadTimingInfo load_timing_info;
857 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
xunjieli84adaab2016-09-20 01:12:28858 ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
xunjieli100937eb52016-09-15 20:09:37859
860 // SetResponse() again for second request as |response_headers_| was moved.
861 SetResponse("200 OK", string());
862 EXPECT_THAT(stream2.ReadResponseHeaders(callback2.callback()),
863 IsError(ERR_IO_PENDING));
864
865 ProcessPacket(InnerConstructResponseHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33866 3, GetNthClientInitiatedBidirectionalStreamId(1), kFin,
ckrasicbf2f59c2017-05-04 23:54:36867 &spdy_response_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37868
869 EXPECT_THAT(callback2.WaitForResult(), IsOk());
870
871 // There is no body, so this should return immediately.
872 EXPECT_EQ(0,
873 stream2.ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
874 callback2.callback()));
875 EXPECT_TRUE(stream2.IsResponseBodyComplete());
876
877 LoadTimingInfo load_timing_info2;
878 EXPECT_TRUE(stream2.GetLoadTimingInfo(&load_timing_info2));
xunjieli84adaab2016-09-20 01:12:28879 ExpectLoadTimingValid(load_timing_info2, /*session_reused=*/true);
xunjieli100937eb52016-09-15 20:09:37880}
881
xunjieli34291fe12016-03-02 13:58:38882// QuicHttpStream does not currently support trailers. It should ignore
883// trailers upon receiving them.
884TEST_P(QuicHttpStreamTest, GetRequestWithTrailers) {
885 SetRequest("GET", "/", DEFAULT_PRIORITY);
886 size_t spdy_request_header_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:02887 AddWrite(ConstructInitialSettingsPacket());
fayang3bcb8b502016-12-07 21:44:37888 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33889 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:02890 DEFAULT_PRIORITY, &spdy_request_header_frame_length));
Renjie90e808e2019-01-24 07:24:04891 AddWrite(ConstructClientAckPacket(3, 3, 1, 2)); // Ack the data packet.
xunjieli34291fe12016-03-02 13:58:38892
893 Initialize();
894
895 request_.method = "GET";
rchcd379012017-04-12 21:53:32896 request_.url = GURL("https://www.example.org/");
xunjieli34291fe12016-03-02 13:58:38897
xunjieli5fafe142016-03-23 23:32:54898 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27899 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:54900 net_log_.bound(), callback_.callback()));
901
xunjieli34291fe12016-03-02 13:58:38902 EXPECT_EQ(OK,
903 stream_->SendRequest(headers_, &response_, callback_.callback()));
xunjieli34291fe12016-03-02 13:58:38904 // Ack the request.
Renjie90e808e2019-01-24 07:24:04905 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
xunjieli34291fe12016-03-02 13:58:38906
robpercival214763f2016-07-01 23:27:01907 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
908 IsError(ERR_IO_PENDING));
xunjieli34291fe12016-03-02 13:58:38909
bnc614a92d32016-04-04 13:56:07910 SetResponse("200 OK", string());
xunjieli34291fe12016-03-02 13:58:38911
912 // Send the response headers.
913 size_t spdy_response_header_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:02914 ProcessPacket(ConstructResponseHeadersPacket(
915 2, !kFin, &spdy_response_header_frame_length));
xunjieli34291fe12016-03-02 13:58:38916 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:01917 EXPECT_THAT(callback_.WaitForResult(), IsOk());
xunjieli34291fe12016-03-02 13:58:38918 ASSERT_TRUE(response_.headers.get());
919 EXPECT_EQ(200, response_.headers->response_code());
920 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
921 EXPECT_FALSE(response_.response_time.is_null());
922 EXPECT_FALSE(response_.request_time.is_null());
923
924 // Send the response body.
925 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:43926 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:17927 ProcessPacket(
928 ConstructServerDataPacket(3, false, !kFin, header + kResponseBody));
Ryan Hamilton0239aac2018-05-19 00:03:13929 spdy::SpdyHeaderBlock trailers;
xunjieli34291fe12016-03-02 13:58:38930 size_t spdy_trailers_frame_length;
931 trailers["foo"] = "bar";
Ryan Hamiltona1d1f4a2019-06-26 14:43:04932 if (!quic::VersionUsesQpack(version_.transport_version)) {
933 trailers[quic::kFinalOffsetHeaderKey] =
934 base::NumberToString(strlen(kResponseBody) + header.length());
935 }
Ryan Hamilton0d65a8c2019-06-07 00:46:02936 ProcessPacket(ConstructResponseTrailersPacket(4, kFin, std::move(trailers),
937 &spdy_trailers_frame_length));
xunjieli34291fe12016-03-02 13:58:38938
939 // Make sure trailers are processed.
fdoray92e35a72016-06-10 15:54:55940 base::RunLoop().RunUntilIdle();
xunjieli34291fe12016-03-02 13:58:38941
942 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
943 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
944 callback_.callback()));
945 EXPECT_TRUE(stream_->IsResponseBodyComplete());
946
947 EXPECT_EQ(OK,
948 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
949 callback_.callback()));
950
951 EXPECT_TRUE(stream_->IsResponseBodyComplete());
952 EXPECT_TRUE(AtEof());
953
954 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
955 // headers and payload.
956 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
957 stream_->GetTotalSentBytes());
Renjief49758b2019-01-11 23:32:41958 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length +
959 strlen(kResponseBody) + header.length() +
960 +spdy_trailers_frame_length),
961 stream_->GetTotalReceivedBytes());
xunjieli5fafe142016-03-23 23:32:54962 // Check that NetLog was filled as expected.
963 TestNetLogEntry::List entries;
964 net_log_.GetEntries(&entries);
965 size_t pos = ExpectLogContainsSomewhere(
966 entries, /*min_offset=*/0,
mikecirone8b85c432016-09-08 19:11:00967 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
968 NetLogEventPhase::NONE);
xunjieli5fafe142016-03-23 23:32:54969 pos = ExpectLogContainsSomewhere(
970 entries, /*min_offset=*/pos,
mikecirone8b85c432016-09-08 19:11:00971 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
972 NetLogEventPhase::NONE);
xunjieli5fafe142016-03-23 23:32:54973 ExpectLogContainsSomewhere(
974 entries, /*min_offset=*/pos,
mikecirone8b85c432016-09-08 19:11:00975 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
976 NetLogEventPhase::NONE);
xunjieli34291fe12016-03-02 13:58:38977}
978
[email protected]3e7dca62013-09-10 16:14:23979// Regression test for http://crbug.com/288128
[email protected]1e960032013-12-20 19:00:20980TEST_P(QuicHttpStreamTest, GetRequestLargeResponse) {
981 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:45982 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:02983 AddWrite(ConstructInitialSettingsPacket());
fayang3bcb8b502016-12-07 21:44:37984 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33985 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:02986 DEFAULT_PRIORITY, &spdy_request_headers_frame_length));
[email protected]3e7dca62013-09-10 16:14:23987 Initialize();
988
989 request_.method = "GET";
rchcd379012017-04-12 21:53:32990 request_.url = GURL("https://www.example.org/");
[email protected]3e7dca62013-09-10 16:14:23991
xunjieli5fafe142016-03-23 23:32:54992 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27993 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:54994 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:02995 EXPECT_EQ(OK,
996 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:23997
998 // Ack the request.
Renjie90e808e2019-01-24 07:24:04999 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]3e7dca62013-09-10 16:14:231000
robpercival214763f2016-07-01 23:27:011001 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1002 IsError(ERR_IO_PENDING));
[email protected]3e7dca62013-09-10 16:14:231003
bnc086b39e12016-06-24 13:05:261004 response_headers_[":status"] = "200 OK";
1005 response_headers_[":version"] = "HTTP/1.1";
1006 response_headers_["content-type"] = "text/plain";
1007 response_headers_["big6"] = string(1000, 'x'); // Lots of x's.
[email protected]3e7dca62013-09-10 16:14:231008
sclittlec4dc1a32015-09-24 00:15:451009 size_t spdy_response_headers_frame_length;
1010 ProcessPacket(ConstructResponseHeadersPacket(
1011 2, kFin, &spdy_response_headers_frame_length));
[email protected]3e7dca62013-09-10 16:14:231012
1013 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:011014 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]3e7dca62013-09-10 16:14:231015 ASSERT_TRUE(response_.headers.get());
1016 EXPECT_EQ(200, response_.headers->response_code());
1017 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1018
1019 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:021020 EXPECT_EQ(0,
1021 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1022 callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:231023 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1024 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101025
1026 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451027 // headers and payload.
1028 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1029 stream_->GetTotalSentBytes());
1030 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length),
1031 stream_->GetTotalReceivedBytes());
[email protected]3e7dca62013-09-10 16:14:231032}
1033
rchf9f103cbc2014-08-30 05:28:041034// Regression test for http://crbug.com/409101
1035TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendRequest) {
1036 SetRequest("GET", "/", DEFAULT_PRIORITY);
1037 Initialize();
1038
1039 request_.method = "GET";
rchcd379012017-04-12 21:53:321040 request_.url = GURL("https://www.example.org/");
rchf9f103cbc2014-08-30 05:28:041041
xunjieli5fafe142016-03-23 23:32:541042 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271043 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541044 net_log_.bound(), callback_.callback()));
rchf9f103cbc2014-08-30 05:28:041045
jri78ec06a2016-03-31 18:19:401046 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521047 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rchf9f103cbc2014-08-30 05:28:041048
1049 EXPECT_EQ(ERR_CONNECTION_CLOSED,
rjshaded5ced072015-12-18 19:26:021050 stream_->SendRequest(headers_, &response_, callback_.callback()));
sclittle1edeeb22015-09-02 20:46:101051
1052 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1053 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rchf9f103cbc2014-08-30 05:28:041054}
1055
rch03b7a202016-02-05 00:54:201056// Regression test for http://crbug.com/584441
1057TEST_P(QuicHttpStreamTest, GetSSLInfoAfterSessionClosed) {
1058 SetRequest("GET", "/", DEFAULT_PRIORITY);
1059 Initialize();
1060
1061 request_.method = "GET";
rchcd379012017-04-12 21:53:321062 request_.url = GURL("https://www.example.org/");
rch03b7a202016-02-05 00:54:201063
xunjieli5fafe142016-03-23 23:32:541064 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271065 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541066 net_log_.bound(), callback_.callback()));
rch03b7a202016-02-05 00:54:201067
1068 SSLInfo ssl_info;
rch11565e02016-02-09 20:13:471069 EXPECT_FALSE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:201070 stream_->GetSSLInfo(&ssl_info);
rch11565e02016-02-09 20:13:471071 EXPECT_TRUE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:201072
jri78ec06a2016-03-31 18:19:401073 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521074 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rch03b7a202016-02-05 00:54:201075
rch11565e02016-02-09 20:13:471076 SSLInfo ssl_info2;
1077 stream_->GetSSLInfo(&ssl_info2);
1078 EXPECT_TRUE(ssl_info2.is_valid());
rch03b7a202016-02-05 00:54:201079}
1080
rchcd379012017-04-12 21:53:321081TEST_P(QuicHttpStreamTest, GetAlternativeService) {
1082 SetRequest("GET", "/", DEFAULT_PRIORITY);
1083 Initialize();
1084
1085 request_.method = "GET";
1086 request_.url = GURL("https://www.example.org/");
1087
1088 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271089 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
rchcd379012017-04-12 21:53:321090 net_log_.bound(), callback_.callback()));
1091
1092 AlternativeService alternative_service;
1093 EXPECT_TRUE(stream_->GetAlternativeService(&alternative_service));
1094 EXPECT_EQ(AlternativeService(kProtoQUIC, "www.example.org", 443),
1095 alternative_service);
1096
1097 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521098 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rchcd379012017-04-12 21:53:321099
1100 AlternativeService alternative_service2;
1101 EXPECT_TRUE(stream_->GetAlternativeService(&alternative_service2));
1102 EXPECT_EQ(AlternativeService(kProtoQUIC, "www.example.org", 443),
1103 alternative_service2);
1104}
1105
zhongyica364fbb2015-12-12 03:39:121106TEST_P(QuicHttpStreamTest, LogGranularQuicConnectionError) {
1107 SetRequest("GET", "/", DEFAULT_PRIORITY);
1108 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:021109 AddWrite(ConstructInitialSettingsPacket());
fayang3bcb8b502016-12-07 21:44:371110 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:331111 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:021112 DEFAULT_PRIORITY, &spdy_request_headers_frame_length));
fayang3bcb8b502016-12-07 21:44:371113 AddWrite(ConstructAckAndRstStreamPacket(3));
zhongyica364fbb2015-12-12 03:39:121114 Initialize();
1115
1116 request_.method = "GET";
rchcd379012017-04-12 21:53:321117 request_.url = GURL("https://www.example.org/");
zhongyica364fbb2015-12-12 03:39:121118
xunjieli5fafe142016-03-23 23:32:541119 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271120 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541121 net_log_.bound(), callback_.callback()));
zhongyica364fbb2015-12-12 03:39:121122 EXPECT_EQ(OK,
1123 stream_->SendRequest(headers_, &response_, callback_.callback()));
1124
1125 // Ack the request.
Renjie90e808e2019-01-24 07:24:041126 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011127 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1128 IsError(ERR_IO_PENDING));
zhongyica364fbb2015-12-12 03:39:121129
Ryan Hamilton8d9ee76e2018-05-29 23:52:521130 quic::QuicConnectionCloseFrame frame;
Zhongyi Shica576df2019-04-12 17:43:401131 frame.quic_error_code = quic::QUIC_PEER_GOING_AWAY;
rch1c5b74a2016-06-23 22:10:551132 session_->connection()->OnConnectionCloseFrame(frame);
zhongyica364fbb2015-12-12 03:39:121133
1134 NetErrorDetails details;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521135 EXPECT_EQ(quic::QUIC_NO_ERROR, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121136 stream_->PopulateNetErrorDetails(&details);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521137 EXPECT_EQ(quic::QUIC_PEER_GOING_AWAY, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121138}
1139
Ryan Hamiltone316e482017-08-17 02:48:531140TEST_P(QuicHttpStreamTest, LogGranularQuicErrorIfHandshakeNotConfirmed) {
Ryan Hamiltona1d1f4a2019-06-26 14:43:041141 // TODO(nharper): Figure out why this test does not send packets
1142 // when TLS is used.
1143 if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
1144 Initialize();
1145
1146 return;
1147 }
1148
rch617e0652017-04-26 17:57:511149 // By default the test setup defaults handshake to be confirmed. Manually set
1150 // it to be not confirmed.
rch617e0652017-04-26 17:57:511151 crypto_client_stream_factory_.set_handshake_mode(
Ryan Hamilton9835e662018-08-02 05:36:271152 MockCryptoClientStream::ZERO_RTT);
rch617e0652017-04-26 17:57:511153
zhongyica364fbb2015-12-12 03:39:121154 SetRequest("GET", "/", DEFAULT_PRIORITY);
1155 size_t spdy_request_headers_frame_length;
Michael Warres167db3e2019-03-01 21:38:031156 client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
fayang3bcb8b502016-12-07 21:44:371157 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:331158 1, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:021159 DEFAULT_PRIORITY, &spdy_request_headers_frame_length));
zhongyica364fbb2015-12-12 03:39:121160 Initialize();
1161
1162 request_.method = "GET";
rchcd379012017-04-12 21:53:321163 request_.url = GURL("https://www.example.org/");
zhongyica364fbb2015-12-12 03:39:121164
xunjieli5fafe142016-03-23 23:32:541165 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271166 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541167 net_log_.bound(), callback_.callback()));
zhongyica364fbb2015-12-12 03:39:121168 EXPECT_EQ(OK,
1169 stream_->SendRequest(headers_, &response_, callback_.callback()));
1170
1171 // Ack the request.
Renjie90e808e2019-01-24 07:24:041172 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011173 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1174 IsError(ERR_IO_PENDING));
zhongyica364fbb2015-12-12 03:39:121175
Ryan Hamilton8d9ee76e2018-05-29 23:52:521176 quic::QuicConnectionCloseFrame frame;
Zhongyi Shica576df2019-04-12 17:43:401177 frame.quic_error_code = quic::QUIC_PEER_GOING_AWAY;
rch1c5b74a2016-06-23 22:10:551178 session_->connection()->OnConnectionCloseFrame(frame);
zhongyica364fbb2015-12-12 03:39:121179
1180 NetErrorDetails details;
zhongyica364fbb2015-12-12 03:39:121181 stream_->PopulateNetErrorDetails(&details);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521182 EXPECT_EQ(quic::QUIC_PEER_GOING_AWAY, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121183}
1184
rch11a114a2014-09-04 23:41:591185// Regression test for http://crbug.com/409871
1186TEST_P(QuicHttpStreamTest, SessionClosedBeforeReadResponseHeaders) {
1187 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451188 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:021189 AddWrite(ConstructInitialSettingsPacket());
fayang3bcb8b502016-12-07 21:44:371190 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:331191 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:021192 DEFAULT_PRIORITY, &spdy_request_headers_frame_length));
rch11a114a2014-09-04 23:41:591193 Initialize();
1194
1195 request_.method = "GET";
rchcd379012017-04-12 21:53:321196 request_.url = GURL("https://www.example.org/");
rch11a114a2014-09-04 23:41:591197
xunjieli5fafe142016-03-23 23:32:541198 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271199 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541200 net_log_.bound(), callback_.callback()));
rch11a114a2014-09-04 23:41:591201
rjshaded5ced072015-12-18 19:26:021202 EXPECT_EQ(OK,
1203 stream_->SendRequest(headers_, &response_, callback_.callback()));
rch11a114a2014-09-04 23:41:591204
jri78ec06a2016-03-31 18:19:401205 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521206 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rch11a114a2014-09-04 23:41:591207
1208 EXPECT_NE(OK, stream_->ReadResponseHeaders(callback_.callback()));
sclittle1edeeb22015-09-02 20:46:101209
1210 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451211 // headers and payload.
1212 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1213 stream_->GetTotalSentBytes());
sclittle1edeeb22015-09-02 20:46:101214 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rch11a114a2014-09-04 23:41:591215}
1216
[email protected]1e960032013-12-20 19:00:201217TEST_P(QuicHttpStreamTest, SendPostRequest) {
1218 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451219 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:021220 AddWrite(ConstructInitialSettingsPacket());
Yixin Wange7ecc472018-03-06 19:00:251221
Victor Vasiliev076657c2019-03-12 02:46:431222 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harper23290b82019-05-02 00:02:561223 if (version_.transport_version != quic::QUIC_VERSION_99) {
Renjief49758b2019-01-11 23:32:411224 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1225 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:021226 DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
1227 {kUploadData}));
Renjief49758b2019-01-11 23:32:411228 } else {
1229 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1230 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:021231 DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
1232 {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411233 }
Yixin Wange7ecc472018-03-06 19:00:251234
Renjie90e808e2019-01-24 07:24:041235 AddWrite(ConstructClientAckPacket(3, 3, 1, 2));
[email protected]f702d572012-12-04 15:56:201236
1237 Initialize();
1238
danakjad1777e2016-04-16 00:56:421239 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:191240 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
ricea2deef682016-09-09 08:04:071241 kUploadData, strlen(kUploadData)));
rch97827ee2017-05-24 23:49:121242 upload_data_stream_ =
Jeremy Roman0579ed62017-08-29 15:56:191243 std::make_unique<ElementsUploadDataStream>(std::move(element_readers), 0);
[email protected]f702d572012-12-04 15:56:201244 request_.method = "POST";
rchcd379012017-04-12 21:53:321245 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121246 request_.upload_data_stream = upload_data_stream_.get();
Bence Békyd8a21fc32018-06-27 18:29:581247 ASSERT_THAT(request_.upload_data_stream->Init(CompletionOnceCallback(),
tfarina42834112016-09-22 13:38:201248 NetLogWithSource()),
1249 IsOk());
[email protected]f702d572012-12-04 15:56:201250
xunjieli5fafe142016-03-23 23:32:541251 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271252 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541253 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021254 EXPECT_EQ(OK,
1255 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:201256
1257 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041258 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]f702d572012-12-04 15:56:201259
1260 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071261 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451262 size_t spdy_response_headers_frame_length;
1263 ProcessPacket(ConstructResponseHeadersPacket(
1264 2, !kFin, &spdy_response_headers_frame_length));
[email protected]f702d572012-12-04 15:56:201265
rchfb47f712017-05-21 03:24:001266 // The headers have already arrived.
1267 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]cadac622013-06-11 16:46:361268 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:201269 EXPECT_EQ(200, response_.headers->response_code());
1270 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1271
1272 // Send the response body.
1273 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431274 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:411275 ProcessPacket(
Ryan Hamilton7505eb92019-06-08 00:22:171276 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
[email protected]f702d572012-12-04 15:56:201277 // Since the body has already arrived, this should return immediately.
1278 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
1279 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1280 callback_.callback()));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291281 EXPECT_EQ(0,
1282 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1283 callback_.callback()));
1284
1285 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1286 EXPECT_TRUE(AtEof());
1287
1288 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
1289 // headers and payload.
1290 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411291 strlen(kUploadData) + header.length()),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291292 stream_->GetTotalSentBytes());
1293 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411294 strlen(kResponseBody) + header2.length()),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291295 stream_->GetTotalReceivedBytes());
1296}
1297
1298TEST_P(QuicHttpStreamTest, SendPostRequestAndReceiveSoloFin) {
1299 SetRequest("POST", "/", DEFAULT_PRIORITY);
1300 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:021301 AddWrite(ConstructInitialSettingsPacket());
Victor Vasiliev076657c2019-03-12 02:46:431302 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harper23290b82019-05-02 00:02:561303 if (version_.transport_version != quic::QUIC_VERSION_99) {
Renjief49758b2019-01-11 23:32:411304 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1305 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:021306 DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
1307 {kUploadData}));
Renjief49758b2019-01-11 23:32:411308 } else {
1309 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1310 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:021311 DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
1312 {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411313 }
1314
Renjie90e808e2019-01-24 07:24:041315 AddWrite(ConstructClientAckPacket(3, 3, 1, 2));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291316
1317 Initialize();
1318
1319 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:191320 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
Ryan Hamilton2ef0a9c2017-07-25 03:18:291321 kUploadData, strlen(kUploadData)));
1322 upload_data_stream_ =
Jeremy Roman0579ed62017-08-29 15:56:191323 std::make_unique<ElementsUploadDataStream>(std::move(element_readers), 0);
Ryan Hamilton2ef0a9c2017-07-25 03:18:291324 request_.method = "POST";
1325 request_.url = GURL("https://www.example.org/");
1326 request_.upload_data_stream = upload_data_stream_.get();
Bence Békyd8a21fc32018-06-27 18:29:581327 ASSERT_THAT(request_.upload_data_stream->Init(CompletionOnceCallback(),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291328 NetLogWithSource()),
1329 IsOk());
1330
1331 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271332 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
Ryan Hamilton2ef0a9c2017-07-25 03:18:291333 net_log_.bound(), callback_.callback()));
1334 EXPECT_EQ(OK,
1335 stream_->SendRequest(headers_, &response_, callback_.callback()));
1336
1337 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041338 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291339
1340 // Send the response headers (but not the body).
1341 SetResponse("200 OK", string());
1342 size_t spdy_response_headers_frame_length;
1343 ProcessPacket(ConstructResponseHeadersPacket(
1344 2, !kFin, &spdy_response_headers_frame_length));
1345
1346 // The headers have already arrived.
1347 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
1348 ASSERT_TRUE(response_.headers.get());
1349 EXPECT_EQ(200, response_.headers->response_code());
1350 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1351
1352 // Send the response body.
1353 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431354 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Renjief49758b2019-01-11 23:32:411355 ProcessPacket(
Ryan Hamilton7505eb92019-06-08 00:22:171356 ConstructServerDataPacket(3, false, !kFin, header2 + kResponseBody));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291357 // Since the body has already arrived, this should return immediately.
1358 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
1359 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1360 callback_.callback()));
Ryan Hamilton7505eb92019-06-08 00:22:171361 ProcessPacket(ConstructServerDataPacket(4, false, kFin, ""));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291362 EXPECT_EQ(0,
1363 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1364 callback_.callback()));
[email protected]f702d572012-12-04 15:56:201365
1366 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1367 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101368
1369 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451370 // headers and payload.
1371 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411372 strlen(kUploadData) + header.length()),
sclittle1edeeb22015-09-02 20:46:101373 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451374 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411375 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101376 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:201377}
1378
[email protected]1e960032013-12-20 19:00:201379TEST_P(QuicHttpStreamTest, SendChunkedPostRequest) {
1380 SetRequest("POST", "/", DEFAULT_PRIORITY);
[email protected]c9e49a02013-02-26 05:56:471381 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:451382 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:021383 AddWrite(ConstructInitialSettingsPacket());
Victor Vasiliev076657c2019-03-12 02:46:431384 std::string header = ConstructDataHeader(chunk_size);
Nick Harper23290b82019-05-02 00:02:561385 if (version_.transport_version == quic::QUIC_VERSION_99) {
Renjief49758b2019-01-11 23:32:411386 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1387 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
Ryan Hamilton0d65a8c2019-06-07 00:46:021388 !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
1389 {header, kUploadData}));
Ryan Hamilton7505eb92019-06-08 00:22:171390 AddWrite(ConstructClientMultipleDataFramesPacket(3, kIncludeVersion, kFin,
1391 {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411392 } else {
1393 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1394 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
Ryan Hamilton0d65a8c2019-06-07 00:46:021395 !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
1396 {kUploadData}));
Ryan Hamilton7505eb92019-06-08 00:22:171397 AddWrite(ConstructClientDataPacket(3, kIncludeVersion, kFin, kUploadData));
Renjief49758b2019-01-11 23:32:411398 }
1399
Renjie90e808e2019-01-24 07:24:041400 AddWrite(ConstructClientAckPacket(4, 3, 1, 2));
[email protected]c9e49a02013-02-26 05:56:471401 Initialize();
1402
Jeremy Roman0579ed62017-08-29 15:56:191403 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121404 auto* chunked_upload_stream =
1405 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1406 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
[email protected]c9e49a02013-02-26 05:56:471407
1408 request_.method = "POST";
rchcd379012017-04-12 21:53:321409 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121410 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071411 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201412 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]c9e49a02013-02-26 05:56:471413
xunjieli5fafe142016-03-23 23:32:541414 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271415 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541416 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021417 ASSERT_EQ(ERR_IO_PENDING,
1418 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]c9e49a02013-02-26 05:56:471419
rch97827ee2017-05-24 23:49:121420 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
robpercival214763f2016-07-01 23:27:011421 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]c9e49a02013-02-26 05:56:471422
1423 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041424 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]c9e49a02013-02-26 05:56:471425
1426 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071427 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451428 size_t spdy_response_headers_frame_length;
1429 ProcessPacket(ConstructResponseHeadersPacket(
1430 2, !kFin, &spdy_response_headers_frame_length));
[email protected]c9e49a02013-02-26 05:56:471431
rchfb47f712017-05-21 03:24:001432 // The headers have already arrived.
1433 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]cadac622013-06-11 16:46:361434 ASSERT_TRUE(response_.headers.get());
[email protected]c9e49a02013-02-26 05:56:471435 EXPECT_EQ(200, response_.headers->response_code());
1436 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1437
1438 // Send the response body.
1439 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431440 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171441 ProcessPacket(
1442 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
[email protected]c9e49a02013-02-26 05:56:471443
1444 // Since the body has already arrived, this should return immediately.
1445 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1446 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1447 callback_.callback()));
1448
1449 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1450 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101451
1452 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451453 // headers and payload.
1454 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411455 strlen(kUploadData) * 2 + header.length() * 2),
sclittle1edeeb22015-09-02 20:46:101456 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451457 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411458 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101459 stream_->GetTotalReceivedBytes());
[email protected]c9e49a02013-02-26 05:56:471460}
1461
[email protected]16ba7742014-08-22 00:57:251462TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithFinalEmptyDataPacket) {
1463 SetRequest("POST", "/", DEFAULT_PRIORITY);
1464 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:451465 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:021466 AddWrite(ConstructInitialSettingsPacket());
Victor Vasiliev076657c2019-03-12 02:46:431467 std::string header = ConstructDataHeader(chunk_size);
Renjief49758b2019-01-11 23:32:411468
Nick Harper23290b82019-05-02 00:02:561469 if (version_.transport_version != quic::QUIC_VERSION_99) {
Renjief49758b2019-01-11 23:32:411470 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1471 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
Ryan Hamilton0d65a8c2019-06-07 00:46:021472 !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
1473 {kUploadData}));
Renjief49758b2019-01-11 23:32:411474 } else {
1475 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1476 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
Ryan Hamilton0d65a8c2019-06-07 00:46:021477 !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
1478 {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411479 }
Ryan Hamilton7505eb92019-06-08 00:22:171480 AddWrite(ConstructClientDataPacket(3, kIncludeVersion, kFin, ""));
Renjie90e808e2019-01-24 07:24:041481 AddWrite(ConstructClientAckPacket(4, 3, 1, 2));
[email protected]16ba7742014-08-22 00:57:251482 Initialize();
1483
Jeremy Roman0579ed62017-08-29 15:56:191484 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121485 auto* chunked_upload_stream =
1486 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1487 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
[email protected]16ba7742014-08-22 00:57:251488
1489 request_.method = "POST";
rchcd379012017-04-12 21:53:321490 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121491 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071492 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201493 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]16ba7742014-08-22 00:57:251494
xunjieli5fafe142016-03-23 23:32:541495 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271496 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541497 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021498 ASSERT_EQ(ERR_IO_PENDING,
1499 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251500
rch97827ee2017-05-24 23:49:121501 chunked_upload_stream->AppendData(nullptr, 0, true);
robpercival214763f2016-07-01 23:27:011502 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]16ba7742014-08-22 00:57:251503
Renjie90e808e2019-01-24 07:24:041504 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]16ba7742014-08-22 00:57:251505
1506 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071507 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451508 size_t spdy_response_headers_frame_length;
1509 ProcessPacket(ConstructResponseHeadersPacket(
1510 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251511
rchfb47f712017-05-21 03:24:001512 // The headers have already arrived.
1513 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]16ba7742014-08-22 00:57:251514 ASSERT_TRUE(response_.headers.get());
1515 EXPECT_EQ(200, response_.headers->response_code());
1516 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1517
1518 // Send the response body.
1519 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431520 std::string header2 = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171521 ProcessPacket(
1522 ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody));
[email protected]16ba7742014-08-22 00:57:251523
rchb27683c2015-07-29 23:53:501524 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251525 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1526 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1527 callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251528 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1529 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101530
1531 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451532 // headers and payload.
1533 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411534 strlen(kUploadData) + header.length()),
sclittle1edeeb22015-09-02 20:46:101535 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451536 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411537 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101538 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251539}
1540
1541TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithOneEmptyDataPacket) {
1542 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451543 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:021544 AddWrite(ConstructInitialSettingsPacket());
fayang3bcb8b502016-12-07 21:44:371545 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:331546 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, !kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:021547 DEFAULT_PRIORITY, &spdy_request_headers_frame_length));
Ryan Hamilton7505eb92019-06-08 00:22:171548 AddWrite(ConstructClientDataPacket(3, kIncludeVersion, kFin, ""));
Renjie90e808e2019-01-24 07:24:041549 AddWrite(ConstructClientAckPacket(4, 3, 1, 2));
[email protected]16ba7742014-08-22 00:57:251550 Initialize();
1551
Jeremy Roman0579ed62017-08-29 15:56:191552 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121553 auto* chunked_upload_stream =
1554 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
[email protected]16ba7742014-08-22 00:57:251555
1556 request_.method = "POST";
rchcd379012017-04-12 21:53:321557 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121558 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071559 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201560 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]16ba7742014-08-22 00:57:251561
xunjieli5fafe142016-03-23 23:32:541562 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271563 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541564 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021565 ASSERT_EQ(ERR_IO_PENDING,
1566 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251567
rch97827ee2017-05-24 23:49:121568 chunked_upload_stream->AppendData(nullptr, 0, true);
robpercival214763f2016-07-01 23:27:011569 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]16ba7742014-08-22 00:57:251570
Renjie90e808e2019-01-24 07:24:041571 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]16ba7742014-08-22 00:57:251572
1573 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071574 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451575 size_t spdy_response_headers_frame_length;
1576 ProcessPacket(ConstructResponseHeadersPacket(
1577 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251578
rchfb47f712017-05-21 03:24:001579 // The headers have already arrived.
1580 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]16ba7742014-08-22 00:57:251581 ASSERT_TRUE(response_.headers.get());
1582 EXPECT_EQ(200, response_.headers->response_code());
1583 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1584
1585 // Send the response body.
1586 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431587 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171588 ProcessPacket(
1589 ConstructServerDataPacket(3, false, kFin, header + kResponseBody));
[email protected]16ba7742014-08-22 00:57:251590
rchb27683c2015-07-29 23:53:501591 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251592 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1593 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1594 callback_.callback()));
1595
1596 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1597 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101598
1599 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451600 // headers and payload.
1601 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1602 stream_->GetTotalSentBytes());
1603 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411604 strlen(kResponseBody) + header.length()),
sclittle1edeeb22015-09-02 20:46:101605 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251606}
1607
[email protected]1e960032013-12-20 19:00:201608TEST_P(QuicHttpStreamTest, DestroyedEarly) {
1609 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451610 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:021611 AddWrite(ConstructInitialSettingsPacket());
fayang3bcb8b502016-12-07 21:44:371612 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:331613 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:021614 DEFAULT_PRIORITY, &spdy_request_headers_frame_length));
fayang3bcb8b502016-12-07 21:44:371615 AddWrite(ConstructAckAndRstStreamPacket(3));
[email protected]63534512012-12-23 18:49:001616 Initialize();
1617
1618 request_.method = "GET";
rchcd379012017-04-12 21:53:321619 request_.url = GURL("https://www.example.org/");
[email protected]63534512012-12-23 18:49:001620
xunjieli5fafe142016-03-23 23:32:541621 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271622 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541623 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021624 EXPECT_EQ(OK,
1625 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]63534512012-12-23 18:49:001626
1627 // Ack the request.
Renjie90e808e2019-01-24 07:24:041628 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
rchfb47f712017-05-21 03:24:001629 EXPECT_THAT(stream_->ReadResponseHeaders(
1630 base::Bind(&QuicHttpStreamTest::CloseStream,
1631 base::Unretained(this), stream_.get())),
robpercival214763f2016-07-01 23:27:011632 IsError(ERR_IO_PENDING));
[email protected]63534512012-12-23 18:49:001633
1634 // Send the response with a body.
[email protected]1e960032013-12-20 19:00:201635 SetResponse("404 OK", "hello world!");
[email protected]63534512012-12-23 18:49:001636 // In the course of processing this packet, the QuicHttpStream close itself.
rchfb47f712017-05-21 03:24:001637 size_t response_size = 0;
rch1bcfddf22017-06-03 00:26:291638 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin, &response_size));
[email protected]63534512012-12-23 18:49:001639
fdoray92e35a72016-06-10 15:54:551640 base::RunLoop().RunUntilIdle();
rchb27683c2015-07-29 23:53:501641
[email protected]63534512012-12-23 18:49:001642 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101643
1644 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451645 // headers and payload.
1646 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1647 stream_->GetTotalSentBytes());
rchfb47f712017-05-21 03:24:001648 // The stream was closed after receiving the headers.
1649 EXPECT_EQ(static_cast<int64_t>(response_size),
1650 stream_->GetTotalReceivedBytes());
[email protected]63534512012-12-23 18:49:001651}
1652
[email protected]1e960032013-12-20 19:00:201653TEST_P(QuicHttpStreamTest, Priority) {
1654 SetRequest("GET", "/", MEDIUM);
sclittlec4dc1a32015-09-24 00:15:451655 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:021656 AddWrite(ConstructInitialSettingsPacket());
fayang3bcb8b502016-12-07 21:44:371657 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:331658 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:021659 MEDIUM, &spdy_request_headers_frame_length));
[email protected]24e5bc52013-09-18 15:36:581660 Initialize();
1661
1662 request_.method = "GET";
rchcd379012017-04-12 21:53:321663 request_.url = GURL("https://www.example.org/");
[email protected]24e5bc52013-09-18 15:36:581664
Steven Valdezb4ff0412018-01-18 22:39:271665 EXPECT_EQ(OK,
1666 stream_->InitializeStream(&request_, true, MEDIUM, net_log_.bound(),
1667 callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581668
rjshaded5ced072015-12-18 19:26:021669 EXPECT_EQ(OK,
1670 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581671
[email protected]24e5bc52013-09-18 15:36:581672 // Ack the request.
Renjie90e808e2019-01-24 07:24:041673 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011674 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1675 IsError(ERR_IO_PENDING));
[email protected]24e5bc52013-09-18 15:36:581676
1677 // Send the response with a body.
[email protected]1e960032013-12-20 19:00:201678 SetResponse("404 OK", "hello world!");
rchfb47f712017-05-21 03:24:001679 size_t response_size = 0;
1680 ProcessPacket(ConstructResponseHeadersPacket(2, kFin, &response_size));
[email protected]24e5bc52013-09-18 15:36:581681
rchfb47f712017-05-21 03:24:001682 EXPECT_EQ(OK, callback_.WaitForResult());
rchb27683c2015-07-29 23:53:501683
[email protected]24e5bc52013-09-18 15:36:581684 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101685
1686 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451687 // headers and payload.
1688 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1689 stream_->GetTotalSentBytes());
rchfb47f712017-05-21 03:24:001690 EXPECT_EQ(static_cast<int64_t>(response_size),
1691 stream_->GetTotalReceivedBytes());
[email protected]24e5bc52013-09-18 15:36:581692}
1693
xunjieli8dff50b2016-07-22 14:19:061694TEST_P(QuicHttpStreamTest, SessionClosedDuringDoLoop) {
1695 SetRequest("POST", "/", DEFAULT_PRIORITY);
1696 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:021697 AddWrite(ConstructInitialSettingsPacket());
Victor Vasiliev076657c2019-03-12 02:46:431698 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harper23290b82019-05-02 00:02:561699 if (version_.transport_version != quic::QUIC_VERSION_99) {
Renjief49758b2019-01-11 23:32:411700 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1701 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
Ryan Hamilton0d65a8c2019-06-07 00:46:021702 !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
1703 {kUploadData}));
Renjief49758b2019-01-11 23:32:411704 } else {
1705 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1706 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
Ryan Hamilton0d65a8c2019-06-07 00:46:021707 !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
1708 {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411709 }
1710
xunjieli8dff50b2016-07-22 14:19:061711 // Second data write will result in a synchronous failure which will close
1712 // the session.
1713 AddWrite(SYNCHRONOUS, ERR_FAILED);
1714 Initialize();
1715
Jeremy Roman0579ed62017-08-29 15:56:191716 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121717 auto* chunked_upload_stream =
1718 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
xunjieli8dff50b2016-07-22 14:19:061719
1720 request_.method = "POST";
rchcd379012017-04-12 21:53:321721 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121722 request_.upload_data_stream = upload_data_stream_.get();
xunjieli8dff50b2016-07-22 14:19:061723 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201724 TestCompletionCallback().callback(), NetLogWithSource()));
xunjieli8dff50b2016-07-22 14:19:061725
1726 size_t chunk_size = strlen(kUploadData);
rch97827ee2017-05-24 23:49:121727 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
xunjieli8dff50b2016-07-22 14:19:061728 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271729 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli8dff50b2016-07-22 14:19:061730 net_log_.bound(), callback_.callback()));
1731 QuicHttpStream* stream = stream_.get();
1732 DeleteStreamCallback delete_stream_callback(std::move(stream_));
1733 // SendRequest() completes asynchronously after the final chunk is added.
Yixin Wange7ecc472018-03-06 19:00:251734 // Error does not surface yet since packet write is triggered by a packet
1735 // flusher that tries to bundle request body writes.
xunjieli8dff50b2016-07-22 14:19:061736 ASSERT_EQ(ERR_IO_PENDING,
1737 stream->SendRequest(headers_, &response_, callback_.callback()));
rch97827ee2017-05-24 23:49:121738 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
xunjieli8dff50b2016-07-22 14:19:061739 int rv = callback_.WaitForResult();
Yixin Wange7ecc472018-03-06 19:00:251740 EXPECT_EQ(OK, rv);
1741 // Error will be surfaced once an attempt to read the response occurs.
1742 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1743 stream->ReadResponseHeaders(callback_.callback()));
xunjieli8dff50b2016-07-22 14:19:061744}
1745
rtenneti15656ae2016-01-23 03:05:031746TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersComplete) {
1747 SetRequest("POST", "/", DEFAULT_PRIORITY);
Ryan Hamilton0d65a8c2019-06-07 00:46:021748 AddWrite(ConstructInitialSettingsPacket());
rtenneti15656ae2016-01-23 03:05:031749 AddWrite(SYNCHRONOUS, ERR_FAILED);
1750 Initialize();
1751
Jeremy Roman0579ed62017-08-29 15:56:191752 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
Yixin Wange7ecc472018-03-06 19:00:251753 auto* chunked_upload_stream =
1754 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
rtenneti15656ae2016-01-23 03:05:031755
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();
rtenneti15656ae2016-01-23 03:05:031759 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201760 TestCompletionCallback().callback(), NetLogWithSource()));
rtenneti15656ae2016-01-23 03:05:031761
xunjieli5fafe142016-03-23 23:32:541762 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271763 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541764 net_log_.bound(), callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:251765 ASSERT_EQ(ERR_IO_PENDING,
rtenneti15656ae2016-01-23 03:05:031766 stream_->SendRequest(headers_, &response_, callback_.callback()));
mmenkeffff3642017-06-15 17:37:241767
Yixin Wange7ecc472018-03-06 19:00:251768 // Error will be surfaced once |upload_data_stream| triggers the next write.
1769 size_t chunk_size = strlen(kUploadData);
1770 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1771 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR, callback_.WaitForResult());
1772
1773 EXPECT_LE(0, stream_->GetTotalSentBytes());
1774 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1775}
1776
1777TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersCompleteReadResponse) {
1778 SetRequest("POST", "/", DEFAULT_PRIORITY);
Ryan Hamilton0d65a8c2019-06-07 00:46:021779 AddWrite(ConstructInitialSettingsPacket());
Yixin Wange7ecc472018-03-06 19:00:251780 AddWrite(SYNCHRONOUS, ERR_FAILED);
1781 Initialize();
1782
1783 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
1784 auto* chunked_upload_stream =
1785 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1786
1787 request_.method = "POST";
1788 request_.url = GURL("https://www.example.org/");
1789 request_.upload_data_stream = upload_data_stream_.get();
1790
1791 size_t chunk_size = strlen(kUploadData);
1792 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1793
1794 ASSERT_EQ(OK, request_.upload_data_stream->Init(
1795 TestCompletionCallback().callback(), NetLogWithSource()));
1796
1797 ASSERT_EQ(OK,
1798 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1799 net_log_.bound(), callback_.callback()));
1800 ASSERT_EQ(OK,
1801 stream_->SendRequest(headers_, &response_, callback_.callback()));
1802
1803 // Error will be surfaced once an attempt to read the response occurs.
1804 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1805 stream_->ReadResponseHeaders(callback_.callback()));
1806
mmenkeffff3642017-06-15 17:37:241807 EXPECT_LE(0, stream_->GetTotalSentBytes());
1808 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rtenneti15656ae2016-01-23 03:05:031809}
1810
1811TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBodyComplete) {
1812 SetRequest("POST", "/", DEFAULT_PRIORITY);
1813 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:021814 AddWrite(ConstructInitialSettingsPacket());
fayang3bcb8b502016-12-07 21:44:371815 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:331816 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, !kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:021817 DEFAULT_PRIORITY, &spdy_request_headers_frame_length));
rtenneti15656ae2016-01-23 03:05:031818 AddWrite(SYNCHRONOUS, ERR_FAILED);
1819 Initialize();
1820
Jeremy Roman0579ed62017-08-29 15:56:191821 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121822 auto* chunked_upload_stream =
1823 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
rtenneti15656ae2016-01-23 03:05:031824
1825 request_.method = "POST";
rchcd379012017-04-12 21:53:321826 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121827 request_.upload_data_stream = upload_data_stream_.get();
rtenneti15656ae2016-01-23 03:05:031828 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201829 TestCompletionCallback().callback(), NetLogWithSource()));
rtenneti15656ae2016-01-23 03:05:031830
xunjieli5fafe142016-03-23 23:32:541831 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271832 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541833 net_log_.bound(), callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:251834 ASSERT_EQ(ERR_IO_PENDING,
rtenneti15656ae2016-01-23 03:05:031835 stream_->SendRequest(headers_, &response_, callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:251836
1837 size_t chunk_size = strlen(kUploadData);
1838 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1839 // Error does not surface yet since packet write is triggered by a packet
1840 // flusher that tries to bundle request body writes.
1841 ASSERT_EQ(OK, callback_.WaitForResult());
1842 // Error will be surfaced once an attempt to read the response occurs.
1843 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1844 stream_->ReadResponseHeaders(callback_.callback()));
1845
1846 EXPECT_LE(0, stream_->GetTotalSentBytes());
1847 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1848}
1849
1850TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBundledBodyComplete) {
1851 SetRequest("POST", "/", DEFAULT_PRIORITY);
1852 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:021853 AddWrite(ConstructInitialSettingsPacket());
Victor Vasiliev076657c2019-03-12 02:46:431854 std::string header = ConstructDataHeader(strlen(kUploadData));
Nick Harper23290b82019-05-02 00:02:561855 if (version_.transport_version != quic::QUIC_VERSION_99) {
Renjief49758b2019-01-11 23:32:411856 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1857 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
Ryan Hamilton0d65a8c2019-06-07 00:46:021858 !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
1859 {kUploadData}));
Renjief49758b2019-01-11 23:32:411860 } else {
1861 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1862 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
Ryan Hamilton0d65a8c2019-06-07 00:46:021863 !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
1864 {header, kUploadData}));
Renjief49758b2019-01-11 23:32:411865 }
1866
Yixin Wange7ecc472018-03-06 19:00:251867 AddWrite(SYNCHRONOUS, ERR_FAILED);
1868 Initialize();
1869
1870 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
1871 auto* chunked_upload_stream =
1872 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1873
1874 request_.method = "POST";
1875 request_.url = GURL("https://www.example.org/");
1876 request_.upload_data_stream = upload_data_stream_.get();
1877
1878 size_t chunk_size = strlen(kUploadData);
1879 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
1880
1881 ASSERT_EQ(OK, request_.upload_data_stream->Init(
1882 TestCompletionCallback().callback(), NetLogWithSource()));
1883
1884 ASSERT_EQ(OK,
1885 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1886 net_log_.bound(), callback_.callback()));
1887 ASSERT_EQ(ERR_IO_PENDING,
1888 stream_->SendRequest(headers_, &response_, callback_.callback()));
1889
1890 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1891
1892 // Error does not surface yet since packet write is triggered by a packet
1893 // flusher that tries to bundle request body writes.
1894 ASSERT_EQ(OK, callback_.WaitForResult());
1895 // Error will be surfaced once an attempt to read the response occurs.
1896 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1897 stream_->ReadResponseHeaders(callback_.callback()));
1898
1899 EXPECT_LE(0, stream_->GetTotalSentBytes());
1900 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rtenneti15656ae2016-01-23 03:05:031901}
1902
ckrasic3865ee0f2016-02-29 22:04:561903TEST_P(QuicHttpStreamTest, ServerPushGetRequest) {
1904 SetRequest("GET", "/", DEFAULT_PRIORITY);
1905 Initialize();
1906
1907 // Initialize the first stream, for receiving the promise on.
1908 request_.method = "GET";
rchcd379012017-04-12 21:53:321909 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:561910
xunjieli5fafe142016-03-23 23:32:541911 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271912 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541913 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561914
1915 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
1916 // packet, but does it matter?
1917 ReceivePromise(promise_id_);
1918 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
1919
1920 request_.url = GURL(promise_url_);
1921
1922 // Make the second stream that will exercise the first step of the
1923 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:271924 EXPECT_EQ(OK, promised_stream_->InitializeStream(
1925 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
1926 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561927
1928 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:251929 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:561930 size_t spdy_response_headers_frame_length;
1931 ProcessPacket(InnerConstructResponseHeadersPacket(
1932 1, promise_id_, false, &spdy_response_headers_frame_length));
1933
1934 // Receive the promised response body.
1935 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:431936 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:171937 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
1938 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:561939
1940 // Now sending a matching request will have successful rendezvous
1941 // with the promised stream.
Ryan Hamiltona1d1f4a2019-06-26 14:43:041942 ASSERT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
ckrasic3865ee0f2016-02-29 22:04:561943 callback_.callback()));
1944
1945 EXPECT_EQ(
1946 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
1947 ->id(),
1948 promise_id_);
1949
1950 // The headers will be immediately available.
robpercival214763f2016-07-01 23:27:011951 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
1952 IsOk());
ckrasic3865ee0f2016-02-29 22:04:561953
1954 // As will be the body.
1955 EXPECT_EQ(
1956 static_cast<int>(strlen(kResponseBody)),
1957 promised_stream_->ReadResponseBody(
1958 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
1959 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
1960 EXPECT_TRUE(AtEof());
1961
1962 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1963 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1964 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
1965 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411966 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:561967 promised_stream_->GetTotalReceivedBytes());
1968}
1969
1970TEST_P(QuicHttpStreamTest, ServerPushGetRequestSlowResponse) {
1971 SetRequest("GET", "/", DEFAULT_PRIORITY);
1972 Initialize();
1973
1974 // Initialize the first stream, for receiving the promise on.
1975 request_.method = "GET";
rchcd379012017-04-12 21:53:321976 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:561977
xunjieli5fafe142016-03-23 23:32:541978 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271979 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541980 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561981
1982 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
1983 // packet, but does it matter?
1984 ReceivePromise(promise_id_);
1985 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
1986
1987 request_.url = GURL(promise_url_);
1988
1989 // Make the second stream that will exercise the first step of the
1990 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:271991 EXPECT_EQ(OK, promised_stream_->InitializeStream(
1992 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
1993 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561994
1995 // Now sending a matching request will rendezvous with the promised
1996 // stream, but pending secondary validation.
1997 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
1998 headers_, &response_, callback_.callback()));
1999
2000 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252001 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562002 size_t spdy_response_headers_frame_length;
2003 ProcessPacket(InnerConstructResponseHeadersPacket(
2004 1, promise_id_, false, &spdy_response_headers_frame_length));
2005
2006 // Receive the promised response body.
2007 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432008 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172009 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2010 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562011
fdoray92e35a72016-06-10 15:54:552012 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562013
2014 // Rendezvous should have succeeded now, so the promised stream
2015 // should point at our push stream, and we should be able read
2016 // headers and data from it.
robpercival214763f2016-07-01 23:27:012017 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562018
2019 EXPECT_EQ(
2020 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2021 ->id(),
2022 promise_id_);
2023
robpercival214763f2016-07-01 23:27:012024 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2025 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562026
2027 EXPECT_EQ(
2028 static_cast<int>(strlen(kResponseBody)),
2029 promised_stream_->ReadResponseBody(
2030 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2031
2032 // Callback should return
2033 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2034 EXPECT_TRUE(AtEof());
2035
2036 EXPECT_EQ(0, stream_->GetTotalSentBytes());
2037 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2038 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2039 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412040 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562041 promised_stream_->GetTotalReceivedBytes());
2042}
2043
ckrasic2c63f9b2016-08-16 23:54:072044// Verify fix for crbug.com/637349
2045TEST_P(QuicHttpStreamTest, ServerPushCancelHttpStreamBeforeResponse) {
2046 SetRequest("GET", "/", DEFAULT_PRIORITY);
2047 Initialize();
2048
2049 // Initialize the first stream, for receiving the promise on.
2050 request_.method = "GET";
rchcd379012017-04-12 21:53:322051 request_.url = GURL("https://www.example.org/");
ckrasic2c63f9b2016-08-16 23:54:072052
2053 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272054 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
ckrasic2c63f9b2016-08-16 23:54:072055 net_log_.bound(), callback_.callback()));
2056
2057 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2058 // packet, but does it matter?
2059 ReceivePromise(promise_id_);
2060 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2061
2062 request_.url = GURL(promise_url_);
2063
2064 // Make the second stream that will exercise the first step of the
2065 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272066 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2067 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2068 callback_.callback()));
ckrasic2c63f9b2016-08-16 23:54:072069
2070 // Now sending a matching request will rendezvous with the promised
2071 // stream, but pending secondary validation.
2072 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2073 headers_, &response_, callback_.callback()));
2074
2075 base::RunLoop().RunUntilIdle();
2076
2077 // Cause of FinalValidation() crash as per bug.
2078 promised_stream_.reset();
2079
2080 // Receive the promised response headers.
2081 response_headers_ = promised_response_.Clone();
2082 size_t spdy_response_headers_frame_length;
2083 ProcessPacket(InnerConstructResponseHeadersPacket(
2084 1, promise_id_, false, &spdy_response_headers_frame_length));
2085}
2086
ckrasic3865ee0f2016-02-29 22:04:562087TEST_P(QuicHttpStreamTest, ServerPushCrossOriginOK) {
2088 SetRequest("GET", "/", DEFAULT_PRIORITY);
2089 Initialize();
2090
2091 // Initialize the first stream, for receiving the promise on.
2092 request_.method = "GET";
rchcd379012017-04-12 21:53:322093 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562094
xunjieli5fafe142016-03-23 23:32:542095 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272096 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542097 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562098
2099 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2100 // packet, but does it matter?
2101
2102 push_promise_[":authority"] = "mail.example.org";
David Schinazi3f7465c2019-07-12 01:57:052103 promise_url_ =
2104 quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
ckrasic3865ee0f2016-02-29 22:04:562105
2106 ReceivePromise(promise_id_);
2107 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2108
2109 request_.url = GURL(promise_url_);
2110
2111 // Make the second stream that will exercise the first step of the
2112 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272113 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2114 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2115 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562116
2117 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252118 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562119 size_t spdy_response_headers_frame_length;
2120 ProcessPacket(InnerConstructResponseHeadersPacket(
2121 1, promise_id_, false, &spdy_response_headers_frame_length));
2122
2123 // Receive the promised response body.
2124 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432125 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172126 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2127 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562128
2129 // Now sending a matching request will have successful rendezvous
2130 // with the promised stream.
2131 EXPECT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
2132 callback_.callback()));
2133
2134 EXPECT_EQ(
2135 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2136 ->id(),
2137 promise_id_);
2138
2139 // The headers will be immediately available.
robpercival214763f2016-07-01 23:27:012140 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2141 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562142
2143 // As will be the body.
2144 EXPECT_EQ(
2145 static_cast<int>(strlen(kResponseBody)),
2146 promised_stream_->ReadResponseBody(
2147 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2148 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2149 EXPECT_TRUE(AtEof());
2150
2151 EXPECT_EQ(0, stream_->GetTotalSentBytes());
2152 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2153 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2154 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412155 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562156 promised_stream_->GetTotalReceivedBytes());
2157}
2158
2159TEST_P(QuicHttpStreamTest, ServerPushCrossOriginFail) {
2160 SetRequest("GET", "/", DEFAULT_PRIORITY);
2161 Initialize();
2162
2163 // Initialize the first stream, for receiving the promise on.
2164 request_.method = "GET";
rchcd379012017-04-12 21:53:322165 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562166
xunjieli5fafe142016-03-23 23:32:542167 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272168 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542169 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562170
2171 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2172 // packet, but does it matter?
2173 push_promise_[":authority"] = "www.notexample.org";
David Schinazi3f7465c2019-07-12 01:57:052174 promise_url_ =
2175 quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
ckrasic3865ee0f2016-02-29 22:04:562176
2177 ReceivePromise(promise_id_);
2178 // The promise will have been rejected because the cert doesn't
2179 // match.
2180 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
2181}
2182
2183TEST_P(QuicHttpStreamTest, ServerPushVaryCheckOK) {
2184 SetRequest("GET", "/", DEFAULT_PRIORITY);
2185 Initialize();
2186
2187 // Initialize the first stream, for receiving the promise on.
2188 request_.method = "GET";
rchcd379012017-04-12 21:53:322189 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562190
xunjieli5fafe142016-03-23 23:32:542191 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272192 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542193 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562194
2195 push_promise_["accept-encoding"] = "gzip";
ckrasic3865ee0f2016-02-29 22:04:562196
2197 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2198 // packet, but does it matter?
2199 ReceivePromise(promise_id_);
2200 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2201
2202 request_.url = GURL(promise_url_);
2203
2204 // Make the second stream that will exercise the first step of the
2205 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272206 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2207 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2208 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562209
2210 headers_.SetHeader("accept-encoding", "gzip");
2211
2212 // Now sending a matching request will rendezvous with the promised
2213 // stream, but pending secondary validation.
2214 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2215 headers_, &response_, callback_.callback()));
2216
2217 // Receive the promised response headers.
2218 promised_response_["vary"] = "accept-encoding";
bnc94893a72016-06-30 13:45:252219 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562220 size_t spdy_response_headers_frame_length;
2221 ProcessPacket(InnerConstructResponseHeadersPacket(
2222 1, promise_id_, false, &spdy_response_headers_frame_length));
2223
2224 // Receive the promised response body.
2225 const char kResponseBody[] = "Hello world!";
Victor Vasiliev076657c2019-03-12 02:46:432226 std::string header = ConstructDataHeader(strlen(kResponseBody));
Ryan Hamilton7505eb92019-06-08 00:22:172227 ProcessPacket(server_maker_.MakeDataPacket(2, promise_id_, false, kFin,
2228 header + kResponseBody));
ckrasic3865ee0f2016-02-29 22:04:562229
fdoray92e35a72016-06-10 15:54:552230 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562231
2232 // Rendezvous should have succeeded now, so the promised stream
2233 // should point at our push stream, and we should be able read
2234 // headers and data from it.
robpercival214763f2016-07-01 23:27:012235 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562236
2237 EXPECT_EQ(
2238 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2239 ->id(),
2240 promise_id_);
2241
robpercival214763f2016-07-01 23:27:012242 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2243 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562244
2245 EXPECT_EQ(
2246 static_cast<int>(strlen(kResponseBody)),
2247 promised_stream_->ReadResponseBody(
2248 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2249
2250 // Callback should return
2251 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2252 EXPECT_TRUE(AtEof());
2253
2254 EXPECT_EQ(0, stream_->GetTotalSentBytes());
2255 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2256 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2257 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412258 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562259 promised_stream_->GetTotalReceivedBytes());
2260}
2261
2262TEST_P(QuicHttpStreamTest, ServerPushVaryCheckFail) {
2263 SetRequest("GET", "/", DEFAULT_PRIORITY);
2264 request_headers_[":scheme"] = "https";
2265 request_headers_[":path"] = "/bar";
2266 request_headers_["accept-encoding"] = "sdch";
2267
2268 size_t spdy_request_header_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:022269 AddWrite(ConstructInitialSettingsPacket());
Yixin Wangb470bc882018-02-15 18:43:572270
Fan Yangac867502019-01-28 21:10:232271 uint64_t client_packet_number = 2;
Yixin Wangb470bc882018-02-15 18:43:572272 if (client_headers_include_h2_stream_dependency_ &&
Nick Harper23290b82019-05-02 00:02:562273 version_.transport_version >= quic::QUIC_VERSION_43) {
Ryan Hamilton0d65a8c2019-06-07 00:46:022274 AddWrite(ConstructClientPriorityPacket(client_packet_number++,
2275 kIncludeVersion, promise_id_, 0,
2276 DEFAULT_PRIORITY));
Yixin Wangb470bc882018-02-15 18:43:572277 }
Michael Warresabba8b7d2018-07-20 22:50:272278 AddWrite(ConstructClientRstStreamVaryMismatchAndRequestHeadersPacket(
Victor Vasiliev4a6798e2019-03-06 02:26:092279 client_packet_number++,
Nick Harper23290b82019-05-02 00:02:562280 stream_id_ + quic::QuicUtils::StreamIdDelta(version_.transport_version),
2281 !kIncludeVersion, kFin, DEFAULT_PRIORITY, promise_id_,
Ryan Hamilton0d65a8c2019-06-07 00:46:022282 &spdy_request_header_frame_length));
Renjie90e808e2019-01-24 07:24:042283 AddWrite(ConstructClientAckPacket(client_packet_number++, 3, 1, 2));
Yixin Wangb470bc882018-02-15 18:43:572284 AddWrite(ConstructClientRstStreamCancelledPacket(client_packet_number++));
2285
ckrasic3865ee0f2016-02-29 22:04:562286 Initialize();
2287
2288 // Initialize the first stream, for receiving the promise on.
2289 request_.method = "GET";
rchcd379012017-04-12 21:53:322290 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562291
xunjieli5fafe142016-03-23 23:32:542292 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272293 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542294 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562295
2296 push_promise_["accept-encoding"] = "gzip";
ckrasic3865ee0f2016-02-29 22:04:562297
2298 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2299 // packet, but does it matter?
2300 ReceivePromise(promise_id_);
2301 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2302
2303 request_.url = GURL(promise_url_);
2304
2305 // Make the second stream that will exercise the first step of the
2306 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272307 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2308 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2309 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562310
2311 headers_.SetHeader("accept-encoding", "sdch");
2312
2313 // Now sending a matching request will rendezvous with the promised
2314 // stream, but pending secondary validation.
2315 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2316 headers_, &response_, callback_.callback()));
2317
2318 // Receive the promised response headers.
2319 promised_response_["vary"] = "accept-encoding";
bnc94893a72016-06-30 13:45:252320 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562321 size_t spdy_response_headers_frame_length;
2322 ProcessPacket(InnerConstructResponseHeadersPacket(
2323 1, promise_id_, false, &spdy_response_headers_frame_length));
2324
fdoray92e35a72016-06-10 15:54:552325 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562326
2327 // Rendezvous should have failed due to vary mismatch, so the
2328 // promised stream should have been aborted, and instead we have a
2329 // new, regular client initiated stream.
robpercival214763f2016-07-01 23:27:012330 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562331
2332 // Not a server-initiated stream.
2333 EXPECT_NE(
2334 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2335 ->id(),
2336 promise_id_);
2337
2338 // Instead, a new client-initiated stream.
2339 EXPECT_EQ(
2340 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2341 ->id(),
Nick Harper23290b82019-05-02 00:02:562342 stream_id_ + quic::QuicUtils::StreamIdDelta(version_.transport_version));
ckrasic3865ee0f2016-02-29 22:04:562343
2344 // After rendezvous failure, the push stream has been cancelled.
2345 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
2346
2347 // The rest of the test verifies that the retried as
2348 // client-initiated version of |promised_stream_| works as intended.
2349
2350 // Ack the request.
Renjie90e808e2019-01-24 07:24:042351 ProcessPacket(ConstructServerAckPacket(2, 1, 1, 1));
ckrasic3865ee0f2016-02-29 22:04:562352
bnc614a92d32016-04-04 13:56:072353 SetResponse("404 Not Found", string());
ckrasic3865ee0f2016-02-29 22:04:562354 size_t spdy_response_header_frame_length;
2355 ProcessPacket(InnerConstructResponseHeadersPacket(
Nick Harper23290b82019-05-02 00:02:562356 3,
2357 stream_id_ + quic::QuicUtils::StreamIdDelta(version_.transport_version),
2358 kFin, &spdy_response_header_frame_length));
ckrasic3865ee0f2016-02-29 22:04:562359
fdoray92e35a72016-06-10 15:54:552360 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562361
robpercival214763f2016-07-01 23:27:012362 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2363 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562364 ASSERT_TRUE(response_.headers.get());
2365 EXPECT_EQ(404, response_.headers->response_code());
2366 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
2367 EXPECT_FALSE(response_.response_time.is_null());
2368 EXPECT_FALSE(response_.request_time.is_null());
2369
2370 // There is no body, so this should return immediately.
2371 EXPECT_EQ(
2372 0, promised_stream_->ReadResponseBody(
2373 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2374 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2375
2376 stream_->Close(true);
2377
2378 EXPECT_TRUE(AtEof());
2379
2380 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
2381 // headers and payload.
2382 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
2383 promised_stream_->GetTotalSentBytes());
2384 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length),
2385 promised_stream_->GetTotalReceivedBytes());
2386}
2387
maksim.sisov84e20c92016-06-23 08:49:342388TEST_P(QuicHttpStreamTest, DataReadErrorSynchronous) {
2389 SetRequest("POST", "/", DEFAULT_PRIORITY);
2390 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:022391 AddWrite(ConstructInitialSettingsPacket());
Yixin Wange7ecc472018-03-06 19:00:252392 AddWrite(ConstructRequestAndRstPacket(
Fan Yang32c5a112018-12-10 20:06:332393 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, !kFin,
Yixin Wange7ecc472018-03-06 19:00:252394 DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
Ryan Hamiltonb5d4c5a2019-06-21 22:08:412395 quic::QUIC_ERROR_PROCESSING_STREAM));
maksim.sisov84e20c92016-06-23 08:49:342396
2397 Initialize();
2398
Jeremy Roman0579ed62017-08-29 15:56:192399 upload_data_stream_ = std::make_unique<ReadErrorUploadDataStream>(
maksim.sisov84e20c92016-06-23 08:49:342400 ReadErrorUploadDataStream::FailureMode::SYNC);
2401 request_.method = "POST";
rchcd379012017-04-12 21:53:322402 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122403 request_.upload_data_stream = upload_data_stream_.get();
maksim.sisov84e20c92016-06-23 08:49:342404 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202405 TestCompletionCallback().callback(), NetLogWithSource()));
maksim.sisov84e20c92016-06-23 08:49:342406
2407 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272408 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
maksim.sisov84e20c92016-06-23 08:49:342409 net_log_.bound(), callback_.callback()));
2410
2411 int result = stream_->SendRequest(headers_, &response_, callback_.callback());
robpercival214763f2016-07-01 23:27:012412 EXPECT_THAT(result, IsError(ERR_FAILED));
maksim.sisov84e20c92016-06-23 08:49:342413
2414 EXPECT_TRUE(AtEof());
2415
2416 // QuicHttpStream::GetTotalSent/ReceivedBytes includes only headers.
2417 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
2418 stream_->GetTotalSentBytes());
2419 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2420}
2421
2422TEST_P(QuicHttpStreamTest, DataReadErrorAsynchronous) {
2423 SetRequest("POST", "/", DEFAULT_PRIORITY);
2424 size_t spdy_request_headers_frame_length;
Ryan Hamilton0d65a8c2019-06-07 00:46:022425 AddWrite(ConstructInitialSettingsPacket());
fayang3bcb8b502016-12-07 21:44:372426 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:332427 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, !kFin,
Ryan Hamilton0d65a8c2019-06-07 00:46:022428 DEFAULT_PRIORITY, &spdy_request_headers_frame_length));
fayang3bcb8b502016-12-07 21:44:372429 AddWrite(ConstructClientRstStreamErrorPacket(3, !kIncludeVersion));
maksim.sisov84e20c92016-06-23 08:49:342430
2431 Initialize();
2432
Jeremy Roman0579ed62017-08-29 15:56:192433 upload_data_stream_ = std::make_unique<ReadErrorUploadDataStream>(
maksim.sisov84e20c92016-06-23 08:49:342434 ReadErrorUploadDataStream::FailureMode::ASYNC);
2435 request_.method = "POST";
rchcd379012017-04-12 21:53:322436 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122437 request_.upload_data_stream = upload_data_stream_.get();
maksim.sisov84e20c92016-06-23 08:49:342438 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202439 TestCompletionCallback().callback(), NetLogWithSource()));
maksim.sisov84e20c92016-06-23 08:49:342440
2441 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272442 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
maksim.sisov84e20c92016-06-23 08:49:342443 net_log_.bound(), callback_.callback()));
2444
2445 int result = stream_->SendRequest(headers_, &response_, callback_.callback());
2446
Renjie90e808e2019-01-24 07:24:042447 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
maksim.sisov84e20c92016-06-23 08:49:342448 SetResponse("200 OK", string());
2449
robpercival214763f2016-07-01 23:27:012450 EXPECT_THAT(result, IsError(ERR_IO_PENDING));
2451 EXPECT_THAT(callback_.GetResult(result), IsError(ERR_FAILED));
maksim.sisov84e20c92016-06-23 08:49:342452
2453 EXPECT_TRUE(AtEof());
2454
2455 // QuicHttpStream::GetTotalSent/ReceivedBytes includes only headers.
2456 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
2457 stream_->GetTotalSentBytes());
2458 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2459}
2460
[email protected]f702d572012-12-04 15:56:202461} // namespace test
[email protected]f702d572012-12-04 15:56:202462} // namespace net