blob: 1d14ef04e4a48b8c5956cf9107a5a3e45f2b23b0 [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"
Ryan Hamiltona3ee93a72018-08-01 22:03:0832#include "net/quic/crypto/proof_verifier_chromium.h"
33#include "net/quic/mock_crypto_client_stream_factory.h"
34#include "net/quic/quic_chromium_alarm_factory.h"
35#include "net/quic/quic_chromium_connection_helper.h"
36#include "net/quic/quic_chromium_packet_reader.h"
37#include "net/quic/quic_chromium_packet_writer.h"
38#include "net/quic/quic_http_utils.h"
39#include "net/quic/quic_server_info.h"
40#include "net/quic/quic_stream_factory.h"
41#include "net/quic/quic_test_packet_maker.h"
42#include "net/quic/test_task_runner.h"
tbansalca83c002016-04-28 20:56:2843#include "net/socket/socket_performance_watcher.h"
[email protected]f702d572012-12-04 15:56:2044#include "net/socket/socket_test_util.h"
Bence Béky94658bf2018-05-11 19:22:5845#include "net/spdy/spdy_http_utils.h"
rch03b7a202016-02-05 00:54:2046#include "net/test/cert_test_util.h"
robpercival214763f2016-07-01 23:27:0147#include "net/test/gtest_util.h"
rsleevia69c79a2016-06-22 03:28:4348#include "net/test/test_data_directory.h"
Bence Béky98447b12018-05-08 03:14:0149#include "net/test/test_with_scoped_task_environment.h"
Ryan Hamilton56b10c5d2018-05-11 13:40:1650#include "net/third_party/quic/core/congestion_control/send_algorithm_interface.h"
51#include "net/third_party/quic/core/crypto/crypto_protocol.h"
52#include "net/third_party/quic/core/crypto/quic_decrypter.h"
53#include "net/third_party/quic/core/crypto/quic_encrypter.h"
Victor Vasilievc5b409c22018-07-24 12:23:4654#include "net/third_party/quic/core/http/spdy_utils.h"
Ryan Hamilton56b10c5d2018-05-11 13:40:1655#include "net/third_party/quic/core/quic_connection.h"
56#include "net/third_party/quic/core/quic_write_blocked_list.h"
Ryan Hamilton56b10c5d2018-05-11 13:40:1657#include "net/third_party/quic/core/tls_client_handshaker.h"
58#include "net/third_party/quic/platform/api/quic_string_piece.h"
59#include "net/third_party/quic/test_tools/crypto_test_utils.h"
60#include "net/third_party/quic/test_tools/mock_clock.h"
61#include "net/third_party/quic/test_tools/mock_random.h"
62#include "net/third_party/quic/test_tools/quic_connection_peer.h"
63#include "net/third_party/quic/test_tools/quic_spdy_session_peer.h"
64#include "net/third_party/quic/test_tools/quic_test_utils.h"
Victor Vasiliev27cc7712019-01-24 11:50:1465#include "net/third_party/quiche/src/spdy/core/spdy_frame_builder.h"
66#include "net/third_party/quiche/src/spdy/core/spdy_framer.h"
67#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
Ramin Halavati683bcaa92018-02-14 08:42:3968#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
[email protected]f702d572012-12-04 15:56:2069#include "testing/gmock/include/gmock/gmock.h"
70#include "testing/gtest/include/gtest/gtest.h"
71
bnc614a92d32016-04-04 13:56:0772using std::string;
[email protected]f702d572012-12-04 15:56:2073using testing::_;
[email protected]06ff5152013-08-29 01:03:0574using testing::AnyNumber;
75using testing::Return;
[email protected]f702d572012-12-04 15:56:2076
77namespace net {
[email protected]f702d572012-12-04 15:56:2078namespace test {
[email protected]f702d572012-12-04 15:56:2079namespace {
80
[email protected]16ba7742014-08-22 00:57:2581const char kUploadData[] = "Really nifty data!";
rch9ae5b3b2016-02-11 00:36:2982const char kDefaultServerHostName[] = "www.example.org";
rchcd379012017-04-12 21:53:3283const uint16_t kDefaultServerPort = 443;
[email protected]f702d572012-12-04 15:56:2084
Ryan Hamilton8d9ee76e2018-05-29 23:52:5285class TestQuicConnection : public quic::QuicConnection {
[email protected]f702d572012-12-04 15:56:2086 public:
Ryan Hamilton8d9ee76e2018-05-29 23:52:5287 TestQuicConnection(const quic::ParsedQuicVersionVector& versions,
88 quic::QuicConnectionId connection_id,
[email protected]f702d572012-12-04 15:56:2089 IPEndPoint address,
rch12fef552016-01-15 16:26:3190 QuicChromiumConnectionHelper* helper,
rch16c74d1d2016-04-22 06:14:0791 QuicChromiumAlarmFactory* alarm_factory,
Ryan Hamilton8d9ee76e2018-05-29 23:52:5292 quic::QuicPacketWriter* writer)
93 : quic::QuicConnection(
94 connection_id,
95 quic::QuicSocketAddress(quic::QuicSocketAddressImpl(address)),
96 helper,
97 alarm_factory,
98 writer,
99 true /* owns_writer */,
100 quic::Perspective::IS_CLIENT,
101 versions) {}
[email protected]f702d572012-12-04 15:56:20102
Ryan Hamilton8d9ee76e2018-05-29 23:52:52103 void SetSendAlgorithm(quic::SendAlgorithmInterface* send_algorithm) {
104 quic::test::QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
[email protected]f702d572012-12-04 15:56:20105 }
106};
107
maksim.sisov84e20c92016-06-23 08:49:34108// UploadDataStream that always returns errors on data read.
109class ReadErrorUploadDataStream : public UploadDataStream {
110 public:
111 enum class FailureMode { SYNC, ASYNC };
112
113 explicit ReadErrorUploadDataStream(FailureMode mode)
114 : UploadDataStream(true, 0), async_(mode), weak_factory_(this) {}
115 ~ReadErrorUploadDataStream() override {}
116
117 private:
118 void CompleteRead() { UploadDataStream::OnReadCompleted(ERR_FAILED); }
119
120 // UploadDataStream implementation:
tfarina42834112016-09-22 13:38:20121 int InitInternal(const NetLogWithSource& net_log) override { return OK; }
maksim.sisov84e20c92016-06-23 08:49:34122
123 int ReadInternal(IOBuffer* buf, int buf_len) override {
124 if (async_ == FailureMode::ASYNC) {
125 base::ThreadTaskRunnerHandle::Get()->PostTask(
kylecharf4fe5172019-02-15 18:53:49126 FROM_HERE, base::BindOnce(&ReadErrorUploadDataStream::CompleteRead,
127 weak_factory_.GetWeakPtr()));
maksim.sisov84e20c92016-06-23 08:49:34128 return ERR_IO_PENDING;
129 }
130 return ERR_FAILED;
131 }
132
133 void ResetInternal() override {}
134
135 const FailureMode async_;
136
137 base::WeakPtrFactory<ReadErrorUploadDataStream> weak_factory_;
138
139 DISALLOW_COPY_AND_ASSIGN(ReadErrorUploadDataStream);
140};
141
Bence Béky8ddc2492018-06-13 01:02:04142// A helper class that will delete |stream| when the callback is invoked.
xunjieli8dff50b2016-07-22 14:19:06143class DeleteStreamCallback : public TestCompletionCallbackBase {
144 public:
Bence Béky8ddc2492018-06-13 01:02:04145 explicit DeleteStreamCallback(std::unique_ptr<QuicHttpStream> stream)
146 : stream_(std::move(stream)) {}
xunjieli8dff50b2016-07-22 14:19:06147
Bence Béky8ddc2492018-06-13 01:02:04148 CompletionOnceCallback callback() {
149 return base::BindOnce(&DeleteStreamCallback::DeleteStream,
150 base::Unretained(this));
151 }
xunjieli8dff50b2016-07-22 14:19:06152
153 private:
154 void DeleteStream(int result) {
155 stream_.reset();
156 SetResult(result);
157 }
158
159 std::unique_ptr<QuicHttpStream> stream_;
xunjieli8dff50b2016-07-22 14:19:06160};
161
[email protected]f702d572012-12-04 15:56:20162} // namespace
163
[email protected]24e5bc52013-09-18 15:36:58164class QuicHttpStreamPeer {
165 public:
rch08e198572017-05-09 16:56:55166 static QuicChromiumClientStream::Handle* GetQuicChromiumClientStream(
[email protected]24e5bc52013-09-18 15:36:58167 QuicHttpStream* stream) {
rch08e198572017-05-09 16:56:55168 return stream->stream_.get();
[email protected]24e5bc52013-09-18 15:36:58169 }
170};
171
Ryan Hamilton8d9ee76e2018-05-29 23:52:52172class QuicHttpStreamTest : public ::testing::TestWithParam<
173 std::tuple<quic::QuicTransportVersion, bool>>,
174 public WithScopedTaskEnvironment {
rchfb47f712017-05-21 03:24:00175 public:
176 void CloseStream(QuicHttpStream* stream, int /*rv*/) { stream->Close(false); }
177
[email protected]f702d572012-12-04 15:56:20178 protected:
[email protected]1e960032013-12-20 19:00:20179 static const bool kFin = true;
180 static const bool kIncludeVersion = true;
181 static const bool kIncludeCongestionFeedback = true;
182
[email protected]f702d572012-12-04 15:56:20183 // Holds a packet to be written to the wire, and the IO mode that should
184 // be used by the mock socket when performing the write.
185 struct PacketToWrite {
Ryan Hamilton8d9ee76e2018-05-29 23:52:52186 PacketToWrite(IoMode mode, quic::QuicReceivedPacket* packet)
rjshaded5ced072015-12-18 19:26:02187 : mode(mode), packet(packet) {}
rtenneti15656ae2016-01-23 03:05:03188 PacketToWrite(IoMode mode, int rv) : mode(mode), packet(nullptr), rv(rv) {}
[email protected]f702d572012-12-04 15:56:20189 IoMode mode;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52190 quic::QuicReceivedPacket* packet;
rtenneti15656ae2016-01-23 03:05:03191 int rv;
[email protected]f702d572012-12-04 15:56:20192 };
193
194 QuicHttpStreamTest()
Yixin Wang079ad542018-01-11 04:06:05195 : version_(std::get<0>(GetParam())),
196 client_headers_include_h2_stream_dependency_(std::get<1>(GetParam())),
Ryan Hamilton8d9ee76e2018-05-29 23:52:52197 crypto_config_(quic::test::crypto_test_utils::ProofVerifierForTesting(),
198 quic::TlsClientHandshaker::CreateSslCtx()),
Victor Costan9c7302b2018-08-27 16:39:44199 read_buffer_(base::MakeRefCounted<IOBufferWithSize>(4096)),
Fan Yang32c5a112018-12-10 20:06:33200 promise_id_(GetNthServerInitiatedUnidirectionalStreamId(0)),
201 stream_id_(GetNthClientInitiatedBidirectionalStreamId(0)),
David Schinazic8281052019-01-24 06:14:17202 connection_id_(quic::test::TestConnectionId(2)),
Yixin Wang079ad542018-01-11 04:06:05203 client_maker_(version_,
alyssar2adf3ac2016-05-03 17:12:58204 connection_id_,
205 &clock_,
206 kDefaultServerHostName,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52207 quic::Perspective::IS_CLIENT,
Yixin Wang079ad542018-01-11 04:06:05208 client_headers_include_h2_stream_dependency_),
209 server_maker_(version_,
zhongyi5dbfdd42017-06-20 05:22:15210 connection_id_,
alyssar2adf3ac2016-05-03 17:12:58211 &clock_,
212 kDefaultServerHostName,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52213 quic::Perspective::IS_SERVER,
Yixin Wang079ad542018-01-11 04:06:05214 false),
ckrasic3865ee0f2016-02-29 22:04:56215 random_generator_(0),
216 response_offset_(0) {
martijn21968ea2016-02-24 18:46:20217 IPAddress ip(192, 0, 2, 33);
[email protected]f702d572012-12-04 15:56:20218 peer_addr_ = IPEndPoint(ip, 443);
219 self_addr_ = IPEndPoint(ip, 8435);
Ryan Hamilton8d9ee76e2018-05-29 23:52:52220 clock_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(20));
Ramin Halavati683bcaa92018-02-14 08:42:39221 request_.traffic_annotation =
222 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f702d572012-12-04 15:56:20223 }
224
225 ~QuicHttpStreamTest() {
Renjieba55fae2018-09-20 03:05:16226 session_->CloseSessionOnError(ERR_ABORTED, quic::QUIC_INTERNAL_ERROR,
227 quic::ConnectionCloseBehavior::SILENT_CLOSE);
[email protected]f702d572012-12-04 15:56:20228 for (size_t i = 0; i < writes_.size(); i++) {
229 delete writes_[i].packet;
230 }
231 }
232
233 // Adds a packet to the list of expected writes.
Ryan Hamilton8d9ee76e2018-05-29 23:52:52234 void AddWrite(std::unique_ptr<quic::QuicReceivedPacket> packet) {
[email protected]1e960032013-12-20 19:00:20235 writes_.push_back(PacketToWrite(SYNCHRONOUS, packet.release()));
[email protected]f702d572012-12-04 15:56:20236 }
237
rtenneti15656ae2016-01-23 03:05:03238 void AddWrite(IoMode mode, int rv) {
239 writes_.push_back(PacketToWrite(mode, rv));
240 }
241
[email protected]f702d572012-12-04 15:56:20242 // Returns the packet to be written at position |pos|.
Ryan Hamilton8d9ee76e2018-05-29 23:52:52243 quic::QuicReceivedPacket* GetWrite(size_t pos) { return writes_[pos].packet; }
[email protected]f702d572012-12-04 15:56:20244
245 bool AtEof() {
rch37de576c2015-05-17 20:28:17246 return socket_data_->AllReadDataConsumed() &&
247 socket_data_->AllWriteDataConsumed();
[email protected]f702d572012-12-04 15:56:20248 }
249
Ryan Hamilton8d9ee76e2018-05-29 23:52:52250 void ProcessPacket(std::unique_ptr<quic::QuicReceivedPacket> packet) {
fayang91ca2012016-11-22 07:42:46251 connection_->ProcessUdpPacket(
Ryan Hamilton8d9ee76e2018-05-29 23:52:52252 quic::QuicSocketAddress(quic::QuicSocketAddressImpl(self_addr_)),
253 quic::QuicSocketAddress(quic::QuicSocketAddressImpl(peer_addr_)),
254 *packet);
[email protected]f702d572012-12-04 15:56:20255 }
256
257 // Configures the test fixture to use the list of expected writes.
258 void Initialize() {
259 mock_writes_.reset(new MockWrite[writes_.size()]);
260 for (size_t i = 0; i < writes_.size(); i++) {
rtenneti15656ae2016-01-23 03:05:03261 if (writes_[i].packet == nullptr) {
262 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].rv, i);
263 } else {
264 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].packet->data(),
265 writes_[i].packet->length());
266 }
bnc614a92d32016-04-04 13:56:07267 }
[email protected]f702d572012-12-04 15:56:20268
rtennetibe635732014-10-02 22:51:42269 socket_data_.reset(new StaticSocketDataProvider(
Ryan Sleevib8d7ea02018-05-07 20:01:01270 base::span<MockRead>(),
271 base::make_span(mock_writes_.get(), writes_.size())));
[email protected]f702d572012-12-04 15:56:20272
danakjad1777e2016-04-16 00:56:42273 std::unique_ptr<MockUDPClientSocket> socket(new MockUDPClientSocket(
xunjielib53b38c2016-03-24 15:54:36274 socket_data_.get(), net_log_.bound().net_log()));
[email protected]e13201d82012-12-12 05:00:32275 socket->Connect(peer_addr_);
[email protected]f702d572012-12-04 15:56:20276 runner_ = new TestTaskRunner(&clock_);
Ryan Hamilton8d9ee76e2018-05-29 23:52:52277 send_algorithm_ = new quic::test::MockSendAlgorithm();
rch7dd15702015-07-01 18:57:57278 EXPECT_CALL(*send_algorithm_, InRecovery()).WillRepeatedly(Return(false));
279 EXPECT_CALL(*send_algorithm_, InSlowStart()).WillRepeatedly(Return(false));
rjshaded5ced072015-12-18 19:26:02280 EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
Dan Zhangf11470172017-09-18 22:02:09281 .Times(testing::AtLeast(1));
rtenneti44f4a2e2015-08-07 14:00:07282 EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
Ryan Hamilton8d9ee76e2018-05-29 23:52:52283 .WillRepeatedly(Return(quic::kMaxPacketSize));
jokulik0e0a00c32016-06-13 21:51:58284 EXPECT_CALL(*send_algorithm_, PacingRate(_))
Ryan Hamilton8d9ee76e2018-05-29 23:52:52285 .WillRepeatedly(Return(quic::QuicBandwidth::Zero()));
Michael Warres74ee3ce2017-10-09 15:26:37286 EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true));
rtenneti44f4a2e2015-08-07 14:00:07287 EXPECT_CALL(*send_algorithm_, BandwidthEstimate())
Ryan Hamilton8d9ee76e2018-05-29 23:52:52288 .WillRepeatedly(Return(quic::QuicBandwidth::Zero()));
rch1e543ec2015-03-29 07:04:40289 EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(AnyNumber());
rch08cae032017-03-29 00:59:15290 EXPECT_CALL(*send_algorithm_, OnApplicationLimited(_)).Times(AnyNumber());
rch0d5bcf62017-05-24 22:48:45291 EXPECT_CALL(*send_algorithm_, GetCongestionControlType())
292 .Times(AnyNumber());
rch16c74d1d2016-04-22 06:14:07293 helper_.reset(
294 new QuicChromiumConnectionHelper(&clock_, &random_generator_));
295 alarm_factory_.reset(new QuicChromiumAlarmFactory(runner_.get(), &clock_));
296
Michael Warres74ee3ce2017-10-09 15:26:37297 connection_ = new TestQuicConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:52298 quic::test::SupportedVersions(
299 quic::ParsedQuicVersion(quic::PROTOCOL_QUIC_CRYPTO, version_)),
Dan Zhangfefaf5b2017-12-11 17:06:24300 connection_id_, peer_addr_, helper_.get(), alarm_factory_.get(),
Ryan Hamilton9edcf1a2017-11-22 05:55:17301 new QuicChromiumPacketWriter(
302 socket.get(), base::ThreadTaskRunnerHandle::Get().get()));
[email protected]f702d572012-12-04 15:56:20303 connection_->set_visitor(&visitor_);
[email protected]fee17f72013-02-03 07:47:41304 connection_->SetSendAlgorithm(send_algorithm_);
rch03b7a202016-02-05 00:54:20305
306 // Load a certificate that is valid for *.example.org
307 scoped_refptr<X509Certificate> test_cert(
308 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
309 EXPECT_TRUE(test_cert.get());
310
311 verify_details_.cert_verify_result.verified_cert = test_cert;
312 verify_details_.cert_verify_result.is_issued_by_known_root = true;
313 crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details_);
314
xunjieli84adaab2016-09-20 01:12:28315 base::TimeTicks dns_end = base::TimeTicks::Now();
316 base::TimeTicks dns_start = dns_end - base::TimeDelta::FromMilliseconds(1);
ckrasic4f9d88d2015-07-22 22:23:16317 session_.reset(new QuicChromiumClientSession(
xunjielib53b38c2016-03-24 15:54:36318 connection_, std::move(socket),
rtenneti1cd3b162015-09-29 02:58:28319 /*stream_factory=*/nullptr, &crypto_client_stream_factory_, &clock_,
Nick Harper89bc7212018-07-31 19:07:57320 &transport_security_state_, /*ssl_config_service=*/nullptr,
danakjad1777e2016-04-16 00:56:42321 base::WrapUnique(static_cast<QuicServerInfo*>(nullptr)),
Paul Jensen8e3c5d32018-02-19 17:06:33322 QuicSessionKey(kDefaultServerHostName, kDefaultServerPort,
323 PRIVACY_MODE_DISABLED, SocketTag()),
Zhongyi Shi757fcce2018-06-27 05:41:27324 /*require_confirmation=*/false, /*migrate_session_early_v2=*/false,
325 /*migrate_session_on_network_change_v2=*/false,
326 /*default_network=*/NetworkChangeNotifier::kInvalidNetworkHandle,
Zhongyi Shie01f2db2019-02-22 19:53:23327 quic::QuicTime::Delta::FromMilliseconds(
328 kDefaultRetransmittableOnWireTimeoutMillisecs),
Zhongyi Shic16b4102019-02-12 00:37:40329 base::TimeDelta::FromSeconds(kDefaultIdleSessionMigrationPeriodSeconds),
Zhongyi Shi73f23ca872017-12-13 18:37:13330 base::TimeDelta::FromSeconds(kMaxTimeOnNonDefaultNetworkSecs),
Zhongyi Shiee760762018-08-01 00:54:29331 kMaxMigrationsToNonDefaultNetworkOnWriteError,
Zhongyi Shi8b1e43f2017-12-13 20:46:30332 kMaxMigrationsToNonDefaultNetworkOnPathDegrading,
Zhongyi Shi5f587cc2017-11-21 23:24:17333 kQuicYieldAfterPacketsRead,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52334 quic::QuicTime::Delta::FromMilliseconds(
335 kQuicYieldAfterDurationMilliseconds),
Zhongyi Shidbce7f412019-02-01 23:16:29336 /*go_away_on_path_degrading*/ false,
Yixin Wang079ad542018-01-11 04:06:05337 client_headers_include_h2_stream_dependency_, /*cert_verify_flags=*/0,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52338 quic::test::DefaultQuicConfig(), &crypto_config_, "CONNECTION_UNKNOWN",
339 dns_start, dns_end, &push_promise_index_, nullptr,
Zhongyi Shic16b4102019-02-12 00:37:40340 base::DefaultTickClock::GetInstance(),
xunjieli84adaab2016-09-20 01:12:28341 base::ThreadTaskRunnerHandle::Get().get(),
xunjieli5fafe142016-03-23 23:32:54342 /*socket_performance_watcher=*/nullptr, net_log_.bound().net_log()));
rtennetid39bd762015-06-12 01:05:52343 session_->Initialize();
xunjieli100937eb52016-09-15 20:09:37344 TestCompletionCallback callback;
rchf0b18c8a2017-05-05 19:31:57345
rch433bf5f2017-02-14 04:10:47346 session_->CryptoConnect(callback.callback());
Ryan Hamilton6c2a2a82017-12-15 02:06:28347 stream_ = std::make_unique<QuicHttpStream>(
348 session_->CreateHandle(HostPortPair("www.example.org", 443)));
349 promised_stream_ = std::make_unique<QuicHttpStream>(
350 session_->CreateHandle(HostPortPair("www.example.org", 443)));
ckrasic3865ee0f2016-02-29 22:04:56351 push_promise_[":path"] = "/bar";
352 push_promise_[":authority"] = "www.example.org";
353 push_promise_[":version"] = "HTTP/1.1";
354 push_promise_[":method"] = "GET";
355 push_promise_[":scheme"] = "https";
356
357 promised_response_[":status"] = "200 OK";
358 promised_response_[":version"] = "HTTP/1.1";
359 promised_response_["content-type"] = "text/plain";
360
Ryan Hamilton8d9ee76e2018-05-29 23:52:52361 promise_url_ = quic::SpdyUtils::GetPromisedUrlFromHeaders(push_promise_);
[email protected]6cca996b2013-01-25 07:43:36362 }
363
bnc614a92d32016-04-04 13:56:07364 void SetRequest(const string& method,
365 const string& path,
[email protected]1e960032013-12-20 19:00:20366 RequestPriority priority) {
rchcd379012017-04-12 21:53:32367 request_headers_ = client_maker_.GetRequestHeaders(method, "https", path);
[email protected]6cca996b2013-01-25 07:43:36368 }
369
bnc614a92d32016-04-04 13:56:07370 void SetResponse(const string& status, const string& body) {
alyssar2adf3ac2016-05-03 17:12:58371 response_headers_ = server_maker_.GetResponseHeaders(status);
[email protected]92bf17c2014-03-03 21:14:03372 response_data_ = body;
[email protected]6cca996b2013-01-25 07:43:36373 }
[email protected]f702d572012-12-04 15:56:20374
Ryan Hamilton8d9ee76e2018-05-29 23:52:52375 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructDataPacket(
Fan Yangac867502019-01-28 21:10:23376 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52377 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56378 bool should_include_version,
379 bool fin,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52380 quic::QuicStreamOffset offset,
381 quic::QuicStringPiece data,
alyssar2adf3ac2016-05-03 17:12:58382 QuicTestPacketMaker* maker) {
383 return maker->MakeDataPacket(packet_number, stream_id,
ckrasic3865ee0f2016-02-29 22:04:56384 should_include_version, fin, offset, data);
385 }
386
Ryan Hamilton8d9ee76e2018-05-29 23:52:52387 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientDataPacket(
Fan Yangac867502019-01-28 21:10:23388 uint64_t packet_number,
[email protected]e8ff26842013-03-22 21:02:05389 bool should_include_version,
[email protected]f702d572012-12-04 15:56:20390 bool fin,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52391 quic::QuicStreamOffset offset,
392 quic::QuicStringPiece data) {
ckrasic3865ee0f2016-02-29 22:04:56393 return InnerConstructDataPacket(packet_number, stream_id_,
alyssar2adf3ac2016-05-03 17:12:58394 should_include_version, fin, offset, data,
395 &client_maker_);
396 }
397
Renjief49758b2019-01-11 23:32:41398 std::unique_ptr<quic::QuicReceivedPacket>
399 ConstructClientMultipleDataFramesPacket(
Fan Yangac867502019-01-28 21:10:23400 uint64_t packet_number,
Renjief49758b2019-01-11 23:32:41401 bool should_include_version,
402 bool fin,
403 quic::QuicStreamOffset offset,
404 const std::vector<std::string>& data) {
405 return client_maker_.MakeMultipleDataFramesPacket(
406 packet_number, stream_id_, should_include_version, fin, offset, data);
407 }
408
Ryan Hamilton8d9ee76e2018-05-29 23:52:52409 std::unique_ptr<quic::QuicReceivedPacket> ConstructServerDataPacket(
Fan Yangac867502019-01-28 21:10:23410 uint64_t packet_number,
alyssar2adf3ac2016-05-03 17:12:58411 bool should_include_version,
412 bool fin,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52413 quic::QuicStreamOffset offset,
414 quic::QuicStringPiece data) {
alyssar2adf3ac2016-05-03 17:12:58415 return InnerConstructDataPacket(packet_number, stream_id_,
416 should_include_version, fin, offset, data,
417 &server_maker_);
ckrasic3865ee0f2016-02-29 22:04:56418 }
419
Ryan Hamilton8d9ee76e2018-05-29 23:52:52420 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23421 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52422 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56423 bool should_include_version,
424 bool fin,
425 RequestPriority request_priority,
xunjieli100937eb52016-09-15 20:09:37426 size_t* spdy_headers_frame_length,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52427 quic::QuicStreamOffset* offset) {
Yixin Wang7a3f1b8d2018-01-17 21:40:48428 return InnerConstructRequestHeadersPacket(
429 packet_number, stream_id, should_include_version, fin, request_priority,
430 0, spdy_headers_frame_length, offset);
431 }
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,
Yixin Wang7a3f1b8d2018-01-17 21:40:48440 size_t* spdy_headers_frame_length,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52441 quic::QuicStreamOffset* offset) {
Ryan Hamilton0239aac2018-05-19 00:03:13442 spdy::SpdyPriority priority =
ckrasic3865ee0f2016-02-29 22:04:56443 ConvertRequestPriorityToQuicPriority(request_priority);
alyssar2adf3ac2016-05-03 17:12:58444 return client_maker_.MakeRequestHeadersPacket(
ckrasic3865ee0f2016-02-29 22:04:56445 packet_number, stream_id, should_include_version, fin, priority,
Yixin Wang7a3f1b8d2018-01-17 21:40:48446 std::move(request_headers_), parent_stream_id,
447 spdy_headers_frame_length, offset);
[email protected]f702d572012-12-04 15:56:20448 }
449
Ryan Hamilton8d9ee76e2018-05-29 23:52:52450 std::unique_ptr<quic::QuicReceivedPacket>
Yixin Wange7ecc472018-03-06 19:00:25451 ConstructRequestHeadersAndDataFramesPacket(
Fan Yangac867502019-01-28 21:10:23452 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52453 quic::QuicStreamId stream_id,
Yixin Wange7ecc472018-03-06 19:00:25454 bool should_include_version,
455 bool fin,
456 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52457 quic::QuicStreamId parent_stream_id,
458 quic::QuicStreamOffset* offset,
Yixin Wange7ecc472018-03-06 19:00:25459 size_t* spdy_headers_frame_length,
460 const std::vector<std::string>& data_writes) {
Ryan Hamilton0239aac2018-05-19 00:03:13461 spdy::SpdyPriority priority =
Yixin Wange7ecc472018-03-06 19:00:25462 ConvertRequestPriorityToQuicPriority(request_priority);
463 return client_maker_.MakeRequestHeadersAndMultipleDataFramesPacket(
464 packet_number, stream_id, should_include_version, fin, priority,
465 std::move(request_headers_), parent_stream_id, offset,
466 spdy_headers_frame_length, data_writes);
467 }
468
Ryan Hamilton8d9ee76e2018-05-29 23:52:52469 std::unique_ptr<quic::QuicReceivedPacket> ConstructRequestAndRstPacket(
Fan Yangac867502019-01-28 21:10:23470 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52471 quic::QuicStreamId stream_id,
Yixin Wange7ecc472018-03-06 19:00:25472 bool should_include_version,
473 bool fin,
474 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52475 quic::QuicStreamId parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25476 size_t* spdy_headers_frame_length,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52477 quic::QuicStreamOffset* header_stream_offset,
478 quic::QuicRstStreamErrorCode error_code,
Yixin Wange7ecc472018-03-06 19:00:25479 size_t bytes_written) {
Ryan Hamilton0239aac2018-05-19 00:03:13480 spdy::SpdyPriority priority =
Yixin Wange7ecc472018-03-06 19:00:25481 ConvertRequestPriorityToQuicPriority(request_priority);
482 return client_maker_.MakeRequestHeadersAndRstPacket(
483 packet_number, stream_id, should_include_version, fin, priority,
484 std::move(request_headers_), parent_stream_id,
485 spdy_headers_frame_length, header_stream_offset, error_code,
486 bytes_written);
487 }
488
Ryan Hamilton8d9ee76e2018-05-29 23:52:52489 std::unique_ptr<quic::QuicReceivedPacket> ConstructRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23490 uint64_t packet_number,
rtennetif4bdb542015-01-21 14:33:05491 bool fin,
sclittlec4dc1a32015-09-24 00:15:45492 RequestPriority request_priority,
493 size_t* spdy_headers_frame_length) {
ckrasic3865ee0f2016-02-29 22:04:56494 return InnerConstructRequestHeadersPacket(
495 packet_number, stream_id_, kIncludeVersion, fin, request_priority,
xunjieli100937eb52016-09-15 20:09:37496 spdy_headers_frame_length, nullptr);
ckrasic3865ee0f2016-02-29 22:04:56497 }
498
Ryan Hamilton8d9ee76e2018-05-29 23:52:52499 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructResponseHeadersPacket(
Fan Yangac867502019-01-28 21:10:23500 uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52501 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56502 bool fin,
503 size_t* spdy_headers_frame_length) {
alyssar2adf3ac2016-05-03 17:12:58504 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26505 packet_number, stream_id, !kIncludeVersion, fin,
506 std::move(response_headers_), spdy_headers_frame_length,
507 &response_offset_);
[email protected]1e960032013-12-20 19:00:20508 }
509
Ryan Hamilton8d9ee76e2018-05-29 23:52:52510 std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseHeadersPacket(
Fan Yangac867502019-01-28 21:10:23511 uint64_t packet_number,
sclittlec4dc1a32015-09-24 00:15:45512 bool fin,
513 size_t* spdy_headers_frame_length) {
ckrasic3865ee0f2016-02-29 22:04:56514 return InnerConstructResponseHeadersPacket(packet_number, stream_id_, fin,
515 spdy_headers_frame_length);
[email protected]1e960032013-12-20 19:00:20516 }
517
Ryan Hamilton8d9ee76e2018-05-29 23:52:52518 std::unique_ptr<quic::QuicReceivedPacket>
Fan Yangac867502019-01-28 21:10:23519 ConstructResponseHeadersPacketWithOffset(uint64_t packet_number,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52520 bool fin,
521 size_t* spdy_headers_frame_length,
522 quic::QuicStreamOffset* offset) {
alyssar2adf3ac2016-05-03 17:12:58523 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26524 packet_number, stream_id_, !kIncludeVersion, fin,
525 std::move(response_headers_), spdy_headers_frame_length, offset);
xunjieli34291fe12016-03-02 13:58:38526 }
527
Ryan Hamilton8d9ee76e2018-05-29 23:52:52528 std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseTrailersPacket(
Fan Yangac867502019-01-28 21:10:23529 uint64_t packet_number,
xunjieli34291fe12016-03-02 13:58:38530 bool fin,
Ryan Hamilton0239aac2018-05-19 00:03:13531 spdy::SpdyHeaderBlock trailers,
xunjieli34291fe12016-03-02 13:58:38532 size_t* spdy_headers_frame_length,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52533 quic::QuicStreamOffset* offset) {
alyssar2adf3ac2016-05-03 17:12:58534 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26535 packet_number, stream_id_, !kIncludeVersion, fin, std::move(trailers),
alyssar2adf3ac2016-05-03 17:12:58536 spdy_headers_frame_length, offset);
xunjieli34291fe12016-03-02 13:58:38537 }
538
Ryan Hamilton8d9ee76e2018-05-29 23:52:52539 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientRstStreamPacket(
Fan Yangac867502019-01-28 21:10:23540 uint64_t packet_number) {
alyssara72f5352016-10-20 12:45:16541 return client_maker_.MakeRstPacket(packet_number, true, stream_id_,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52542 quic::QUIC_RST_ACKNOWLEDGEMENT);
[email protected]06ff5152013-08-29 01:03:05543 }
544
Ryan Hamilton8d9ee76e2018-05-29 23:52:52545 std::unique_ptr<quic::QuicReceivedPacket>
Fan Yangac867502019-01-28 21:10:23546 ConstructClientRstStreamCancelledPacket(uint64_t packet_number) {
alyssar2adf3ac2016-05-03 17:12:58547 return client_maker_.MakeRstPacket(packet_number, !kIncludeVersion,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52548 stream_id_, quic::QUIC_STREAM_CANCELLED);
rtenneti6bd660b2015-07-18 00:19:53549 }
550
Ryan Hamilton8d9ee76e2018-05-29 23:52:52551 std::unique_ptr<quic::QuicReceivedPacket>
Fan Yangac867502019-01-28 21:10:23552 ConstructClientRstStreamVaryMismatchPacket(uint64_t packet_number) {
alyssar2adf3ac2016-05-03 17:12:58553 return client_maker_.MakeRstPacket(packet_number, !kIncludeVersion,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52554 promise_id_,
555 quic::QUIC_PROMISE_VARY_MISMATCH);
ckrasic3865ee0f2016-02-29 22:04:56556 }
557
Fan Yang550c6282018-06-22 18:53:25558 std::unique_ptr<quic::QuicReceivedPacket>
559 ConstructClientRstStreamVaryMismatchAndRequestHeadersPacket(
Fan Yangac867502019-01-28 21:10:23560 uint64_t packet_number,
Fan Yang550c6282018-06-22 18:53:25561 quic::QuicStreamId stream_id,
562 bool should_include_version,
563 bool fin,
564 RequestPriority request_priority,
565 quic::QuicStreamId parent_stream_id,
566 size_t* spdy_headers_frame_length,
567 quic::QuicStreamOffset* offset) {
568 spdy::SpdyPriority priority =
569 ConvertRequestPriorityToQuicPriority(request_priority);
570 return client_maker_.MakeRstAndRequestHeadersPacket(
571 packet_number, should_include_version, promise_id_,
572 quic::QUIC_PROMISE_VARY_MISMATCH, stream_id, fin, priority,
573 std::move(request_headers_), parent_stream_id,
574 spdy_headers_frame_length, offset);
575 }
576
Ryan Hamilton8d9ee76e2018-05-29 23:52:52577 std::unique_ptr<quic::QuicReceivedPacket> ConstructAckAndRstStreamPacket(
Fan Yangac867502019-01-28 21:10:23578 uint64_t packet_number,
579 uint64_t largest_received,
580 uint64_t smallest_received,
581 uint64_t least_unacked) {
alyssar2adf3ac2016-05-03 17:12:58582 return client_maker_.MakeAckAndRstPacket(
Ryan Hamilton8d9ee76e2018-05-29 23:52:52583 packet_number, !kIncludeVersion, stream_id_,
584 quic::QUIC_STREAM_CANCELLED, largest_received, smallest_received,
585 least_unacked, !kIncludeCongestionFeedback);
xunjieli34291fe12016-03-02 13:58:38586 }
587
Ryan Hamilton8d9ee76e2018-05-29 23:52:52588 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientRstStreamErrorPacket(
Fan Yangac867502019-01-28 21:10:23589 uint64_t packet_number,
maksim.sisov84e20c92016-06-23 08:49:34590 bool include_version) {
591 return client_maker_.MakeRstPacket(packet_number, include_version,
592 stream_id_,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52593 quic::QUIC_ERROR_PROCESSING_STREAM);
maksim.sisov84e20c92016-06-23 08:49:34594 }
595
Ryan Hamilton8d9ee76e2018-05-29 23:52:52596 std::unique_ptr<quic::QuicReceivedPacket> ConstructAckAndRstStreamPacket(
Fan Yangac867502019-01-28 21:10:23597 uint64_t packet_number) {
Renjie90e808e2019-01-24 07:24:04598 return ConstructAckAndRstStreamPacket(packet_number, 2, 1, 2);
[email protected]c5e1aca2014-01-30 04:03:04599 }
600
Ryan Hamilton8d9ee76e2018-05-29 23:52:52601 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientAckPacket(
Fan Yangac867502019-01-28 21:10:23602 uint64_t packet_number,
603 uint64_t largest_received,
604 uint64_t smallest_received,
605 uint64_t least_unacked) {
alyssar2adf3ac2016-05-03 17:12:58606 return client_maker_.MakeAckPacket(packet_number, largest_received,
wangyix6444ffe2017-04-25 17:49:49607 smallest_received, least_unacked,
alyssar2adf3ac2016-05-03 17:12:58608 !kIncludeCongestionFeedback);
609 }
610
Ryan Hamilton8d9ee76e2018-05-29 23:52:52611 std::unique_ptr<quic::QuicReceivedPacket> ConstructServerAckPacket(
Fan Yangac867502019-01-28 21:10:23612 uint64_t packet_number,
613 uint64_t largest_received,
614 uint64_t smallest_received,
615 uint64_t least_unacked) {
alyssar2adf3ac2016-05-03 17:12:58616 return server_maker_.MakeAckPacket(packet_number, largest_received,
wangyix6444ffe2017-04-25 17:49:49617 smallest_received, least_unacked,
alyssar2adf3ac2016-05-03 17:12:58618 !kIncludeCongestionFeedback);
[email protected]63534512012-12-23 18:49:00619 }
620
Ryan Hamilton8d9ee76e2018-05-29 23:52:52621 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientPriorityPacket(
Fan Yangac867502019-01-28 21:10:23622 uint64_t packet_number,
Yixin Wangb470bc882018-02-15 18:43:57623 bool should_include_version,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52624 quic::QuicStreamId id,
625 quic::QuicStreamId parent_stream_id,
Yixin Wangb470bc882018-02-15 18:43:57626 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52627 quic::QuicStreamOffset* header_stream_offset) {
Yixin Wangb470bc882018-02-15 18:43:57628 return client_maker_.MakePriorityPacket(
629 packet_number, should_include_version, id, parent_stream_id,
630 ConvertRequestPriorityToQuicPriority(request_priority),
631 header_stream_offset);
632 }
633
Ryan Hamilton8d9ee76e2018-05-29 23:52:52634 std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket(
635 quic::QuicStreamOffset* offset) {
rch5cb522462017-04-25 20:18:36636 return client_maker_.MakeInitialSettingsPacket(1, offset);
fayang3bcb8b502016-12-07 21:44:37637 }
638
Renjief49758b2019-01-11 23:32:41639 quic::QuicString ConstructDataHeader(size_t body_len) {
640 if (version_ != quic::QUIC_VERSION_99) {
641 return "";
642 }
643 quic::HttpEncoder encoder;
644 std::unique_ptr<char[]> buffer;
645 auto header_length = encoder.SerializeDataFrameHeader(body_len, &buffer);
646 return quic::QuicString(buffer.get(), header_length);
647 }
648
Ryan Hamilton8d9ee76e2018-05-29 23:52:52649 void ReceivePromise(quic::QuicStreamId id) {
650 auto headers = quic::test::AsHeaderList(push_promise_);
rch08e198572017-05-09 16:56:55651 QuicChromiumClientStream::Handle* stream =
ckrasic3865ee0f2016-02-29 22:04:56652 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
ckrasic32b17dcd2016-10-31 06:15:35653 stream->OnPromiseHeaderList(id, headers.uncompressed_header_bytes(),
654 headers);
ckrasic3865ee0f2016-02-29 22:04:56655 }
656
xunjieli84adaab2016-09-20 01:12:28657 void ExpectLoadTimingValid(const LoadTimingInfo& load_timing_info,
xunjieli100937eb52016-09-15 20:09:37658 bool session_reused) {
659 EXPECT_EQ(session_reused, load_timing_info.socket_reused);
xunjieli84adaab2016-09-20 01:12:28660 if (session_reused) {
661 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
662 } else {
663 ExpectConnectTimingHasTimes(
664 load_timing_info.connect_timing,
665 CONNECT_TIMING_HAS_SSL_TIMES | CONNECT_TIMING_HAS_DNS_TIMES);
666 }
667 ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info);
xunjieli100937eb52016-09-15 20:09:37668 }
669
Fan Yang32c5a112018-12-10 20:06:33670 quic::QuicStreamId GetNthClientInitiatedBidirectionalStreamId(int n) {
671 return quic::test::GetNthClientInitiatedBidirectionalStreamId(version_, n);
ckrasicbf2f59c2017-05-04 23:54:36672 }
673
Fan Yang32c5a112018-12-10 20:06:33674 quic::QuicStreamId GetNthServerInitiatedUnidirectionalStreamId(int n) {
675 return quic::test::GetNthServerInitiatedUnidirectionalStreamId(version_, n);
ckrasicbf2f59c2017-05-04 23:54:36676 }
677
Ryan Hamilton8d9ee76e2018-05-29 23:52:52678 const quic::QuicTransportVersion version_;
Yixin Wang079ad542018-01-11 04:06:05679 const bool client_headers_include_h2_stream_dependency_;
680
xunjieli5fafe142016-03-23 23:32:54681 BoundTestNetLog net_log_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52682 quic::test::MockSendAlgorithm* send_algorithm_;
[email protected]f702d572012-12-04 15:56:20683 scoped_refptr<TestTaskRunner> runner_;
danakjad1777e2016-04-16 00:56:42684 std::unique_ptr<MockWrite[]> mock_writes_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52685 quic::MockClock clock_;
[email protected]f702d572012-12-04 15:56:20686 TestQuicConnection* connection_;
danakjad1777e2016-04-16 00:56:42687 std::unique_ptr<QuicChromiumConnectionHelper> helper_;
rch16c74d1d2016-04-22 06:14:07688 std::unique_ptr<QuicChromiumAlarmFactory> alarm_factory_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52689 testing::StrictMock<quic::test::MockQuicConnectionVisitor> visitor_;
rch97827ee2017-05-24 23:49:12690 std::unique_ptr<UploadDataStream> upload_data_stream_;
danakjad1777e2016-04-16 00:56:42691 std::unique_ptr<QuicHttpStream> stream_;
[email protected]5db452202014-08-19 05:22:15692 TransportSecurityState transport_security_state_;
danakjad1777e2016-04-16 00:56:42693 std::unique_ptr<QuicChromiumClientSession> session_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52694 quic::QuicCryptoClientConfig crypto_config_;
[email protected]f702d572012-12-04 15:56:20695 TestCompletionCallback callback_;
696 HttpRequestInfo request_;
697 HttpRequestHeaders headers_;
698 HttpResponseInfo response_;
699 scoped_refptr<IOBufferWithSize> read_buffer_;
Ryan Hamilton0239aac2018-05-19 00:03:13700 spdy::SpdyHeaderBlock request_headers_;
701 spdy::SpdyHeaderBlock response_headers_;
bnc614a92d32016-04-04 13:56:07702 string request_data_;
703 string response_data_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52704 quic::QuicClientPushPromiseIndex push_promise_index_;
[email protected]f702d572012-12-04 15:56:20705
ckrasic3865ee0f2016-02-29 22:04:56706 // For server push testing
danakjad1777e2016-04-16 00:56:42707 std::unique_ptr<QuicHttpStream> promised_stream_;
Ryan Hamilton0239aac2018-05-19 00:03:13708 spdy::SpdyHeaderBlock push_promise_;
709 spdy::SpdyHeaderBlock promised_response_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52710 const quic::QuicStreamId promise_id_;
ckrasic3865ee0f2016-02-29 22:04:56711 string promise_url_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52712 const quic::QuicStreamId stream_id_;
ckrasic3865ee0f2016-02-29 22:04:56713
Ryan Hamilton8d9ee76e2018-05-29 23:52:52714 const quic::QuicConnectionId connection_id_;
alyssar2adf3ac2016-05-03 17:12:58715 QuicTestPacketMaker client_maker_;
716 QuicTestPacketMaker server_maker_;
[email protected]f702d572012-12-04 15:56:20717 IPEndPoint self_addr_;
718 IPEndPoint peer_addr_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52719 quic::test::MockRandom random_generator_;
rch03b7a202016-02-05 00:54:20720 ProofVerifyDetailsChromium verify_details_;
[email protected]e8ff26842013-03-22 21:02:05721 MockCryptoClientStreamFactory crypto_client_stream_factory_;
danakjad1777e2016-04-16 00:56:42722 std::unique_ptr<StaticSocketDataProvider> socket_data_;
[email protected]f702d572012-12-04 15:56:20723 std::vector<PacketToWrite> writes_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52724 quic::QuicStreamOffset response_offset_;
[email protected]f702d572012-12-04 15:56:20725};
726
Victor Costane635086f2019-01-27 05:20:30727INSTANTIATE_TEST_SUITE_P(
Bence Békyce380cb2018-04-26 23:39:55728 VersionIncludeStreamDependencySequence,
Yixin Wang079ad542018-01-11 04:06:05729 QuicHttpStreamTest,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52730 ::testing::Combine(
731 ::testing::ValuesIn(quic::AllSupportedTransportVersions()),
732 ::testing::Bool()));
[email protected]1e960032013-12-20 19:00:20733
734TEST_P(QuicHttpStreamTest, RenewStreamForAuth) {
[email protected]ed3fc15d2013-03-08 18:37:44735 Initialize();
rtennetibe635732014-10-02 22:51:42736 EXPECT_EQ(nullptr, stream_->RenewStreamForAuth());
[email protected]f702d572012-12-04 15:56:20737}
738
mmenkebd84c392015-09-02 14:12:34739TEST_P(QuicHttpStreamTest, CanReuseConnection) {
[email protected]ed3fc15d2013-03-08 18:37:44740 Initialize();
mmenkebd84c392015-09-02 14:12:34741 EXPECT_FALSE(stream_->CanReuseConnection());
[email protected]f702d572012-12-04 15:56:20742}
743
jri231c2972016-03-08 19:50:11744TEST_P(QuicHttpStreamTest, DisableConnectionMigrationForStream) {
Zhongyi Shibb28b1f2018-07-18 02:41:26745 request_.load_flags |= LOAD_DISABLE_CONNECTION_MIGRATION_TO_CELLULAR;
jri231c2972016-03-08 19:50:11746 Initialize();
xunjieli5fafe142016-03-23 23:32:54747 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27748 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:54749 net_log_.bound(), callback_.callback()));
rch08e198572017-05-09 16:56:55750 QuicChromiumClientStream::Handle* client_stream =
jri231c2972016-03-08 19:50:11751 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
Zhongyi Shibb28b1f2018-07-18 02:41:26752 EXPECT_FALSE(client_stream->can_migrate_to_cellular_network());
jri231c2972016-03-08 19:50:11753}
754
[email protected]1e960032013-12-20 19:00:20755TEST_P(QuicHttpStreamTest, GetRequest) {
756 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:45757 size_t spdy_request_header_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52758 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:36759 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:37760 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33761 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
ckrasicbf2f59c2017-05-04 23:54:36762 DEFAULT_PRIORITY, &spdy_request_header_frame_length,
763 &header_stream_offset));
fayang3bcb8b502016-12-07 21:44:37764
[email protected]f702d572012-12-04 15:56:20765 Initialize();
766
767 request_.method = "GET";
rchcd379012017-04-12 21:53:32768 request_.url = GURL("https://www.example.org/");
[email protected]f702d572012-12-04 15:56:20769
xunjieli100937eb52016-09-15 20:09:37770 // Make sure getting load timing from the stream early does not crash.
771 LoadTimingInfo load_timing_info;
772 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
773
xunjieli5fafe142016-03-23 23:32:54774 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27775 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:54776 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:02777 EXPECT_EQ(OK,
778 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20779
780 // Ack the request.
Renjie90e808e2019-01-24 07:24:04781 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]f702d572012-12-04 15:56:20782
robpercival214763f2016-07-01 23:27:01783 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
784 IsError(ERR_IO_PENDING));
[email protected]f702d572012-12-04 15:56:20785
bnc614a92d32016-04-04 13:56:07786 SetResponse("404 Not Found", string());
sclittlec4dc1a32015-09-24 00:15:45787 size_t spdy_response_header_frame_length;
788 ProcessPacket(ConstructResponseHeadersPacket(
789 2, kFin, &spdy_response_header_frame_length));
[email protected]f702d572012-12-04 15:56:20790
791 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:01792 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]cadac622013-06-11 16:46:36793 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:20794 EXPECT_EQ(404, response_.headers->response_code());
795 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
[email protected]6ed67432014-06-24 01:53:53796 EXPECT_FALSE(response_.response_time.is_null());
797 EXPECT_FALSE(response_.request_time.is_null());
[email protected]f702d572012-12-04 15:56:20798
799 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:02800 EXPECT_EQ(0,
801 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
802 callback_.callback()));
[email protected]f702d572012-12-04 15:56:20803 EXPECT_TRUE(stream_->IsResponseBodyComplete());
804 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:10805
xunjieli100937eb52016-09-15 20:09:37806 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
xunjieli84adaab2016-09-20 01:12:28807 ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
xunjieli100937eb52016-09-15 20:09:37808
sclittle1edeeb22015-09-02 20:46:10809 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:45810 // headers and payload.
811 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
812 stream_->GetTotalSentBytes());
813 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length),
814 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:20815}
816
xunjieli100937eb52016-09-15 20:09:37817TEST_P(QuicHttpStreamTest, LoadTimingTwoRequests) {
818 SetRequest("GET", "/", DEFAULT_PRIORITY);
819 size_t spdy_request_header_frame_length;
820
Ryan Hamilton8d9ee76e2018-05-29 23:52:52821 quic::QuicStreamOffset offset = 0;
rch5cb522462017-04-25 20:18:36822 AddWrite(ConstructInitialSettingsPacket(&offset));
xunjieli100937eb52016-09-15 20:09:37823 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33824 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
ckrasicbf2f59c2017-05-04 23:54:36825 DEFAULT_PRIORITY, &spdy_request_header_frame_length, &offset));
xunjieli100937eb52016-09-15 20:09:37826
827 // SetRequest() again for second request as |request_headers_| was moved.
828 SetRequest("GET", "/", DEFAULT_PRIORITY);
829 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33830 3, GetNthClientInitiatedBidirectionalStreamId(1), kIncludeVersion, kFin,
831 DEFAULT_PRIORITY, GetNthClientInitiatedBidirectionalStreamId(0),
Yixin Wang7a3f1b8d2018-01-17 21:40:48832 &spdy_request_header_frame_length, &offset));
Renjie90e808e2019-01-24 07:24:04833 AddWrite(ConstructClientAckPacket(4, 3, 1, 2)); // Ack the responses.
xunjieli100937eb52016-09-15 20:09:37834
835 Initialize();
836
837 request_.method = "GET";
rchcd379012017-04-12 21:53:32838 request_.url = GURL("https://www.example.org/");
xunjieli100937eb52016-09-15 20:09:37839 // Start first request.
840 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27841 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli100937eb52016-09-15 20:09:37842 net_log_.bound(), callback_.callback()));
843 EXPECT_EQ(OK,
844 stream_->SendRequest(headers_, &response_, callback_.callback()));
845
846 // Start a second request.
Ryan Hamilton6c2a2a82017-12-15 02:06:28847 QuicHttpStream stream2(
848 session_->CreateHandle(HostPortPair("www.example.org", 443)));
xunjieli100937eb52016-09-15 20:09:37849 TestCompletionCallback callback2;
850 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27851 stream2.InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli100937eb52016-09-15 20:09:37852 net_log_.bound(), callback2.callback()));
853 EXPECT_EQ(OK,
854 stream2.SendRequest(headers_, &response_, callback2.callback()));
855
856 // Ack both requests.
Renjie90e808e2019-01-24 07:24:04857 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
xunjieli100937eb52016-09-15 20:09:37858
859 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
860 IsError(ERR_IO_PENDING));
861 size_t spdy_response_header_frame_length;
862 SetResponse("200 OK", string());
863 ProcessPacket(InnerConstructResponseHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33864 2, GetNthClientInitiatedBidirectionalStreamId(0), kFin,
ckrasicbf2f59c2017-05-04 23:54:36865 &spdy_response_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37866
867 // Now that the headers have been processed, the callback will return.
868 EXPECT_THAT(callback_.WaitForResult(), IsOk());
869 EXPECT_EQ(200, response_.headers->response_code());
870
871 // There is no body, so this should return immediately.
872 EXPECT_EQ(0,
873 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
874 callback_.callback()));
875 EXPECT_TRUE(stream_->IsResponseBodyComplete());
876
877 LoadTimingInfo load_timing_info;
878 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
xunjieli84adaab2016-09-20 01:12:28879 ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
xunjieli100937eb52016-09-15 20:09:37880
881 // SetResponse() again for second request as |response_headers_| was moved.
882 SetResponse("200 OK", string());
883 EXPECT_THAT(stream2.ReadResponseHeaders(callback2.callback()),
884 IsError(ERR_IO_PENDING));
885
886 ProcessPacket(InnerConstructResponseHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33887 3, GetNthClientInitiatedBidirectionalStreamId(1), kFin,
ckrasicbf2f59c2017-05-04 23:54:36888 &spdy_response_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37889
890 EXPECT_THAT(callback2.WaitForResult(), IsOk());
891
892 // There is no body, so this should return immediately.
893 EXPECT_EQ(0,
894 stream2.ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
895 callback2.callback()));
896 EXPECT_TRUE(stream2.IsResponseBodyComplete());
897
898 LoadTimingInfo load_timing_info2;
899 EXPECT_TRUE(stream2.GetLoadTimingInfo(&load_timing_info2));
xunjieli84adaab2016-09-20 01:12:28900 ExpectLoadTimingValid(load_timing_info2, /*session_reused=*/true);
xunjieli100937eb52016-09-15 20:09:37901}
902
xunjieli34291fe12016-03-02 13:58:38903// QuicHttpStream does not currently support trailers. It should ignore
904// trailers upon receiving them.
905TEST_P(QuicHttpStreamTest, GetRequestWithTrailers) {
906 SetRequest("GET", "/", DEFAULT_PRIORITY);
907 size_t spdy_request_header_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52908 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:36909 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:37910 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:33911 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
ckrasicbf2f59c2017-05-04 23:54:36912 DEFAULT_PRIORITY, &spdy_request_header_frame_length,
913 &header_stream_offset));
Renjie90e808e2019-01-24 07:24:04914 AddWrite(ConstructClientAckPacket(3, 3, 1, 2)); // Ack the data packet.
xunjieli34291fe12016-03-02 13:58:38915
916 Initialize();
917
918 request_.method = "GET";
rchcd379012017-04-12 21:53:32919 request_.url = GURL("https://www.example.org/");
xunjieli34291fe12016-03-02 13:58:38920
xunjieli5fafe142016-03-23 23:32:54921 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27922 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:54923 net_log_.bound(), callback_.callback()));
924
xunjieli34291fe12016-03-02 13:58:38925 EXPECT_EQ(OK,
926 stream_->SendRequest(headers_, &response_, callback_.callback()));
xunjieli34291fe12016-03-02 13:58:38927 // Ack the request.
Renjie90e808e2019-01-24 07:24:04928 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
xunjieli34291fe12016-03-02 13:58:38929
robpercival214763f2016-07-01 23:27:01930 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
931 IsError(ERR_IO_PENDING));
xunjieli34291fe12016-03-02 13:58:38932
bnc614a92d32016-04-04 13:56:07933 SetResponse("200 OK", string());
xunjieli34291fe12016-03-02 13:58:38934
935 // Send the response headers.
936 size_t spdy_response_header_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52937 quic::QuicStreamOffset offset = 0;
xunjieli34291fe12016-03-02 13:58:38938 ProcessPacket(ConstructResponseHeadersPacketWithOffset(
939 2, !kFin, &spdy_response_header_frame_length, &offset));
940 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:01941 EXPECT_THAT(callback_.WaitForResult(), IsOk());
xunjieli34291fe12016-03-02 13:58:38942 ASSERT_TRUE(response_.headers.get());
943 EXPECT_EQ(200, response_.headers->response_code());
944 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
945 EXPECT_FALSE(response_.response_time.is_null());
946 EXPECT_FALSE(response_.request_time.is_null());
947
948 // Send the response body.
949 const char kResponseBody[] = "Hello world!";
Renjief49758b2019-01-11 23:32:41950 quic::QuicString header = ConstructDataHeader(strlen(kResponseBody));
951 ProcessPacket(ConstructServerDataPacket(3, false, !kFin, /*offset=*/0,
952 header + kResponseBody));
Ryan Hamilton0239aac2018-05-19 00:03:13953 spdy::SpdyHeaderBlock trailers;
xunjieli34291fe12016-03-02 13:58:38954 size_t spdy_trailers_frame_length;
955 trailers["foo"] = "bar";
Ryan Hamilton8d9ee76e2018-05-29 23:52:52956 trailers[quic::kFinalOffsetHeaderKey] =
Raul Tambre8c1981d2019-02-08 02:22:26957 base::NumberToString(strlen(kResponseBody) + header.length());
xunjieli34291fe12016-03-02 13:58:38958 ProcessPacket(ConstructResponseTrailersPacket(
bnc086b39e12016-06-24 13:05:26959 4, kFin, std::move(trailers), &spdy_trailers_frame_length, &offset));
xunjieli34291fe12016-03-02 13:58:38960
961 // Make sure trailers are processed.
fdoray92e35a72016-06-10 15:54:55962 base::RunLoop().RunUntilIdle();
xunjieli34291fe12016-03-02 13:58:38963
964 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
965 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
966 callback_.callback()));
967 EXPECT_TRUE(stream_->IsResponseBodyComplete());
968
969 EXPECT_EQ(OK,
970 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
971 callback_.callback()));
972
973 EXPECT_TRUE(stream_->IsResponseBodyComplete());
974 EXPECT_TRUE(AtEof());
975
976 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
977 // headers and payload.
978 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
979 stream_->GetTotalSentBytes());
Renjief49758b2019-01-11 23:32:41980 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length +
981 strlen(kResponseBody) + header.length() +
982 +spdy_trailers_frame_length),
983 stream_->GetTotalReceivedBytes());
xunjieli5fafe142016-03-23 23:32:54984 // Check that NetLog was filled as expected.
985 TestNetLogEntry::List entries;
986 net_log_.GetEntries(&entries);
987 size_t pos = ExpectLogContainsSomewhere(
988 entries, /*min_offset=*/0,
mikecirone8b85c432016-09-08 19:11:00989 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
990 NetLogEventPhase::NONE);
xunjieli5fafe142016-03-23 23:32:54991 pos = ExpectLogContainsSomewhere(
992 entries, /*min_offset=*/pos,
mikecirone8b85c432016-09-08 19:11:00993 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
994 NetLogEventPhase::NONE);
xunjieli5fafe142016-03-23 23:32:54995 ExpectLogContainsSomewhere(
996 entries, /*min_offset=*/pos,
mikecirone8b85c432016-09-08 19:11:00997 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
998 NetLogEventPhase::NONE);
xunjieli34291fe12016-03-02 13:58:38999}
1000
[email protected]3e7dca62013-09-10 16:14:231001// Regression test for http://crbug.com/288128
[email protected]1e960032013-12-20 19:00:201002TEST_P(QuicHttpStreamTest, GetRequestLargeResponse) {
1003 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451004 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521005 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361006 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:371007 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:331008 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
ckrasicbf2f59c2017-05-04 23:54:361009 DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
1010 &header_stream_offset));
[email protected]3e7dca62013-09-10 16:14:231011 Initialize();
1012
1013 request_.method = "GET";
rchcd379012017-04-12 21:53:321014 request_.url = GURL("https://www.example.org/");
[email protected]3e7dca62013-09-10 16:14:231015
xunjieli5fafe142016-03-23 23:32:541016 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271017 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541018 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021019 EXPECT_EQ(OK,
1020 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:231021
1022 // Ack the request.
Renjie90e808e2019-01-24 07:24:041023 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]3e7dca62013-09-10 16:14:231024
robpercival214763f2016-07-01 23:27:011025 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1026 IsError(ERR_IO_PENDING));
[email protected]3e7dca62013-09-10 16:14:231027
bnc086b39e12016-06-24 13:05:261028 response_headers_[":status"] = "200 OK";
1029 response_headers_[":version"] = "HTTP/1.1";
1030 response_headers_["content-type"] = "text/plain";
1031 response_headers_["big6"] = string(1000, 'x'); // Lots of x's.
[email protected]3e7dca62013-09-10 16:14:231032
sclittlec4dc1a32015-09-24 00:15:451033 size_t spdy_response_headers_frame_length;
1034 ProcessPacket(ConstructResponseHeadersPacket(
1035 2, kFin, &spdy_response_headers_frame_length));
[email protected]3e7dca62013-09-10 16:14:231036
1037 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:011038 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]3e7dca62013-09-10 16:14:231039 ASSERT_TRUE(response_.headers.get());
1040 EXPECT_EQ(200, response_.headers->response_code());
1041 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1042
1043 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:021044 EXPECT_EQ(0,
1045 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1046 callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:231047 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1048 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101049
1050 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451051 // headers and payload.
1052 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1053 stream_->GetTotalSentBytes());
1054 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length),
1055 stream_->GetTotalReceivedBytes());
[email protected]3e7dca62013-09-10 16:14:231056}
1057
rchf9f103cbc2014-08-30 05:28:041058// Regression test for http://crbug.com/409101
1059TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendRequest) {
1060 SetRequest("GET", "/", DEFAULT_PRIORITY);
1061 Initialize();
1062
1063 request_.method = "GET";
rchcd379012017-04-12 21:53:321064 request_.url = GURL("https://www.example.org/");
rchf9f103cbc2014-08-30 05:28:041065
xunjieli5fafe142016-03-23 23:32:541066 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271067 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541068 net_log_.bound(), callback_.callback()));
rchf9f103cbc2014-08-30 05:28:041069
jri78ec06a2016-03-31 18:19:401070 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521071 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rchf9f103cbc2014-08-30 05:28:041072
1073 EXPECT_EQ(ERR_CONNECTION_CLOSED,
rjshaded5ced072015-12-18 19:26:021074 stream_->SendRequest(headers_, &response_, callback_.callback()));
sclittle1edeeb22015-09-02 20:46:101075
1076 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1077 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rchf9f103cbc2014-08-30 05:28:041078}
1079
rch03b7a202016-02-05 00:54:201080// Regression test for http://crbug.com/584441
1081TEST_P(QuicHttpStreamTest, GetSSLInfoAfterSessionClosed) {
1082 SetRequest("GET", "/", DEFAULT_PRIORITY);
1083 Initialize();
1084
1085 request_.method = "GET";
rchcd379012017-04-12 21:53:321086 request_.url = GURL("https://www.example.org/");
rch03b7a202016-02-05 00:54:201087
xunjieli5fafe142016-03-23 23:32:541088 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271089 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541090 net_log_.bound(), callback_.callback()));
rch03b7a202016-02-05 00:54:201091
1092 SSLInfo ssl_info;
rch11565e02016-02-09 20:13:471093 EXPECT_FALSE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:201094 stream_->GetSSLInfo(&ssl_info);
rch11565e02016-02-09 20:13:471095 EXPECT_TRUE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:201096
jri78ec06a2016-03-31 18:19:401097 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521098 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rch03b7a202016-02-05 00:54:201099
rch11565e02016-02-09 20:13:471100 SSLInfo ssl_info2;
1101 stream_->GetSSLInfo(&ssl_info2);
1102 EXPECT_TRUE(ssl_info2.is_valid());
rch03b7a202016-02-05 00:54:201103}
1104
rchcd379012017-04-12 21:53:321105TEST_P(QuicHttpStreamTest, GetAlternativeService) {
1106 SetRequest("GET", "/", DEFAULT_PRIORITY);
1107 Initialize();
1108
1109 request_.method = "GET";
1110 request_.url = GURL("https://www.example.org/");
1111
1112 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271113 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
rchcd379012017-04-12 21:53:321114 net_log_.bound(), callback_.callback()));
1115
1116 AlternativeService alternative_service;
1117 EXPECT_TRUE(stream_->GetAlternativeService(&alternative_service));
1118 EXPECT_EQ(AlternativeService(kProtoQUIC, "www.example.org", 443),
1119 alternative_service);
1120
1121 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521122 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rchcd379012017-04-12 21:53:321123
1124 AlternativeService alternative_service2;
1125 EXPECT_TRUE(stream_->GetAlternativeService(&alternative_service2));
1126 EXPECT_EQ(AlternativeService(kProtoQUIC, "www.example.org", 443),
1127 alternative_service2);
1128}
1129
zhongyica364fbb2015-12-12 03:39:121130TEST_P(QuicHttpStreamTest, LogGranularQuicConnectionError) {
1131 SetRequest("GET", "/", DEFAULT_PRIORITY);
1132 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521133 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361134 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:371135 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:331136 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
ckrasicbf2f59c2017-05-04 23:54:361137 DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
1138 &header_stream_offset));
fayang3bcb8b502016-12-07 21:44:371139 AddWrite(ConstructAckAndRstStreamPacket(3));
zhongyica364fbb2015-12-12 03:39:121140 Initialize();
1141
1142 request_.method = "GET";
rchcd379012017-04-12 21:53:321143 request_.url = GURL("https://www.example.org/");
zhongyica364fbb2015-12-12 03:39:121144
xunjieli5fafe142016-03-23 23:32:541145 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271146 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541147 net_log_.bound(), callback_.callback()));
zhongyica364fbb2015-12-12 03:39:121148 EXPECT_EQ(OK,
1149 stream_->SendRequest(headers_, &response_, callback_.callback()));
1150
1151 // Ack the request.
Renjie90e808e2019-01-24 07:24:041152 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011153 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1154 IsError(ERR_IO_PENDING));
zhongyica364fbb2015-12-12 03:39:121155
Ryan Hamilton8d9ee76e2018-05-29 23:52:521156 quic::QuicConnectionCloseFrame frame;
1157 frame.error_code = quic::QUIC_PEER_GOING_AWAY;
rch1c5b74a2016-06-23 22:10:551158 session_->connection()->OnConnectionCloseFrame(frame);
zhongyica364fbb2015-12-12 03:39:121159
1160 NetErrorDetails details;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521161 EXPECT_EQ(quic::QUIC_NO_ERROR, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121162 stream_->PopulateNetErrorDetails(&details);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521163 EXPECT_EQ(quic::QUIC_PEER_GOING_AWAY, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121164}
1165
Ryan Hamiltone316e482017-08-17 02:48:531166TEST_P(QuicHttpStreamTest, LogGranularQuicErrorIfHandshakeNotConfirmed) {
rch617e0652017-04-26 17:57:511167 // By default the test setup defaults handshake to be confirmed. Manually set
1168 // it to be not confirmed.
rch617e0652017-04-26 17:57:511169 crypto_client_stream_factory_.set_handshake_mode(
Ryan Hamilton9835e662018-08-02 05:36:271170 MockCryptoClientStream::ZERO_RTT);
rch617e0652017-04-26 17:57:511171
zhongyica364fbb2015-12-12 03:39:121172 SetRequest("GET", "/", DEFAULT_PRIORITY);
1173 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521174 quic::QuicStreamOffset header_stream_offset = 0;
1175 client_maker_.SetEncryptionLevel(quic::ENCRYPTION_INITIAL);
1176 client_maker_.SetLongHeaderType(quic::ZERO_RTT_PROTECTED);
fayang3bcb8b502016-12-07 21:44:371177 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:331178 1, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
ckrasicbf2f59c2017-05-04 23:54:361179 DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
1180 &header_stream_offset));
zhongyica364fbb2015-12-12 03:39:121181 Initialize();
1182
1183 request_.method = "GET";
rchcd379012017-04-12 21:53:321184 request_.url = GURL("https://www.example.org/");
zhongyica364fbb2015-12-12 03:39:121185
xunjieli5fafe142016-03-23 23:32:541186 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271187 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541188 net_log_.bound(), callback_.callback()));
zhongyica364fbb2015-12-12 03:39:121189 EXPECT_EQ(OK,
1190 stream_->SendRequest(headers_, &response_, callback_.callback()));
1191
1192 // Ack the request.
Renjie90e808e2019-01-24 07:24:041193 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011194 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1195 IsError(ERR_IO_PENDING));
zhongyica364fbb2015-12-12 03:39:121196
Ryan Hamilton8d9ee76e2018-05-29 23:52:521197 quic::QuicConnectionCloseFrame frame;
1198 frame.error_code = quic::QUIC_PEER_GOING_AWAY;
rch1c5b74a2016-06-23 22:10:551199 session_->connection()->OnConnectionCloseFrame(frame);
zhongyica364fbb2015-12-12 03:39:121200
1201 NetErrorDetails details;
zhongyica364fbb2015-12-12 03:39:121202 stream_->PopulateNetErrorDetails(&details);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521203 EXPECT_EQ(quic::QUIC_PEER_GOING_AWAY, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121204}
1205
rch11a114a2014-09-04 23:41:591206// Regression test for http://crbug.com/409871
1207TEST_P(QuicHttpStreamTest, SessionClosedBeforeReadResponseHeaders) {
1208 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451209 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521210 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361211 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:371212 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:331213 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
ckrasicbf2f59c2017-05-04 23:54:361214 DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
1215 &header_stream_offset));
rch11a114a2014-09-04 23:41:591216 Initialize();
1217
1218 request_.method = "GET";
rchcd379012017-04-12 21:53:321219 request_.url = GURL("https://www.example.org/");
rch11a114a2014-09-04 23:41:591220
xunjieli5fafe142016-03-23 23:32:541221 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271222 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541223 net_log_.bound(), callback_.callback()));
rch11a114a2014-09-04 23:41:591224
rjshaded5ced072015-12-18 19:26:021225 EXPECT_EQ(OK,
1226 stream_->SendRequest(headers_, &response_, callback_.callback()));
rch11a114a2014-09-04 23:41:591227
jri78ec06a2016-03-31 18:19:401228 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521229 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rch11a114a2014-09-04 23:41:591230
1231 EXPECT_NE(OK, stream_->ReadResponseHeaders(callback_.callback()));
sclittle1edeeb22015-09-02 20:46:101232
1233 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451234 // headers and payload.
1235 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1236 stream_->GetTotalSentBytes());
sclittle1edeeb22015-09-02 20:46:101237 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rch11a114a2014-09-04 23:41:591238}
1239
[email protected]1e960032013-12-20 19:00:201240TEST_P(QuicHttpStreamTest, SendPostRequest) {
1241 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451242 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521243 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361244 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
Yixin Wange7ecc472018-03-06 19:00:251245
Renjief49758b2019-01-11 23:32:411246 quic::QuicString header = ConstructDataHeader(strlen(kUploadData));
1247 if (version_ != quic::QUIC_VERSION_99) {
1248 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1249 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
1250 DEFAULT_PRIORITY, 0, &header_stream_offset,
1251 &spdy_request_headers_frame_length, {kUploadData}));
1252 } else {
1253 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1254 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
1255 DEFAULT_PRIORITY, 0, &header_stream_offset,
1256 &spdy_request_headers_frame_length, {header, kUploadData}));
1257 }
Yixin Wange7ecc472018-03-06 19:00:251258
Renjie90e808e2019-01-24 07:24:041259 AddWrite(ConstructClientAckPacket(3, 3, 1, 2));
[email protected]f702d572012-12-04 15:56:201260
1261 Initialize();
1262
danakjad1777e2016-04-16 00:56:421263 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:191264 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
ricea2deef682016-09-09 08:04:071265 kUploadData, strlen(kUploadData)));
rch97827ee2017-05-24 23:49:121266 upload_data_stream_ =
Jeremy Roman0579ed62017-08-29 15:56:191267 std::make_unique<ElementsUploadDataStream>(std::move(element_readers), 0);
[email protected]f702d572012-12-04 15:56:201268 request_.method = "POST";
rchcd379012017-04-12 21:53:321269 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121270 request_.upload_data_stream = upload_data_stream_.get();
Bence Békyd8a21fc32018-06-27 18:29:581271 ASSERT_THAT(request_.upload_data_stream->Init(CompletionOnceCallback(),
tfarina42834112016-09-22 13:38:201272 NetLogWithSource()),
1273 IsOk());
[email protected]f702d572012-12-04 15:56:201274
xunjieli5fafe142016-03-23 23:32:541275 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271276 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541277 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021278 EXPECT_EQ(OK,
1279 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:201280
1281 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041282 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]f702d572012-12-04 15:56:201283
1284 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071285 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451286 size_t spdy_response_headers_frame_length;
1287 ProcessPacket(ConstructResponseHeadersPacket(
1288 2, !kFin, &spdy_response_headers_frame_length));
[email protected]f702d572012-12-04 15:56:201289
rchfb47f712017-05-21 03:24:001290 // The headers have already arrived.
1291 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]cadac622013-06-11 16:46:361292 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:201293 EXPECT_EQ(200, response_.headers->response_code());
1294 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1295
1296 // Send the response body.
1297 const char kResponseBody[] = "Hello world!";
Renjief49758b2019-01-11 23:32:411298 quic::QuicString header2 = ConstructDataHeader(strlen(kResponseBody));
1299 ProcessPacket(
1300 ConstructServerDataPacket(3, false, kFin, 0, header2 + kResponseBody));
[email protected]f702d572012-12-04 15:56:201301 // Since the body has already arrived, this should return immediately.
1302 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
1303 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1304 callback_.callback()));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291305 EXPECT_EQ(0,
1306 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1307 callback_.callback()));
1308
1309 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1310 EXPECT_TRUE(AtEof());
1311
1312 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
1313 // headers and payload.
1314 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411315 strlen(kUploadData) + header.length()),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291316 stream_->GetTotalSentBytes());
1317 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411318 strlen(kResponseBody) + header2.length()),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291319 stream_->GetTotalReceivedBytes());
1320}
1321
1322TEST_P(QuicHttpStreamTest, SendPostRequestAndReceiveSoloFin) {
1323 SetRequest("POST", "/", DEFAULT_PRIORITY);
1324 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521325 quic::QuicStreamOffset header_stream_offset = 0;
Ryan Hamilton2ef0a9c2017-07-25 03:18:291326 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
Renjief49758b2019-01-11 23:32:411327 quic::QuicString header = ConstructDataHeader(strlen(kUploadData));
1328 if (version_ != quic::QUIC_VERSION_99) {
1329 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1330 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
1331 DEFAULT_PRIORITY, 0, &header_stream_offset,
1332 &spdy_request_headers_frame_length, {kUploadData}));
1333 } else {
1334 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1335 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
1336 DEFAULT_PRIORITY, 0, &header_stream_offset,
1337 &spdy_request_headers_frame_length, {header, kUploadData}));
1338 }
1339
Renjie90e808e2019-01-24 07:24:041340 AddWrite(ConstructClientAckPacket(3, 3, 1, 2));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291341
1342 Initialize();
1343
1344 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:191345 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
Ryan Hamilton2ef0a9c2017-07-25 03:18:291346 kUploadData, strlen(kUploadData)));
1347 upload_data_stream_ =
Jeremy Roman0579ed62017-08-29 15:56:191348 std::make_unique<ElementsUploadDataStream>(std::move(element_readers), 0);
Ryan Hamilton2ef0a9c2017-07-25 03:18:291349 request_.method = "POST";
1350 request_.url = GURL("https://www.example.org/");
1351 request_.upload_data_stream = upload_data_stream_.get();
Bence Békyd8a21fc32018-06-27 18:29:581352 ASSERT_THAT(request_.upload_data_stream->Init(CompletionOnceCallback(),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291353 NetLogWithSource()),
1354 IsOk());
1355
1356 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271357 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
Ryan Hamilton2ef0a9c2017-07-25 03:18:291358 net_log_.bound(), callback_.callback()));
1359 EXPECT_EQ(OK,
1360 stream_->SendRequest(headers_, &response_, callback_.callback()));
1361
1362 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041363 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291364
1365 // Send the response headers (but not the body).
1366 SetResponse("200 OK", string());
1367 size_t spdy_response_headers_frame_length;
1368 ProcessPacket(ConstructResponseHeadersPacket(
1369 2, !kFin, &spdy_response_headers_frame_length));
1370
1371 // The headers have already arrived.
1372 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
1373 ASSERT_TRUE(response_.headers.get());
1374 EXPECT_EQ(200, response_.headers->response_code());
1375 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1376
1377 // Send the response body.
1378 const char kResponseBody[] = "Hello world!";
Renjief49758b2019-01-11 23:32:411379 quic::QuicString header2 = ConstructDataHeader(strlen(kResponseBody));
1380 ProcessPacket(
1381 ConstructServerDataPacket(3, false, !kFin, 0, header2 + kResponseBody));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291382 // Since the body has already arrived, this should return immediately.
1383 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
1384 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1385 callback_.callback()));
Renjief49758b2019-01-11 23:32:411386 ProcessPacket(ConstructServerDataPacket(
1387 4, false, kFin, base::size(kResponseBody) - 1 + header2.length(), ""));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291388 EXPECT_EQ(0,
1389 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1390 callback_.callback()));
[email protected]f702d572012-12-04 15:56:201391
1392 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1393 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101394
1395 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451396 // headers and payload.
1397 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411398 strlen(kUploadData) + header.length()),
sclittle1edeeb22015-09-02 20:46:101399 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451400 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411401 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101402 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:201403}
1404
[email protected]1e960032013-12-20 19:00:201405TEST_P(QuicHttpStreamTest, SendChunkedPostRequest) {
1406 SetRequest("POST", "/", DEFAULT_PRIORITY);
[email protected]c9e49a02013-02-26 05:56:471407 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:451408 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521409 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361410 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
Renjief49758b2019-01-11 23:32:411411 quic::QuicString header = ConstructDataHeader(chunk_size);
1412 if (version_ == quic::QUIC_VERSION_99) {
1413 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1414 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
1415 !kFin, DEFAULT_PRIORITY, 0, &header_stream_offset,
1416 &spdy_request_headers_frame_length, {header, kUploadData}));
1417 AddWrite(ConstructClientMultipleDataFramesPacket(
1418 3, kIncludeVersion, kFin, header.length() + chunk_size,
1419 {header, kUploadData}));
1420 } else {
1421 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1422 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
1423 !kFin, DEFAULT_PRIORITY, 0, &header_stream_offset,
1424 &spdy_request_headers_frame_length, {kUploadData}));
1425 AddWrite(ConstructClientDataPacket(3, kIncludeVersion, kFin, chunk_size,
1426 kUploadData));
1427 }
1428
Renjie90e808e2019-01-24 07:24:041429 AddWrite(ConstructClientAckPacket(4, 3, 1, 2));
[email protected]c9e49a02013-02-26 05:56:471430 Initialize();
1431
Jeremy Roman0579ed62017-08-29 15:56:191432 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121433 auto* chunked_upload_stream =
1434 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1435 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
[email protected]c9e49a02013-02-26 05:56:471436
1437 request_.method = "POST";
rchcd379012017-04-12 21:53:321438 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121439 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071440 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201441 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]c9e49a02013-02-26 05:56:471442
xunjieli5fafe142016-03-23 23:32:541443 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271444 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541445 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021446 ASSERT_EQ(ERR_IO_PENDING,
1447 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]c9e49a02013-02-26 05:56:471448
rch97827ee2017-05-24 23:49:121449 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
robpercival214763f2016-07-01 23:27:011450 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]c9e49a02013-02-26 05:56:471451
1452 // Ack both packets in the request.
Renjie90e808e2019-01-24 07:24:041453 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]c9e49a02013-02-26 05:56:471454
1455 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071456 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451457 size_t spdy_response_headers_frame_length;
1458 ProcessPacket(ConstructResponseHeadersPacket(
1459 2, !kFin, &spdy_response_headers_frame_length));
[email protected]c9e49a02013-02-26 05:56:471460
rchfb47f712017-05-21 03:24:001461 // The headers have already arrived.
1462 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]cadac622013-06-11 16:46:361463 ASSERT_TRUE(response_.headers.get());
[email protected]c9e49a02013-02-26 05:56:471464 EXPECT_EQ(200, response_.headers->response_code());
1465 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1466
1467 // Send the response body.
1468 const char kResponseBody[] = "Hello world!";
Renjief49758b2019-01-11 23:32:411469 quic::QuicString header2 = ConstructDataHeader(strlen(kResponseBody));
alyssar2adf3ac2016-05-03 17:12:581470 ProcessPacket(ConstructServerDataPacket(
Renjief49758b2019-01-11 23:32:411471 3, false, kFin, response_data_.length(), header2 + kResponseBody));
[email protected]c9e49a02013-02-26 05:56:471472
1473 // Since the body has already arrived, this should return immediately.
1474 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1475 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1476 callback_.callback()));
1477
1478 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1479 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101480
1481 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451482 // headers and payload.
1483 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411484 strlen(kUploadData) * 2 + header.length() * 2),
sclittle1edeeb22015-09-02 20:46:101485 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451486 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411487 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101488 stream_->GetTotalReceivedBytes());
[email protected]c9e49a02013-02-26 05:56:471489}
1490
[email protected]16ba7742014-08-22 00:57:251491TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithFinalEmptyDataPacket) {
1492 SetRequest("POST", "/", DEFAULT_PRIORITY);
1493 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:451494 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521495 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361496 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
Renjief49758b2019-01-11 23:32:411497 quic::QuicString header = ConstructDataHeader(chunk_size);
1498
1499 if (version_ != quic::QUIC_VERSION_99) {
1500 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1501 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
1502 !kFin, DEFAULT_PRIORITY, 0, &header_stream_offset,
1503 &spdy_request_headers_frame_length, {kUploadData}));
1504 } else {
1505 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1506 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
1507 !kFin, DEFAULT_PRIORITY, 0, &header_stream_offset,
1508 &spdy_request_headers_frame_length, {header, kUploadData}));
1509 }
1510 AddWrite(ConstructClientDataPacket(3, kIncludeVersion, kFin,
1511 chunk_size + header.length(), ""));
Renjie90e808e2019-01-24 07:24:041512 AddWrite(ConstructClientAckPacket(4, 3, 1, 2));
[email protected]16ba7742014-08-22 00:57:251513 Initialize();
1514
Jeremy Roman0579ed62017-08-29 15:56:191515 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121516 auto* chunked_upload_stream =
1517 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1518 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
[email protected]16ba7742014-08-22 00:57:251519
1520 request_.method = "POST";
rchcd379012017-04-12 21:53:321521 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121522 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071523 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201524 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]16ba7742014-08-22 00:57:251525
xunjieli5fafe142016-03-23 23:32:541526 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271527 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541528 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021529 ASSERT_EQ(ERR_IO_PENDING,
1530 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251531
rch97827ee2017-05-24 23:49:121532 chunked_upload_stream->AppendData(nullptr, 0, true);
robpercival214763f2016-07-01 23:27:011533 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]16ba7742014-08-22 00:57:251534
Renjie90e808e2019-01-24 07:24:041535 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]16ba7742014-08-22 00:57:251536
1537 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071538 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451539 size_t spdy_response_headers_frame_length;
1540 ProcessPacket(ConstructResponseHeadersPacket(
1541 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251542
rchfb47f712017-05-21 03:24:001543 // The headers have already arrived.
1544 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]16ba7742014-08-22 00:57:251545 ASSERT_TRUE(response_.headers.get());
1546 EXPECT_EQ(200, response_.headers->response_code());
1547 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1548
1549 // Send the response body.
1550 const char kResponseBody[] = "Hello world!";
Renjief49758b2019-01-11 23:32:411551 quic::QuicString header2 = ConstructDataHeader(strlen(kResponseBody));
alyssar2adf3ac2016-05-03 17:12:581552 ProcessPacket(ConstructServerDataPacket(
Renjief49758b2019-01-11 23:32:411553 3, false, kFin, response_data_.length(), header2 + kResponseBody));
[email protected]16ba7742014-08-22 00:57:251554
rchb27683c2015-07-29 23:53:501555 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251556 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1557 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1558 callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251559 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1560 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101561
1562 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451563 // headers and payload.
1564 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
Renjief49758b2019-01-11 23:32:411565 strlen(kUploadData) + header.length()),
sclittle1edeeb22015-09-02 20:46:101566 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451567 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411568 strlen(kResponseBody) + header2.length()),
sclittle1edeeb22015-09-02 20:46:101569 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251570}
1571
1572TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithOneEmptyDataPacket) {
1573 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451574 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521575 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361576 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:371577 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:331578 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, !kFin,
ckrasicbf2f59c2017-05-04 23:54:361579 DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
1580 &header_stream_offset));
fayang3bcb8b502016-12-07 21:44:371581 AddWrite(ConstructClientDataPacket(3, kIncludeVersion, kFin, 0, ""));
Renjie90e808e2019-01-24 07:24:041582 AddWrite(ConstructClientAckPacket(4, 3, 1, 2));
[email protected]16ba7742014-08-22 00:57:251583 Initialize();
1584
Jeremy Roman0579ed62017-08-29 15:56:191585 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121586 auto* chunked_upload_stream =
1587 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
[email protected]16ba7742014-08-22 00:57:251588
1589 request_.method = "POST";
rchcd379012017-04-12 21:53:321590 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121591 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071592 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201593 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]16ba7742014-08-22 00:57:251594
xunjieli5fafe142016-03-23 23:32:541595 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271596 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541597 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021598 ASSERT_EQ(ERR_IO_PENDING,
1599 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251600
rch97827ee2017-05-24 23:49:121601 chunked_upload_stream->AppendData(nullptr, 0, true);
robpercival214763f2016-07-01 23:27:011602 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]16ba7742014-08-22 00:57:251603
Renjie90e808e2019-01-24 07:24:041604 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
[email protected]16ba7742014-08-22 00:57:251605
1606 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071607 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451608 size_t spdy_response_headers_frame_length;
1609 ProcessPacket(ConstructResponseHeadersPacket(
1610 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251611
rchfb47f712017-05-21 03:24:001612 // The headers have already arrived.
1613 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]16ba7742014-08-22 00:57:251614 ASSERT_TRUE(response_.headers.get());
1615 EXPECT_EQ(200, response_.headers->response_code());
1616 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1617
1618 // Send the response body.
1619 const char kResponseBody[] = "Hello world!";
Renjief49758b2019-01-11 23:32:411620 quic::QuicString header = ConstructDataHeader(strlen(kResponseBody));
alyssar2adf3ac2016-05-03 17:12:581621 ProcessPacket(ConstructServerDataPacket(
Renjief49758b2019-01-11 23:32:411622 3, false, kFin, response_data_.length(), header + kResponseBody));
[email protected]16ba7742014-08-22 00:57:251623
rchb27683c2015-07-29 23:53:501624 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251625 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1626 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1627 callback_.callback()));
1628
1629 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1630 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101631
1632 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451633 // headers and payload.
1634 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1635 stream_->GetTotalSentBytes());
1636 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:411637 strlen(kResponseBody) + header.length()),
sclittle1edeeb22015-09-02 20:46:101638 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251639}
1640
[email protected]1e960032013-12-20 19:00:201641TEST_P(QuicHttpStreamTest, DestroyedEarly) {
1642 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451643 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521644 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361645 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:371646 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:331647 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
ckrasicbf2f59c2017-05-04 23:54:361648 DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
1649 &header_stream_offset));
fayang3bcb8b502016-12-07 21:44:371650 AddWrite(ConstructAckAndRstStreamPacket(3));
[email protected]63534512012-12-23 18:49:001651 Initialize();
1652
1653 request_.method = "GET";
rchcd379012017-04-12 21:53:321654 request_.url = GURL("https://www.example.org/");
[email protected]63534512012-12-23 18:49:001655
xunjieli5fafe142016-03-23 23:32:541656 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271657 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541658 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021659 EXPECT_EQ(OK,
1660 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]63534512012-12-23 18:49:001661
1662 // Ack the request.
Renjie90e808e2019-01-24 07:24:041663 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
rchfb47f712017-05-21 03:24:001664 EXPECT_THAT(stream_->ReadResponseHeaders(
1665 base::Bind(&QuicHttpStreamTest::CloseStream,
1666 base::Unretained(this), stream_.get())),
robpercival214763f2016-07-01 23:27:011667 IsError(ERR_IO_PENDING));
[email protected]63534512012-12-23 18:49:001668
1669 // Send the response with a body.
[email protected]1e960032013-12-20 19:00:201670 SetResponse("404 OK", "hello world!");
[email protected]63534512012-12-23 18:49:001671 // In the course of processing this packet, the QuicHttpStream close itself.
rchfb47f712017-05-21 03:24:001672 size_t response_size = 0;
rch1bcfddf22017-06-03 00:26:291673 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin, &response_size));
[email protected]63534512012-12-23 18:49:001674
fdoray92e35a72016-06-10 15:54:551675 base::RunLoop().RunUntilIdle();
rchb27683c2015-07-29 23:53:501676
[email protected]63534512012-12-23 18:49:001677 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101678
1679 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451680 // headers and payload.
1681 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1682 stream_->GetTotalSentBytes());
rchfb47f712017-05-21 03:24:001683 // The stream was closed after receiving the headers.
1684 EXPECT_EQ(static_cast<int64_t>(response_size),
1685 stream_->GetTotalReceivedBytes());
[email protected]63534512012-12-23 18:49:001686}
1687
[email protected]1e960032013-12-20 19:00:201688TEST_P(QuicHttpStreamTest, Priority) {
1689 SetRequest("GET", "/", MEDIUM);
sclittlec4dc1a32015-09-24 00:15:451690 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521691 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361692 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:371693 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:331694 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
1695 MEDIUM, &spdy_request_headers_frame_length, &header_stream_offset));
[email protected]24e5bc52013-09-18 15:36:581696 Initialize();
1697
1698 request_.method = "GET";
rchcd379012017-04-12 21:53:321699 request_.url = GURL("https://www.example.org/");
[email protected]24e5bc52013-09-18 15:36:581700
Steven Valdezb4ff0412018-01-18 22:39:271701 EXPECT_EQ(OK,
1702 stream_->InitializeStream(&request_, true, MEDIUM, net_log_.bound(),
1703 callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581704
rjshaded5ced072015-12-18 19:26:021705 EXPECT_EQ(OK,
1706 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581707
[email protected]24e5bc52013-09-18 15:36:581708 // Ack the request.
Renjie90e808e2019-01-24 07:24:041709 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
robpercival214763f2016-07-01 23:27:011710 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1711 IsError(ERR_IO_PENDING));
[email protected]24e5bc52013-09-18 15:36:581712
1713 // Send the response with a body.
[email protected]1e960032013-12-20 19:00:201714 SetResponse("404 OK", "hello world!");
rchfb47f712017-05-21 03:24:001715 size_t response_size = 0;
1716 ProcessPacket(ConstructResponseHeadersPacket(2, kFin, &response_size));
[email protected]24e5bc52013-09-18 15:36:581717
rchfb47f712017-05-21 03:24:001718 EXPECT_EQ(OK, callback_.WaitForResult());
rchb27683c2015-07-29 23:53:501719
[email protected]24e5bc52013-09-18 15:36:581720 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101721
1722 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451723 // headers and payload.
1724 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1725 stream_->GetTotalSentBytes());
rchfb47f712017-05-21 03:24:001726 EXPECT_EQ(static_cast<int64_t>(response_size),
1727 stream_->GetTotalReceivedBytes());
[email protected]24e5bc52013-09-18 15:36:581728}
1729
xunjieli8dff50b2016-07-22 14:19:061730TEST_P(QuicHttpStreamTest, SessionClosedDuringDoLoop) {
1731 SetRequest("POST", "/", DEFAULT_PRIORITY);
1732 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521733 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361734 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
Renjief49758b2019-01-11 23:32:411735 quic::QuicString header = ConstructDataHeader(strlen(kUploadData));
1736 if (version_ != quic::QUIC_VERSION_99) {
1737 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1738 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
1739 !kFin, DEFAULT_PRIORITY, 0, &header_stream_offset,
1740 &spdy_request_headers_frame_length, {kUploadData}));
1741 } else {
1742 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1743 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
1744 !kFin, DEFAULT_PRIORITY, 0, &header_stream_offset,
1745 &spdy_request_headers_frame_length, {header, kUploadData}));
1746 }
1747
xunjieli8dff50b2016-07-22 14:19:061748 // Second data write will result in a synchronous failure which will close
1749 // the session.
1750 AddWrite(SYNCHRONOUS, ERR_FAILED);
1751 Initialize();
1752
Jeremy Roman0579ed62017-08-29 15:56:191753 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121754 auto* chunked_upload_stream =
1755 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
xunjieli8dff50b2016-07-22 14:19:061756
1757 request_.method = "POST";
rchcd379012017-04-12 21:53:321758 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121759 request_.upload_data_stream = upload_data_stream_.get();
xunjieli8dff50b2016-07-22 14:19:061760 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201761 TestCompletionCallback().callback(), NetLogWithSource()));
xunjieli8dff50b2016-07-22 14:19:061762
1763 size_t chunk_size = strlen(kUploadData);
rch97827ee2017-05-24 23:49:121764 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
xunjieli8dff50b2016-07-22 14:19:061765 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271766 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli8dff50b2016-07-22 14:19:061767 net_log_.bound(), callback_.callback()));
1768 QuicHttpStream* stream = stream_.get();
1769 DeleteStreamCallback delete_stream_callback(std::move(stream_));
1770 // SendRequest() completes asynchronously after the final chunk is added.
Yixin Wange7ecc472018-03-06 19:00:251771 // Error does not surface yet since packet write is triggered by a packet
1772 // flusher that tries to bundle request body writes.
xunjieli8dff50b2016-07-22 14:19:061773 ASSERT_EQ(ERR_IO_PENDING,
1774 stream->SendRequest(headers_, &response_, callback_.callback()));
rch97827ee2017-05-24 23:49:121775 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
xunjieli8dff50b2016-07-22 14:19:061776 int rv = callback_.WaitForResult();
Yixin Wange7ecc472018-03-06 19:00:251777 EXPECT_EQ(OK, rv);
1778 // Error will be surfaced once an attempt to read the response occurs.
1779 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1780 stream->ReadResponseHeaders(callback_.callback()));
xunjieli8dff50b2016-07-22 14:19:061781}
1782
rtenneti15656ae2016-01-23 03:05:031783TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersComplete) {
1784 SetRequest("POST", "/", DEFAULT_PRIORITY);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521785 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361786 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
rtenneti15656ae2016-01-23 03:05:031787 AddWrite(SYNCHRONOUS, ERR_FAILED);
1788 Initialize();
1789
Jeremy Roman0579ed62017-08-29 15:56:191790 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
Yixin Wange7ecc472018-03-06 19:00:251791 auto* chunked_upload_stream =
1792 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
rtenneti15656ae2016-01-23 03:05:031793
1794 request_.method = "POST";
rchcd379012017-04-12 21:53:321795 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121796 request_.upload_data_stream = upload_data_stream_.get();
rtenneti15656ae2016-01-23 03:05:031797 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201798 TestCompletionCallback().callback(), NetLogWithSource()));
rtenneti15656ae2016-01-23 03:05:031799
xunjieli5fafe142016-03-23 23:32:541800 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271801 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541802 net_log_.bound(), callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:251803 ASSERT_EQ(ERR_IO_PENDING,
rtenneti15656ae2016-01-23 03:05:031804 stream_->SendRequest(headers_, &response_, callback_.callback()));
mmenkeffff3642017-06-15 17:37:241805
Yixin Wange7ecc472018-03-06 19:00:251806 // Error will be surfaced once |upload_data_stream| triggers the next write.
1807 size_t chunk_size = strlen(kUploadData);
1808 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1809 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR, callback_.WaitForResult());
1810
1811 EXPECT_LE(0, stream_->GetTotalSentBytes());
1812 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1813}
1814
1815TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersCompleteReadResponse) {
1816 SetRequest("POST", "/", DEFAULT_PRIORITY);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521817 quic::QuicStreamOffset header_stream_offset = 0;
Yixin Wange7ecc472018-03-06 19:00:251818 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
1819 AddWrite(SYNCHRONOUS, ERR_FAILED);
1820 Initialize();
1821
1822 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
1823 auto* chunked_upload_stream =
1824 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1825
1826 request_.method = "POST";
1827 request_.url = GURL("https://www.example.org/");
1828 request_.upload_data_stream = upload_data_stream_.get();
1829
1830 size_t chunk_size = strlen(kUploadData);
1831 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1832
1833 ASSERT_EQ(OK, request_.upload_data_stream->Init(
1834 TestCompletionCallback().callback(), NetLogWithSource()));
1835
1836 ASSERT_EQ(OK,
1837 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1838 net_log_.bound(), callback_.callback()));
1839 ASSERT_EQ(OK,
1840 stream_->SendRequest(headers_, &response_, callback_.callback()));
1841
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
mmenkeffff3642017-06-15 17:37:241846 EXPECT_LE(0, stream_->GetTotalSentBytes());
1847 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rtenneti15656ae2016-01-23 03:05:031848}
1849
1850TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBodyComplete) {
1851 SetRequest("POST", "/", DEFAULT_PRIORITY);
1852 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521853 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361854 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:371855 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:331856 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, !kFin,
ckrasicbf2f59c2017-05-04 23:54:361857 DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
1858 &header_stream_offset));
rtenneti15656ae2016-01-23 03:05:031859 AddWrite(SYNCHRONOUS, ERR_FAILED);
1860 Initialize();
1861
Jeremy Roman0579ed62017-08-29 15:56:191862 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121863 auto* chunked_upload_stream =
1864 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
rtenneti15656ae2016-01-23 03:05:031865
1866 request_.method = "POST";
rchcd379012017-04-12 21:53:321867 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121868 request_.upload_data_stream = upload_data_stream_.get();
rtenneti15656ae2016-01-23 03:05:031869 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201870 TestCompletionCallback().callback(), NetLogWithSource()));
rtenneti15656ae2016-01-23 03:05:031871
xunjieli5fafe142016-03-23 23:32:541872 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271873 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541874 net_log_.bound(), callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:251875 ASSERT_EQ(ERR_IO_PENDING,
rtenneti15656ae2016-01-23 03:05:031876 stream_->SendRequest(headers_, &response_, callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:251877
1878 size_t chunk_size = strlen(kUploadData);
1879 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1880 // Error does not surface yet since packet write is triggered by a packet
1881 // flusher that tries to bundle request body writes.
1882 ASSERT_EQ(OK, callback_.WaitForResult());
1883 // Error will be surfaced once an attempt to read the response occurs.
1884 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1885 stream_->ReadResponseHeaders(callback_.callback()));
1886
1887 EXPECT_LE(0, stream_->GetTotalSentBytes());
1888 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1889}
1890
1891TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBundledBodyComplete) {
1892 SetRequest("POST", "/", DEFAULT_PRIORITY);
1893 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521894 quic::QuicStreamOffset header_stream_offset = 0;
Yixin Wange7ecc472018-03-06 19:00:251895 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
Renjief49758b2019-01-11 23:32:411896 quic::QuicString header = ConstructDataHeader(strlen(kUploadData));
1897 if (version_ != quic::QUIC_VERSION_99) {
1898 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1899 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
1900 !kFin, DEFAULT_PRIORITY, 0, &header_stream_offset,
1901 &spdy_request_headers_frame_length, {kUploadData}));
1902 } else {
1903 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1904 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
1905 !kFin, DEFAULT_PRIORITY, 0, &header_stream_offset,
1906 &spdy_request_headers_frame_length, {header, kUploadData}));
1907 }
1908
Yixin Wange7ecc472018-03-06 19:00:251909 AddWrite(SYNCHRONOUS, ERR_FAILED);
1910 Initialize();
1911
1912 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
1913 auto* chunked_upload_stream =
1914 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1915
1916 request_.method = "POST";
1917 request_.url = GURL("https://www.example.org/");
1918 request_.upload_data_stream = upload_data_stream_.get();
1919
1920 size_t chunk_size = strlen(kUploadData);
1921 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
1922
1923 ASSERT_EQ(OK, request_.upload_data_stream->Init(
1924 TestCompletionCallback().callback(), NetLogWithSource()));
1925
1926 ASSERT_EQ(OK,
1927 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1928 net_log_.bound(), callback_.callback()));
1929 ASSERT_EQ(ERR_IO_PENDING,
1930 stream_->SendRequest(headers_, &response_, callback_.callback()));
1931
1932 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1933
1934 // Error does not surface yet since packet write is triggered by a packet
1935 // flusher that tries to bundle request body writes.
1936 ASSERT_EQ(OK, callback_.WaitForResult());
1937 // Error will be surfaced once an attempt to read the response occurs.
1938 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1939 stream_->ReadResponseHeaders(callback_.callback()));
1940
1941 EXPECT_LE(0, stream_->GetTotalSentBytes());
1942 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rtenneti15656ae2016-01-23 03:05:031943}
1944
ckrasic3865ee0f2016-02-29 22:04:561945TEST_P(QuicHttpStreamTest, ServerPushGetRequest) {
1946 SetRequest("GET", "/", DEFAULT_PRIORITY);
1947 Initialize();
1948
1949 // Initialize the first stream, for receiving the promise on.
1950 request_.method = "GET";
rchcd379012017-04-12 21:53:321951 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:561952
xunjieli5fafe142016-03-23 23:32:541953 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271954 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541955 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561956
1957 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
1958 // packet, but does it matter?
1959 ReceivePromise(promise_id_);
1960 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
1961
1962 request_.url = GURL(promise_url_);
1963
1964 // Make the second stream that will exercise the first step of the
1965 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:271966 EXPECT_EQ(OK, promised_stream_->InitializeStream(
1967 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
1968 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561969
1970 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:251971 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:561972 size_t spdy_response_headers_frame_length;
1973 ProcessPacket(InnerConstructResponseHeadersPacket(
1974 1, promise_id_, false, &spdy_response_headers_frame_length));
1975
1976 // Receive the promised response body.
1977 const char kResponseBody[] = "Hello world!";
Renjief49758b2019-01-11 23:32:411978 quic::QuicString header = ConstructDataHeader(strlen(kResponseBody));
1979 ProcessPacket(InnerConstructDataPacket(
1980 2, promise_id_, false, kFin, 0, header + kResponseBody, &server_maker_));
ckrasic3865ee0f2016-02-29 22:04:561981
1982 // Now sending a matching request will have successful rendezvous
1983 // with the promised stream.
1984 EXPECT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
1985 callback_.callback()));
1986
1987 EXPECT_EQ(
1988 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
1989 ->id(),
1990 promise_id_);
1991
1992 // The headers will be immediately available.
robpercival214763f2016-07-01 23:27:011993 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
1994 IsOk());
ckrasic3865ee0f2016-02-29 22:04:561995
1996 // As will be the body.
1997 EXPECT_EQ(
1998 static_cast<int>(strlen(kResponseBody)),
1999 promised_stream_->ReadResponseBody(
2000 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2001 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2002 EXPECT_TRUE(AtEof());
2003
2004 EXPECT_EQ(0, stream_->GetTotalSentBytes());
2005 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2006 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2007 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412008 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562009 promised_stream_->GetTotalReceivedBytes());
2010}
2011
2012TEST_P(QuicHttpStreamTest, ServerPushGetRequestSlowResponse) {
2013 SetRequest("GET", "/", DEFAULT_PRIORITY);
2014 Initialize();
2015
2016 // Initialize the first stream, for receiving the promise on.
2017 request_.method = "GET";
rchcd379012017-04-12 21:53:322018 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562019
xunjieli5fafe142016-03-23 23:32:542020 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272021 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542022 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562023
2024 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2025 // packet, but does it matter?
2026 ReceivePromise(promise_id_);
2027 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2028
2029 request_.url = GURL(promise_url_);
2030
2031 // Make the second stream that will exercise the first step of the
2032 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272033 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2034 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2035 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562036
2037 // Now sending a matching request will rendezvous with the promised
2038 // stream, but pending secondary validation.
2039 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2040 headers_, &response_, callback_.callback()));
2041
2042 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252043 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562044 size_t spdy_response_headers_frame_length;
2045 ProcessPacket(InnerConstructResponseHeadersPacket(
2046 1, promise_id_, false, &spdy_response_headers_frame_length));
2047
2048 // Receive the promised response body.
2049 const char kResponseBody[] = "Hello world!";
Renjief49758b2019-01-11 23:32:412050 quic::QuicString header = ConstructDataHeader(strlen(kResponseBody));
2051 ProcessPacket(InnerConstructDataPacket(
2052 2, promise_id_, false, kFin, 0, header + kResponseBody, &server_maker_));
ckrasic3865ee0f2016-02-29 22:04:562053
fdoray92e35a72016-06-10 15:54:552054 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562055
2056 // Rendezvous should have succeeded now, so the promised stream
2057 // should point at our push stream, and we should be able read
2058 // headers and data from it.
robpercival214763f2016-07-01 23:27:012059 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562060
2061 EXPECT_EQ(
2062 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2063 ->id(),
2064 promise_id_);
2065
robpercival214763f2016-07-01 23:27:012066 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2067 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562068
2069 EXPECT_EQ(
2070 static_cast<int>(strlen(kResponseBody)),
2071 promised_stream_->ReadResponseBody(
2072 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2073
2074 // Callback should return
2075 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2076 EXPECT_TRUE(AtEof());
2077
2078 EXPECT_EQ(0, stream_->GetTotalSentBytes());
2079 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2080 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2081 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412082 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562083 promised_stream_->GetTotalReceivedBytes());
2084}
2085
ckrasic2c63f9b2016-08-16 23:54:072086// Verify fix for crbug.com/637349
2087TEST_P(QuicHttpStreamTest, ServerPushCancelHttpStreamBeforeResponse) {
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/");
ckrasic2c63f9b2016-08-16 23:54:072094
2095 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272096 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
ckrasic2c63f9b2016-08-16 23:54:072097 net_log_.bound(), callback_.callback()));
2098
2099 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2100 // packet, but does it matter?
2101 ReceivePromise(promise_id_);
2102 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2103
2104 request_.url = GURL(promise_url_);
2105
2106 // Make the second stream that will exercise the first step of the
2107 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272108 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2109 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2110 callback_.callback()));
ckrasic2c63f9b2016-08-16 23:54:072111
2112 // Now sending a matching request will rendezvous with the promised
2113 // stream, but pending secondary validation.
2114 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2115 headers_, &response_, callback_.callback()));
2116
2117 base::RunLoop().RunUntilIdle();
2118
2119 // Cause of FinalValidation() crash as per bug.
2120 promised_stream_.reset();
2121
2122 // Receive the promised response headers.
2123 response_headers_ = promised_response_.Clone();
2124 size_t spdy_response_headers_frame_length;
2125 ProcessPacket(InnerConstructResponseHeadersPacket(
2126 1, promise_id_, false, &spdy_response_headers_frame_length));
2127}
2128
ckrasic3865ee0f2016-02-29 22:04:562129TEST_P(QuicHttpStreamTest, ServerPushCrossOriginOK) {
2130 SetRequest("GET", "/", DEFAULT_PRIORITY);
2131 Initialize();
2132
2133 // Initialize the first stream, for receiving the promise on.
2134 request_.method = "GET";
rchcd379012017-04-12 21:53:322135 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562136
xunjieli5fafe142016-03-23 23:32:542137 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272138 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542139 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562140
2141 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2142 // packet, but does it matter?
2143
2144 push_promise_[":authority"] = "mail.example.org";
Ryan Hamilton8d9ee76e2018-05-29 23:52:522145 promise_url_ = quic::SpdyUtils::GetPromisedUrlFromHeaders(push_promise_);
ckrasic3865ee0f2016-02-29 22:04:562146
2147 ReceivePromise(promise_id_);
2148 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2149
2150 request_.url = GURL(promise_url_);
2151
2152 // Make the second stream that will exercise the first step of the
2153 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272154 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2155 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2156 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562157
2158 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252159 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562160 size_t spdy_response_headers_frame_length;
2161 ProcessPacket(InnerConstructResponseHeadersPacket(
2162 1, promise_id_, false, &spdy_response_headers_frame_length));
2163
2164 // Receive the promised response body.
2165 const char kResponseBody[] = "Hello world!";
Renjief49758b2019-01-11 23:32:412166 quic::QuicString header = ConstructDataHeader(strlen(kResponseBody));
2167 ProcessPacket(InnerConstructDataPacket(
2168 2, promise_id_, false, kFin, 0, header + kResponseBody, &server_maker_));
ckrasic3865ee0f2016-02-29 22:04:562169
2170 // Now sending a matching request will have successful rendezvous
2171 // with the promised stream.
2172 EXPECT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
2173 callback_.callback()));
2174
2175 EXPECT_EQ(
2176 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2177 ->id(),
2178 promise_id_);
2179
2180 // The headers will be immediately available.
robpercival214763f2016-07-01 23:27:012181 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2182 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562183
2184 // As will be the body.
2185 EXPECT_EQ(
2186 static_cast<int>(strlen(kResponseBody)),
2187 promised_stream_->ReadResponseBody(
2188 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2189 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2190 EXPECT_TRUE(AtEof());
2191
2192 EXPECT_EQ(0, stream_->GetTotalSentBytes());
2193 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2194 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2195 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412196 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562197 promised_stream_->GetTotalReceivedBytes());
2198}
2199
2200TEST_P(QuicHttpStreamTest, ServerPushCrossOriginFail) {
2201 SetRequest("GET", "/", DEFAULT_PRIORITY);
2202 Initialize();
2203
2204 // Initialize the first stream, for receiving the promise on.
2205 request_.method = "GET";
rchcd379012017-04-12 21:53:322206 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562207
xunjieli5fafe142016-03-23 23:32:542208 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272209 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542210 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562211
2212 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2213 // packet, but does it matter?
2214 push_promise_[":authority"] = "www.notexample.org";
Ryan Hamilton8d9ee76e2018-05-29 23:52:522215 promise_url_ = quic::SpdyUtils::GetPromisedUrlFromHeaders(push_promise_);
ckrasic3865ee0f2016-02-29 22:04:562216
2217 ReceivePromise(promise_id_);
2218 // The promise will have been rejected because the cert doesn't
2219 // match.
2220 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
2221}
2222
2223TEST_P(QuicHttpStreamTest, ServerPushVaryCheckOK) {
2224 SetRequest("GET", "/", DEFAULT_PRIORITY);
2225 Initialize();
2226
2227 // Initialize the first stream, for receiving the promise on.
2228 request_.method = "GET";
rchcd379012017-04-12 21:53:322229 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562230
xunjieli5fafe142016-03-23 23:32:542231 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272232 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542233 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562234
2235 push_promise_["accept-encoding"] = "gzip";
ckrasic3865ee0f2016-02-29 22:04:562236
2237 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2238 // packet, but does it matter?
2239 ReceivePromise(promise_id_);
2240 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2241
2242 request_.url = GURL(promise_url_);
2243
2244 // Make the second stream that will exercise the first step of the
2245 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272246 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2247 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2248 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562249
2250 headers_.SetHeader("accept-encoding", "gzip");
2251
2252 // Now sending a matching request will rendezvous with the promised
2253 // stream, but pending secondary validation.
2254 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2255 headers_, &response_, callback_.callback()));
2256
2257 // Receive the promised response headers.
2258 promised_response_["vary"] = "accept-encoding";
bnc94893a72016-06-30 13:45:252259 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562260 size_t spdy_response_headers_frame_length;
2261 ProcessPacket(InnerConstructResponseHeadersPacket(
2262 1, promise_id_, false, &spdy_response_headers_frame_length));
2263
2264 // Receive the promised response body.
2265 const char kResponseBody[] = "Hello world!";
Renjief49758b2019-01-11 23:32:412266 quic::QuicString header = ConstructDataHeader(strlen(kResponseBody));
2267 ProcessPacket(InnerConstructDataPacket(
2268 2, promise_id_, false, kFin, 0, header + kResponseBody, &server_maker_));
ckrasic3865ee0f2016-02-29 22:04:562269
fdoray92e35a72016-06-10 15:54:552270 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562271
2272 // Rendezvous should have succeeded now, so the promised stream
2273 // should point at our push stream, and we should be able read
2274 // headers and data from it.
robpercival214763f2016-07-01 23:27:012275 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562276
2277 EXPECT_EQ(
2278 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2279 ->id(),
2280 promise_id_);
2281
robpercival214763f2016-07-01 23:27:012282 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2283 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562284
2285 EXPECT_EQ(
2286 static_cast<int>(strlen(kResponseBody)),
2287 promised_stream_->ReadResponseBody(
2288 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2289
2290 // Callback should return
2291 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2292 EXPECT_TRUE(AtEof());
2293
2294 EXPECT_EQ(0, stream_->GetTotalSentBytes());
2295 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2296 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2297 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
Renjief49758b2019-01-11 23:32:412298 strlen(kResponseBody) + header.length()),
ckrasic3865ee0f2016-02-29 22:04:562299 promised_stream_->GetTotalReceivedBytes());
2300}
2301
2302TEST_P(QuicHttpStreamTest, ServerPushVaryCheckFail) {
2303 SetRequest("GET", "/", DEFAULT_PRIORITY);
2304 request_headers_[":scheme"] = "https";
2305 request_headers_[":path"] = "/bar";
2306 request_headers_["accept-encoding"] = "sdch";
2307
2308 size_t spdy_request_header_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:522309 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:362310 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
Yixin Wangb470bc882018-02-15 18:43:572311
Fan Yangac867502019-01-28 21:10:232312 uint64_t client_packet_number = 2;
Yixin Wangb470bc882018-02-15 18:43:572313 if (client_headers_include_h2_stream_dependency_ &&
Zhongyi Shi7b4f22b2018-08-23 17:22:262314 version_ >= quic::QUIC_VERSION_43) {
Yixin Wangb470bc882018-02-15 18:43:572315 AddWrite(ConstructClientPriorityPacket(
2316 client_packet_number++, kIncludeVersion, promise_id_, 0,
2317 DEFAULT_PRIORITY, &header_stream_offset));
2318 }
Michael Warresabba8b7d2018-07-20 22:50:272319 AddWrite(ConstructClientRstStreamVaryMismatchAndRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:332320 client_packet_number++, stream_id_ + quic::test::NextStreamId(version_),
2321 !kIncludeVersion, kFin, DEFAULT_PRIORITY, promise_id_,
2322 &spdy_request_header_frame_length, &header_stream_offset));
Renjie90e808e2019-01-24 07:24:042323 AddWrite(ConstructClientAckPacket(client_packet_number++, 3, 1, 2));
Yixin Wangb470bc882018-02-15 18:43:572324 AddWrite(ConstructClientRstStreamCancelledPacket(client_packet_number++));
2325
ckrasic3865ee0f2016-02-29 22:04:562326 Initialize();
2327
2328 // Initialize the first stream, for receiving the promise on.
2329 request_.method = "GET";
rchcd379012017-04-12 21:53:322330 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562331
xunjieli5fafe142016-03-23 23:32:542332 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272333 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542334 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562335
2336 push_promise_["accept-encoding"] = "gzip";
ckrasic3865ee0f2016-02-29 22:04:562337
2338 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2339 // packet, but does it matter?
2340 ReceivePromise(promise_id_);
2341 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2342
2343 request_.url = GURL(promise_url_);
2344
2345 // Make the second stream that will exercise the first step of the
2346 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272347 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2348 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2349 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562350
2351 headers_.SetHeader("accept-encoding", "sdch");
2352
2353 // Now sending a matching request will rendezvous with the promised
2354 // stream, but pending secondary validation.
2355 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2356 headers_, &response_, callback_.callback()));
2357
2358 // Receive the promised response headers.
2359 promised_response_["vary"] = "accept-encoding";
bnc94893a72016-06-30 13:45:252360 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562361 size_t spdy_response_headers_frame_length;
2362 ProcessPacket(InnerConstructResponseHeadersPacket(
2363 1, promise_id_, false, &spdy_response_headers_frame_length));
2364
fdoray92e35a72016-06-10 15:54:552365 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562366
2367 // Rendezvous should have failed due to vary mismatch, so the
2368 // promised stream should have been aborted, and instead we have a
2369 // new, regular client initiated stream.
robpercival214763f2016-07-01 23:27:012370 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562371
2372 // Not a server-initiated stream.
2373 EXPECT_NE(
2374 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2375 ->id(),
2376 promise_id_);
2377
2378 // Instead, a new client-initiated stream.
2379 EXPECT_EQ(
2380 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2381 ->id(),
Fan Yang32c5a112018-12-10 20:06:332382 stream_id_ + quic::test::NextStreamId(version_));
ckrasic3865ee0f2016-02-29 22:04:562383
2384 // After rendezvous failure, the push stream has been cancelled.
2385 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
2386
2387 // The rest of the test verifies that the retried as
2388 // client-initiated version of |promised_stream_| works as intended.
2389
2390 // Ack the request.
Renjie90e808e2019-01-24 07:24:042391 ProcessPacket(ConstructServerAckPacket(2, 1, 1, 1));
ckrasic3865ee0f2016-02-29 22:04:562392
bnc614a92d32016-04-04 13:56:072393 SetResponse("404 Not Found", string());
ckrasic3865ee0f2016-02-29 22:04:562394 size_t spdy_response_header_frame_length;
2395 ProcessPacket(InnerConstructResponseHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:332396 3, stream_id_ + quic::test::NextStreamId(version_), kFin,
2397 &spdy_response_header_frame_length));
ckrasic3865ee0f2016-02-29 22:04:562398
fdoray92e35a72016-06-10 15:54:552399 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562400
robpercival214763f2016-07-01 23:27:012401 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2402 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562403 ASSERT_TRUE(response_.headers.get());
2404 EXPECT_EQ(404, response_.headers->response_code());
2405 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
2406 EXPECT_FALSE(response_.response_time.is_null());
2407 EXPECT_FALSE(response_.request_time.is_null());
2408
2409 // There is no body, so this should return immediately.
2410 EXPECT_EQ(
2411 0, promised_stream_->ReadResponseBody(
2412 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2413 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2414
2415 stream_->Close(true);
2416
2417 EXPECT_TRUE(AtEof());
2418
2419 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
2420 // headers and payload.
2421 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
2422 promised_stream_->GetTotalSentBytes());
2423 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length),
2424 promised_stream_->GetTotalReceivedBytes());
2425}
2426
maksim.sisov84e20c92016-06-23 08:49:342427TEST_P(QuicHttpStreamTest, DataReadErrorSynchronous) {
2428 SetRequest("POST", "/", DEFAULT_PRIORITY);
2429 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:522430 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:362431 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
Yixin Wange7ecc472018-03-06 19:00:252432 AddWrite(ConstructRequestAndRstPacket(
Fan Yang32c5a112018-12-10 20:06:332433 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, !kFin,
Yixin Wange7ecc472018-03-06 19:00:252434 DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
Ryan Hamilton8d9ee76e2018-05-29 23:52:522435 &header_stream_offset, quic::QUIC_ERROR_PROCESSING_STREAM, 0));
maksim.sisov84e20c92016-06-23 08:49:342436
2437 Initialize();
2438
Jeremy Roman0579ed62017-08-29 15:56:192439 upload_data_stream_ = std::make_unique<ReadErrorUploadDataStream>(
maksim.sisov84e20c92016-06-23 08:49:342440 ReadErrorUploadDataStream::FailureMode::SYNC);
2441 request_.method = "POST";
rchcd379012017-04-12 21:53:322442 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122443 request_.upload_data_stream = upload_data_stream_.get();
maksim.sisov84e20c92016-06-23 08:49:342444 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202445 TestCompletionCallback().callback(), NetLogWithSource()));
maksim.sisov84e20c92016-06-23 08:49:342446
2447 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272448 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
maksim.sisov84e20c92016-06-23 08:49:342449 net_log_.bound(), callback_.callback()));
2450
2451 int result = stream_->SendRequest(headers_, &response_, callback_.callback());
robpercival214763f2016-07-01 23:27:012452 EXPECT_THAT(result, IsError(ERR_FAILED));
maksim.sisov84e20c92016-06-23 08:49:342453
2454 EXPECT_TRUE(AtEof());
2455
2456 // QuicHttpStream::GetTotalSent/ReceivedBytes includes only headers.
2457 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
2458 stream_->GetTotalSentBytes());
2459 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2460}
2461
2462TEST_P(QuicHttpStreamTest, DataReadErrorAsynchronous) {
2463 SetRequest("POST", "/", DEFAULT_PRIORITY);
2464 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:522465 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:362466 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:372467 AddWrite(InnerConstructRequestHeadersPacket(
Fan Yang32c5a112018-12-10 20:06:332468 2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, !kFin,
ckrasicbf2f59c2017-05-04 23:54:362469 DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
2470 &header_stream_offset));
fayang3bcb8b502016-12-07 21:44:372471 AddWrite(ConstructClientRstStreamErrorPacket(3, !kIncludeVersion));
maksim.sisov84e20c92016-06-23 08:49:342472
2473 Initialize();
2474
Jeremy Roman0579ed62017-08-29 15:56:192475 upload_data_stream_ = std::make_unique<ReadErrorUploadDataStream>(
maksim.sisov84e20c92016-06-23 08:49:342476 ReadErrorUploadDataStream::FailureMode::ASYNC);
2477 request_.method = "POST";
rchcd379012017-04-12 21:53:322478 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122479 request_.upload_data_stream = upload_data_stream_.get();
maksim.sisov84e20c92016-06-23 08:49:342480 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202481 TestCompletionCallback().callback(), NetLogWithSource()));
maksim.sisov84e20c92016-06-23 08:49:342482
2483 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272484 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
maksim.sisov84e20c92016-06-23 08:49:342485 net_log_.bound(), callback_.callback()));
2486
2487 int result = stream_->SendRequest(headers_, &response_, callback_.callback());
2488
Renjie90e808e2019-01-24 07:24:042489 ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
maksim.sisov84e20c92016-06-23 08:49:342490 SetResponse("200 OK", string());
2491
robpercival214763f2016-07-01 23:27:012492 EXPECT_THAT(result, IsError(ERR_IO_PENDING));
2493 EXPECT_THAT(callback_.GetResult(result), IsError(ERR_FAILED));
maksim.sisov84e20c92016-06-23 08:49:342494
2495 EXPECT_TRUE(AtEof());
2496
2497 // QuicHttpStream::GetTotalSent/ReceivedBytes includes only headers.
2498 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
2499 stream_->GetTotalSentBytes());
2500 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2501}
2502
[email protected]f702d572012-12-04 15:56:202503} // namespace test
[email protected]f702d572012-12-04 15:56:202504} // namespace net