blob: f35005e306fbb7547c597f88e6c94311dcd02b24 [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
danakjad1777e2016-04-16 00:56:4212#include "base/memory/ptr_util.h"
fdoray92e35a72016-06-10 15:54:5513#include "base/run_loop.h"
xunjieli188bd402016-03-12 00:17:2514#include "base/strings/string_number_conversions.h"
gabf767595f2016-05-11 18:50:3515#include "base/threading/thread_task_runner_handle.h"
xunjieli84adaab2016-09-20 01:12:2816#include "base/time/time.h"
mmenkecbc2b712014-10-09 20:29:0717#include "net/base/chunked_upload_data_stream.h"
18#include "net/base/elements_upload_data_stream.h"
xunjieli84adaab2016-09-20 01:12:2819#include "net/base/load_timing_info.h"
20#include "net/base/load_timing_info_test_util.h"
[email protected]f702d572012-12-04 15:56:2021#include "net/base/net_errors.h"
22#include "net/base/test_completion_callback.h"
[email protected]b2d26cfd2012-12-11 10:36:0623#include "net/base/upload_bytes_element_reader.h"
[email protected]f702d572012-12-04 15:56:2024#include "net/http/http_response_headers.h"
[email protected]5db452202014-08-19 05:22:1525#include "net/http/transport_security_state.h"
mikecirone8b85c432016-09-08 19:11:0026#include "net/log/net_log_event_type.h"
xunjieli5fafe142016-03-23 23:32:5427#include "net/log/test_net_log.h"
28#include "net/log/test_net_log_util.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0829#include "net/quic/crypto/proof_verifier_chromium.h"
30#include "net/quic/mock_crypto_client_stream_factory.h"
31#include "net/quic/quic_chromium_alarm_factory.h"
32#include "net/quic/quic_chromium_connection_helper.h"
33#include "net/quic/quic_chromium_packet_reader.h"
34#include "net/quic/quic_chromium_packet_writer.h"
35#include "net/quic/quic_http_utils.h"
36#include "net/quic/quic_server_info.h"
37#include "net/quic/quic_stream_factory.h"
38#include "net/quic/quic_test_packet_maker.h"
39#include "net/quic/test_task_runner.h"
tbansalca83c002016-04-28 20:56:2840#include "net/socket/socket_performance_watcher.h"
[email protected]f702d572012-12-04 15:56:2041#include "net/socket/socket_test_util.h"
Bence Béky94658bf2018-05-11 19:22:5842#include "net/spdy/spdy_http_utils.h"
rch03b7a202016-02-05 00:54:2043#include "net/test/cert_test_util.h"
robpercival214763f2016-07-01 23:27:0144#include "net/test/gtest_util.h"
rsleevia69c79a2016-06-22 03:28:4345#include "net/test/test_data_directory.h"
Bence Béky98447b12018-05-08 03:14:0146#include "net/test/test_with_scoped_task_environment.h"
Ryan Hamilton56b10c5d2018-05-11 13:40:1647#include "net/third_party/quic/core/congestion_control/send_algorithm_interface.h"
48#include "net/third_party/quic/core/crypto/crypto_protocol.h"
49#include "net/third_party/quic/core/crypto/quic_decrypter.h"
50#include "net/third_party/quic/core/crypto/quic_encrypter.h"
Victor Vasilievc5b409c22018-07-24 12:23:4651#include "net/third_party/quic/core/http/spdy_utils.h"
Ryan Hamilton56b10c5d2018-05-11 13:40:1652#include "net/third_party/quic/core/quic_connection.h"
53#include "net/third_party/quic/core/quic_write_blocked_list.h"
Ryan Hamilton56b10c5d2018-05-11 13:40:1654#include "net/third_party/quic/core/tls_client_handshaker.h"
55#include "net/third_party/quic/platform/api/quic_string_piece.h"
56#include "net/third_party/quic/test_tools/crypto_test_utils.h"
57#include "net/third_party/quic/test_tools/mock_clock.h"
58#include "net/third_party/quic/test_tools/mock_random.h"
59#include "net/third_party/quic/test_tools/quic_connection_peer.h"
60#include "net/third_party/quic/test_tools/quic_spdy_session_peer.h"
61#include "net/third_party/quic/test_tools/quic_test_utils.h"
Ryan Hamilton2e003eea2018-05-02 00:24:2962#include "net/third_party/spdy/core/spdy_frame_builder.h"
63#include "net/third_party/spdy/core/spdy_framer.h"
64#include "net/third_party/spdy/core/spdy_protocol.h"
Ramin Halavati683bcaa92018-02-14 08:42:3965#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
[email protected]f702d572012-12-04 15:56:2066#include "testing/gmock/include/gmock/gmock.h"
67#include "testing/gtest/include/gtest/gtest.h"
68
bnc614a92d32016-04-04 13:56:0769using std::string;
[email protected]f702d572012-12-04 15:56:2070using testing::_;
[email protected]06ff5152013-08-29 01:03:0571using testing::AnyNumber;
72using testing::Return;
[email protected]f702d572012-12-04 15:56:2073
74namespace net {
[email protected]f702d572012-12-04 15:56:2075namespace test {
[email protected]f702d572012-12-04 15:56:2076namespace {
77
[email protected]16ba7742014-08-22 00:57:2578const char kUploadData[] = "Really nifty data!";
rch9ae5b3b2016-02-11 00:36:2979const char kDefaultServerHostName[] = "www.example.org";
rchcd379012017-04-12 21:53:3280const uint16_t kDefaultServerPort = 443;
[email protected]f702d572012-12-04 15:56:2081
Ryan Hamilton8d9ee76e2018-05-29 23:52:5282class TestQuicConnection : public quic::QuicConnection {
[email protected]f702d572012-12-04 15:56:2083 public:
Ryan Hamilton8d9ee76e2018-05-29 23:52:5284 TestQuicConnection(const quic::ParsedQuicVersionVector& versions,
85 quic::QuicConnectionId connection_id,
[email protected]f702d572012-12-04 15:56:2086 IPEndPoint address,
rch12fef552016-01-15 16:26:3187 QuicChromiumConnectionHelper* helper,
rch16c74d1d2016-04-22 06:14:0788 QuicChromiumAlarmFactory* alarm_factory,
Ryan Hamilton8d9ee76e2018-05-29 23:52:5289 quic::QuicPacketWriter* writer)
90 : quic::QuicConnection(
91 connection_id,
92 quic::QuicSocketAddress(quic::QuicSocketAddressImpl(address)),
93 helper,
94 alarm_factory,
95 writer,
96 true /* owns_writer */,
97 quic::Perspective::IS_CLIENT,
98 versions) {}
[email protected]f702d572012-12-04 15:56:2099
Ryan Hamilton8d9ee76e2018-05-29 23:52:52100 void SetSendAlgorithm(quic::SendAlgorithmInterface* send_algorithm) {
101 quic::test::QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
[email protected]f702d572012-12-04 15:56:20102 }
103};
104
maksim.sisov84e20c92016-06-23 08:49:34105// UploadDataStream that always returns errors on data read.
106class ReadErrorUploadDataStream : public UploadDataStream {
107 public:
108 enum class FailureMode { SYNC, ASYNC };
109
110 explicit ReadErrorUploadDataStream(FailureMode mode)
111 : UploadDataStream(true, 0), async_(mode), weak_factory_(this) {}
112 ~ReadErrorUploadDataStream() override {}
113
114 private:
115 void CompleteRead() { UploadDataStream::OnReadCompleted(ERR_FAILED); }
116
117 // UploadDataStream implementation:
tfarina428341112016-09-22 13:38:20118 int InitInternal(const NetLogWithSource& net_log) override { return OK; }
maksim.sisov84e20c92016-06-23 08:49:34119
120 int ReadInternal(IOBuffer* buf, int buf_len) override {
121 if (async_ == FailureMode::ASYNC) {
122 base::ThreadTaskRunnerHandle::Get()->PostTask(
123 FROM_HERE, base::Bind(&ReadErrorUploadDataStream::CompleteRead,
124 weak_factory_.GetWeakPtr()));
125 return ERR_IO_PENDING;
126 }
127 return ERR_FAILED;
128 }
129
130 void ResetInternal() override {}
131
132 const FailureMode async_;
133
134 base::WeakPtrFactory<ReadErrorUploadDataStream> weak_factory_;
135
136 DISALLOW_COPY_AND_ASSIGN(ReadErrorUploadDataStream);
137};
138
Bence Béky8ddc2492018-06-13 01:02:04139// A helper class that will delete |stream| when the callback is invoked.
xunjieli8dff50b2016-07-22 14:19:06140class DeleteStreamCallback : public TestCompletionCallbackBase {
141 public:
Bence Béky8ddc2492018-06-13 01:02:04142 explicit DeleteStreamCallback(std::unique_ptr<QuicHttpStream> stream)
143 : stream_(std::move(stream)) {}
xunjieli8dff50b2016-07-22 14:19:06144
Bence Béky8ddc2492018-06-13 01:02:04145 CompletionOnceCallback callback() {
146 return base::BindOnce(&DeleteStreamCallback::DeleteStream,
147 base::Unretained(this));
148 }
xunjieli8dff50b2016-07-22 14:19:06149
150 private:
151 void DeleteStream(int result) {
152 stream_.reset();
153 SetResult(result);
154 }
155
156 std::unique_ptr<QuicHttpStream> stream_;
xunjieli8dff50b2016-07-22 14:19:06157};
158
[email protected]f702d572012-12-04 15:56:20159} // namespace
160
[email protected]24e5bc52013-09-18 15:36:58161class QuicHttpStreamPeer {
162 public:
rch08e198572017-05-09 16:56:55163 static QuicChromiumClientStream::Handle* GetQuicChromiumClientStream(
[email protected]24e5bc52013-09-18 15:36:58164 QuicHttpStream* stream) {
rch08e198572017-05-09 16:56:55165 return stream->stream_.get();
[email protected]24e5bc52013-09-18 15:36:58166 }
167};
168
Ryan Hamilton8d9ee76e2018-05-29 23:52:52169class QuicHttpStreamTest : public ::testing::TestWithParam<
170 std::tuple<quic::QuicTransportVersion, bool>>,
171 public WithScopedTaskEnvironment {
rchfb47f712017-05-21 03:24:00172 public:
173 void CloseStream(QuicHttpStream* stream, int /*rv*/) { stream->Close(false); }
174
[email protected]f702d572012-12-04 15:56:20175 protected:
[email protected]1e960032013-12-20 19:00:20176 static const bool kFin = true;
177 static const bool kIncludeVersion = true;
178 static const bool kIncludeCongestionFeedback = true;
179
[email protected]f702d572012-12-04 15:56:20180 // Holds a packet to be written to the wire, and the IO mode that should
181 // be used by the mock socket when performing the write.
182 struct PacketToWrite {
Ryan Hamilton8d9ee76e2018-05-29 23:52:52183 PacketToWrite(IoMode mode, quic::QuicReceivedPacket* packet)
rjshaded5ced072015-12-18 19:26:02184 : mode(mode), packet(packet) {}
rtenneti15656ae2016-01-23 03:05:03185 PacketToWrite(IoMode mode, int rv) : mode(mode), packet(nullptr), rv(rv) {}
[email protected]f702d572012-12-04 15:56:20186 IoMode mode;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52187 quic::QuicReceivedPacket* packet;
rtenneti15656ae2016-01-23 03:05:03188 int rv;
[email protected]f702d572012-12-04 15:56:20189 };
190
191 QuicHttpStreamTest()
Yixin Wang079ad542018-01-11 04:06:05192 : version_(std::get<0>(GetParam())),
193 client_headers_include_h2_stream_dependency_(std::get<1>(GetParam())),
Ryan Hamilton8d9ee76e2018-05-29 23:52:52194 crypto_config_(quic::test::crypto_test_utils::ProofVerifierForTesting(),
195 quic::TlsClientHandshaker::CreateSslCtx()),
Victor Costan9c7302b2018-08-27 16:39:44196 read_buffer_(base::MakeRefCounted<IOBufferWithSize>(4096)),
ckrasicbf2f59c2017-05-04 23:54:36197 promise_id_(GetNthServerInitiatedStreamId(0)),
198 stream_id_(GetNthClientInitiatedStreamId(0)),
ckrasic3865ee0f2016-02-29 22:04:56199 connection_id_(2),
Yixin Wang079ad542018-01-11 04:06:05200 client_maker_(version_,
alyssar2adf3ac2016-05-03 17:12:58201 connection_id_,
202 &clock_,
203 kDefaultServerHostName,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52204 quic::Perspective::IS_CLIENT,
Yixin Wang079ad542018-01-11 04:06:05205 client_headers_include_h2_stream_dependency_),
206 server_maker_(version_,
zhongyi5dbfdd42017-06-20 05:22:15207 connection_id_,
alyssar2adf3ac2016-05-03 17:12:58208 &clock_,
209 kDefaultServerHostName,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52210 quic::Perspective::IS_SERVER,
Yixin Wang079ad542018-01-11 04:06:05211 false),
ckrasic3865ee0f2016-02-29 22:04:56212 random_generator_(0),
213 response_offset_(0) {
martijn21968ea2016-02-24 18:46:20214 IPAddress ip(192, 0, 2, 33);
[email protected]f702d572012-12-04 15:56:20215 peer_addr_ = IPEndPoint(ip, 443);
216 self_addr_ = IPEndPoint(ip, 8435);
Ryan Hamilton8d9ee76e2018-05-29 23:52:52217 clock_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(20));
Ramin Halavati683bcaa92018-02-14 08:42:39218 request_.traffic_annotation =
219 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f702d572012-12-04 15:56:20220 }
221
222 ~QuicHttpStreamTest() {
Renjieba55fae2018-09-20 03:05:16223 session_->CloseSessionOnError(ERR_ABORTED, quic::QUIC_INTERNAL_ERROR,
224 quic::ConnectionCloseBehavior::SILENT_CLOSE);
[email protected]f702d572012-12-04 15:56:20225 for (size_t i = 0; i < writes_.size(); i++) {
226 delete writes_[i].packet;
227 }
228 }
229
230 // Adds a packet to the list of expected writes.
Ryan Hamilton8d9ee76e2018-05-29 23:52:52231 void AddWrite(std::unique_ptr<quic::QuicReceivedPacket> packet) {
[email protected]1e960032013-12-20 19:00:20232 writes_.push_back(PacketToWrite(SYNCHRONOUS, packet.release()));
[email protected]f702d572012-12-04 15:56:20233 }
234
rtenneti15656ae2016-01-23 03:05:03235 void AddWrite(IoMode mode, int rv) {
236 writes_.push_back(PacketToWrite(mode, rv));
237 }
238
[email protected]f702d572012-12-04 15:56:20239 // Returns the packet to be written at position |pos|.
Ryan Hamilton8d9ee76e2018-05-29 23:52:52240 quic::QuicReceivedPacket* GetWrite(size_t pos) { return writes_[pos].packet; }
[email protected]f702d572012-12-04 15:56:20241
242 bool AtEof() {
rch37de576c2015-05-17 20:28:17243 return socket_data_->AllReadDataConsumed() &&
244 socket_data_->AllWriteDataConsumed();
[email protected]f702d572012-12-04 15:56:20245 }
246
Ryan Hamilton8d9ee76e2018-05-29 23:52:52247 void ProcessPacket(std::unique_ptr<quic::QuicReceivedPacket> packet) {
fayang91ca2012016-11-22 07:42:46248 connection_->ProcessUdpPacket(
Ryan Hamilton8d9ee76e2018-05-29 23:52:52249 quic::QuicSocketAddress(quic::QuicSocketAddressImpl(self_addr_)),
250 quic::QuicSocketAddress(quic::QuicSocketAddressImpl(peer_addr_)),
251 *packet);
[email protected]f702d572012-12-04 15:56:20252 }
253
254 // Configures the test fixture to use the list of expected writes.
255 void Initialize() {
256 mock_writes_.reset(new MockWrite[writes_.size()]);
257 for (size_t i = 0; i < writes_.size(); i++) {
rtenneti15656ae2016-01-23 03:05:03258 if (writes_[i].packet == nullptr) {
259 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].rv, i);
260 } else {
261 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].packet->data(),
262 writes_[i].packet->length());
263 }
bnc614a92d32016-04-04 13:56:07264 }
[email protected]f702d572012-12-04 15:56:20265
rtennetibe635732014-10-02 22:51:42266 socket_data_.reset(new StaticSocketDataProvider(
Ryan Sleevib8d7ea02018-05-07 20:01:01267 base::span<MockRead>(),
268 base::make_span(mock_writes_.get(), writes_.size())));
[email protected]f702d572012-12-04 15:56:20269
danakjad1777e2016-04-16 00:56:42270 std::unique_ptr<MockUDPClientSocket> socket(new MockUDPClientSocket(
xunjielib53b38c2016-03-24 15:54:36271 socket_data_.get(), net_log_.bound().net_log()));
[email protected]e13201d82012-12-12 05:00:32272 socket->Connect(peer_addr_);
[email protected]f702d572012-12-04 15:56:20273 runner_ = new TestTaskRunner(&clock_);
Ryan Hamilton8d9ee76e2018-05-29 23:52:52274 send_algorithm_ = new quic::test::MockSendAlgorithm();
rch7dd15702015-07-01 18:57:57275 EXPECT_CALL(*send_algorithm_, InRecovery()).WillRepeatedly(Return(false));
276 EXPECT_CALL(*send_algorithm_, InSlowStart()).WillRepeatedly(Return(false));
rjshaded5ced072015-12-18 19:26:02277 EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
Dan Zhangf11470172017-09-18 22:02:09278 .Times(testing::AtLeast(1));
rtenneti44f4a2e2015-08-07 14:00:07279 EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
Ryan Hamilton8d9ee76e2018-05-29 23:52:52280 .WillRepeatedly(Return(quic::kMaxPacketSize));
jokulik0e0a00c32016-06-13 21:51:58281 EXPECT_CALL(*send_algorithm_, PacingRate(_))
Ryan Hamilton8d9ee76e2018-05-29 23:52:52282 .WillRepeatedly(Return(quic::QuicBandwidth::Zero()));
Michael Warres74ee3ce2017-10-09 15:26:37283 EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true));
rtenneti44f4a2e2015-08-07 14:00:07284 EXPECT_CALL(*send_algorithm_, BandwidthEstimate())
Ryan Hamilton8d9ee76e2018-05-29 23:52:52285 .WillRepeatedly(Return(quic::QuicBandwidth::Zero()));
rch1e543ec2015-03-29 07:04:40286 EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(AnyNumber());
rch08cae032017-03-29 00:59:15287 EXPECT_CALL(*send_algorithm_, OnApplicationLimited(_)).Times(AnyNumber());
rch0d5bcf62017-05-24 22:48:45288 EXPECT_CALL(*send_algorithm_, GetCongestionControlType())
289 .Times(AnyNumber());
rch16c74d1d2016-04-22 06:14:07290 helper_.reset(
291 new QuicChromiumConnectionHelper(&clock_, &random_generator_));
292 alarm_factory_.reset(new QuicChromiumAlarmFactory(runner_.get(), &clock_));
293
Michael Warres74ee3ce2017-10-09 15:26:37294 connection_ = new TestQuicConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:52295 quic::test::SupportedVersions(
296 quic::ParsedQuicVersion(quic::PROTOCOL_QUIC_CRYPTO, version_)),
Dan Zhangfefaf5b2017-12-11 17:06:24297 connection_id_, peer_addr_, helper_.get(), alarm_factory_.get(),
Ryan Hamilton9edcf1a2017-11-22 05:55:17298 new QuicChromiumPacketWriter(
299 socket.get(), base::ThreadTaskRunnerHandle::Get().get()));
[email protected]f702d572012-12-04 15:56:20300 connection_->set_visitor(&visitor_);
[email protected]fee17f72013-02-03 07:47:41301 connection_->SetSendAlgorithm(send_algorithm_);
rch03b7a202016-02-05 00:54:20302
303 // Load a certificate that is valid for *.example.org
304 scoped_refptr<X509Certificate> test_cert(
305 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
306 EXPECT_TRUE(test_cert.get());
307
308 verify_details_.cert_verify_result.verified_cert = test_cert;
309 verify_details_.cert_verify_result.is_issued_by_known_root = true;
310 crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details_);
311
xunjieli84adaab2016-09-20 01:12:28312 base::TimeTicks dns_end = base::TimeTicks::Now();
313 base::TimeTicks dns_start = dns_end - base::TimeDelta::FromMilliseconds(1);
ckrasic4f9d88d2015-07-22 22:23:16314 session_.reset(new QuicChromiumClientSession(
xunjielib53b38c2016-03-24 15:54:36315 connection_, std::move(socket),
rtenneti1cd3b162015-09-29 02:58:28316 /*stream_factory=*/nullptr, &crypto_client_stream_factory_, &clock_,
Nick Harper89bc7212018-07-31 19:07:57317 &transport_security_state_, /*ssl_config_service=*/nullptr,
danakjad1777e2016-04-16 00:56:42318 base::WrapUnique(static_cast<QuicServerInfo*>(nullptr)),
Paul Jensen8e3c5d32018-02-19 17:06:33319 QuicSessionKey(kDefaultServerHostName, kDefaultServerPort,
320 PRIVACY_MODE_DISABLED, SocketTag()),
Zhongyi Shi757fcce2018-06-27 05:41:27321 /*require_confirmation=*/false, /*migrate_session_early_v2=*/false,
322 /*migrate_session_on_network_change_v2=*/false,
Renjiea5722ccf2018-08-10 00:18:49323 /*go_away_on_path_degrading*/ false,
Zhongyi Shi757fcce2018-06-27 05:41:27324 /*default_network=*/NetworkChangeNotifier::kInvalidNetworkHandle,
Zhongyi Shi73f23ca872017-12-13 18:37:13325 base::TimeDelta::FromSeconds(kMaxTimeOnNonDefaultNetworkSecs),
Zhongyi Shiee760762018-08-01 00:54:29326 kMaxMigrationsToNonDefaultNetworkOnWriteError,
Zhongyi Shi8b1e43f2017-12-13 20:46:30327 kMaxMigrationsToNonDefaultNetworkOnPathDegrading,
Zhongyi Shi5f587cc2017-11-21 23:24:17328 kQuicYieldAfterPacketsRead,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52329 quic::QuicTime::Delta::FromMilliseconds(
330 kQuicYieldAfterDurationMilliseconds),
Yixin Wang079ad542018-01-11 04:06:05331 client_headers_include_h2_stream_dependency_, /*cert_verify_flags=*/0,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52332 quic::test::DefaultQuicConfig(), &crypto_config_, "CONNECTION_UNKNOWN",
333 dns_start, dns_end, &push_promise_index_, nullptr,
xunjieli84adaab2016-09-20 01:12:28334 base::ThreadTaskRunnerHandle::Get().get(),
xunjieli5fafe142016-03-23 23:32:54335 /*socket_performance_watcher=*/nullptr, net_log_.bound().net_log()));
rtennetid39bd762015-06-12 01:05:52336 session_->Initialize();
xunjieli100937eb52016-09-15 20:09:37337 TestCompletionCallback callback;
rchf0b18c8a2017-05-05 19:31:57338
rch433bf5f2017-02-14 04:10:47339 session_->CryptoConnect(callback.callback());
Ryan Hamilton6c2a2a82017-12-15 02:06:28340 stream_ = std::make_unique<QuicHttpStream>(
341 session_->CreateHandle(HostPortPair("www.example.org", 443)));
342 promised_stream_ = std::make_unique<QuicHttpStream>(
343 session_->CreateHandle(HostPortPair("www.example.org", 443)));
ckrasic3865ee0f2016-02-29 22:04:56344 push_promise_[":path"] = "/bar";
345 push_promise_[":authority"] = "www.example.org";
346 push_promise_[":version"] = "HTTP/1.1";
347 push_promise_[":method"] = "GET";
348 push_promise_[":scheme"] = "https";
349
350 promised_response_[":status"] = "200 OK";
351 promised_response_[":version"] = "HTTP/1.1";
352 promised_response_["content-type"] = "text/plain";
353
Ryan Hamilton8d9ee76e2018-05-29 23:52:52354 promise_url_ = quic::SpdyUtils::GetPromisedUrlFromHeaders(push_promise_);
[email protected]6cca996b2013-01-25 07:43:36355 }
356
bnc614a92d32016-04-04 13:56:07357 void SetRequest(const string& method,
358 const string& path,
[email protected]1e960032013-12-20 19:00:20359 RequestPriority priority) {
rchcd379012017-04-12 21:53:32360 request_headers_ = client_maker_.GetRequestHeaders(method, "https", path);
[email protected]6cca996b2013-01-25 07:43:36361 }
362
bnc614a92d32016-04-04 13:56:07363 void SetResponse(const string& status, const string& body) {
alyssar2adf3ac2016-05-03 17:12:58364 response_headers_ = server_maker_.GetResponseHeaders(status);
[email protected]92bf17c2014-03-03 21:14:03365 response_data_ = body;
[email protected]6cca996b2013-01-25 07:43:36366 }
[email protected]f702d572012-12-04 15:56:20367
Ryan Hamilton8d9ee76e2018-05-29 23:52:52368 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructDataPacket(
369 quic::QuicPacketNumber packet_number,
370 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56371 bool should_include_version,
372 bool fin,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52373 quic::QuicStreamOffset offset,
374 quic::QuicStringPiece data,
alyssar2adf3ac2016-05-03 17:12:58375 QuicTestPacketMaker* maker) {
376 return maker->MakeDataPacket(packet_number, stream_id,
ckrasic3865ee0f2016-02-29 22:04:56377 should_include_version, fin, offset, data);
378 }
379
Ryan Hamilton8d9ee76e2018-05-29 23:52:52380 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientDataPacket(
381 quic::QuicPacketNumber packet_number,
[email protected]e8ff26842013-03-22 21:02:05382 bool should_include_version,
[email protected]f702d572012-12-04 15:56:20383 bool fin,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52384 quic::QuicStreamOffset offset,
385 quic::QuicStringPiece data) {
ckrasic3865ee0f2016-02-29 22:04:56386 return InnerConstructDataPacket(packet_number, stream_id_,
alyssar2adf3ac2016-05-03 17:12:58387 should_include_version, fin, offset, data,
388 &client_maker_);
389 }
390
Ryan Hamilton8d9ee76e2018-05-29 23:52:52391 std::unique_ptr<quic::QuicReceivedPacket> ConstructServerDataPacket(
392 quic::QuicPacketNumber packet_number,
alyssar2adf3ac2016-05-03 17:12:58393 bool should_include_version,
394 bool fin,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52395 quic::QuicStreamOffset offset,
396 quic::QuicStringPiece data) {
alyssar2adf3ac2016-05-03 17:12:58397 return InnerConstructDataPacket(packet_number, stream_id_,
398 should_include_version, fin, offset, data,
399 &server_maker_);
ckrasic3865ee0f2016-02-29 22:04:56400 }
401
Ryan Hamilton8d9ee76e2018-05-29 23:52:52402 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructRequestHeadersPacket(
403 quic::QuicPacketNumber packet_number,
404 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56405 bool should_include_version,
406 bool fin,
407 RequestPriority request_priority,
xunjieli100937eb52016-09-15 20:09:37408 size_t* spdy_headers_frame_length,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52409 quic::QuicStreamOffset* offset) {
Yixin Wang7a3f1b8d2018-01-17 21:40:48410 return InnerConstructRequestHeadersPacket(
411 packet_number, stream_id, should_include_version, fin, request_priority,
412 0, spdy_headers_frame_length, offset);
413 }
414
Ryan Hamilton8d9ee76e2018-05-29 23:52:52415 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructRequestHeadersPacket(
416 quic::QuicPacketNumber packet_number,
417 quic::QuicStreamId stream_id,
Yixin Wang7a3f1b8d2018-01-17 21:40:48418 bool should_include_version,
419 bool fin,
420 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52421 quic::QuicStreamId parent_stream_id,
Yixin Wang7a3f1b8d2018-01-17 21:40:48422 size_t* spdy_headers_frame_length,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52423 quic::QuicStreamOffset* offset) {
Ryan Hamilton0239aac2018-05-19 00:03:13424 spdy::SpdyPriority priority =
ckrasic3865ee0f2016-02-29 22:04:56425 ConvertRequestPriorityToQuicPriority(request_priority);
alyssar2adf3ac2016-05-03 17:12:58426 return client_maker_.MakeRequestHeadersPacket(
ckrasic3865ee0f2016-02-29 22:04:56427 packet_number, stream_id, should_include_version, fin, priority,
Yixin Wang7a3f1b8d2018-01-17 21:40:48428 std::move(request_headers_), parent_stream_id,
429 spdy_headers_frame_length, offset);
[email protected]f702d572012-12-04 15:56:20430 }
431
Ryan Hamilton8d9ee76e2018-05-29 23:52:52432 std::unique_ptr<quic::QuicReceivedPacket>
Yixin Wange7ecc472018-03-06 19:00:25433 ConstructRequestHeadersAndDataFramesPacket(
Ryan Hamilton8d9ee76e2018-05-29 23:52:52434 quic::QuicPacketNumber packet_number,
435 quic::QuicStreamId stream_id,
Yixin Wange7ecc472018-03-06 19:00:25436 bool should_include_version,
437 bool fin,
438 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52439 quic::QuicStreamId parent_stream_id,
440 quic::QuicStreamOffset* offset,
Yixin Wange7ecc472018-03-06 19:00:25441 size_t* spdy_headers_frame_length,
442 const std::vector<std::string>& data_writes) {
Ryan Hamilton0239aac2018-05-19 00:03:13443 spdy::SpdyPriority priority =
Yixin Wange7ecc472018-03-06 19:00:25444 ConvertRequestPriorityToQuicPriority(request_priority);
445 return client_maker_.MakeRequestHeadersAndMultipleDataFramesPacket(
446 packet_number, stream_id, should_include_version, fin, priority,
447 std::move(request_headers_), parent_stream_id, offset,
448 spdy_headers_frame_length, data_writes);
449 }
450
Ryan Hamilton8d9ee76e2018-05-29 23:52:52451 std::unique_ptr<quic::QuicReceivedPacket> ConstructRequestAndRstPacket(
452 quic::QuicPacketNumber packet_number,
453 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,
Yixin Wange7ecc472018-03-06 19:00:25458 size_t* spdy_headers_frame_length,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52459 quic::QuicStreamOffset* header_stream_offset,
460 quic::QuicRstStreamErrorCode error_code,
Yixin Wange7ecc472018-03-06 19:00:25461 size_t bytes_written) {
Ryan Hamilton0239aac2018-05-19 00:03:13462 spdy::SpdyPriority priority =
Yixin Wange7ecc472018-03-06 19:00:25463 ConvertRequestPriorityToQuicPriority(request_priority);
464 return client_maker_.MakeRequestHeadersAndRstPacket(
465 packet_number, stream_id, should_include_version, fin, priority,
466 std::move(request_headers_), parent_stream_id,
467 spdy_headers_frame_length, header_stream_offset, error_code,
468 bytes_written);
469 }
470
Ryan Hamilton8d9ee76e2018-05-29 23:52:52471 std::unique_ptr<quic::QuicReceivedPacket> ConstructRequestHeadersPacket(
472 quic::QuicPacketNumber packet_number,
rtennetif4bdb542015-01-21 14:33:05473 bool fin,
sclittlec4dc1a32015-09-24 00:15:45474 RequestPriority request_priority,
475 size_t* spdy_headers_frame_length) {
ckrasic3865ee0f2016-02-29 22:04:56476 return InnerConstructRequestHeadersPacket(
477 packet_number, stream_id_, kIncludeVersion, fin, request_priority,
xunjieli100937eb52016-09-15 20:09:37478 spdy_headers_frame_length, nullptr);
ckrasic3865ee0f2016-02-29 22:04:56479 }
480
Ryan Hamilton8d9ee76e2018-05-29 23:52:52481 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructResponseHeadersPacket(
482 quic::QuicPacketNumber packet_number,
483 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56484 bool fin,
485 size_t* spdy_headers_frame_length) {
alyssar2adf3ac2016-05-03 17:12:58486 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26487 packet_number, stream_id, !kIncludeVersion, fin,
488 std::move(response_headers_), spdy_headers_frame_length,
489 &response_offset_);
[email protected]1e960032013-12-20 19:00:20490 }
491
Ryan Hamilton8d9ee76e2018-05-29 23:52:52492 std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseHeadersPacket(
493 quic::QuicPacketNumber packet_number,
sclittlec4dc1a32015-09-24 00:15:45494 bool fin,
495 size_t* spdy_headers_frame_length) {
ckrasic3865ee0f2016-02-29 22:04:56496 return InnerConstructResponseHeadersPacket(packet_number, stream_id_, fin,
497 spdy_headers_frame_length);
[email protected]1e960032013-12-20 19:00:20498 }
499
Ryan Hamilton8d9ee76e2018-05-29 23:52:52500 std::unique_ptr<quic::QuicReceivedPacket>
501 ConstructResponseHeadersPacketWithOffset(quic::QuicPacketNumber packet_number,
502 bool fin,
503 size_t* spdy_headers_frame_length,
504 quic::QuicStreamOffset* offset) {
alyssar2adf3ac2016-05-03 17:12:58505 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26506 packet_number, stream_id_, !kIncludeVersion, fin,
507 std::move(response_headers_), spdy_headers_frame_length, offset);
xunjieli34291fe12016-03-02 13:58:38508 }
509
Ryan Hamilton8d9ee76e2018-05-29 23:52:52510 std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseTrailersPacket(
511 quic::QuicPacketNumber packet_number,
xunjieli34291fe12016-03-02 13:58:38512 bool fin,
Ryan Hamilton0239aac2018-05-19 00:03:13513 spdy::SpdyHeaderBlock trailers,
xunjieli34291fe12016-03-02 13:58:38514 size_t* spdy_headers_frame_length,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52515 quic::QuicStreamOffset* offset) {
alyssar2adf3ac2016-05-03 17:12:58516 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26517 packet_number, stream_id_, !kIncludeVersion, fin, std::move(trailers),
alyssar2adf3ac2016-05-03 17:12:58518 spdy_headers_frame_length, offset);
xunjieli34291fe12016-03-02 13:58:38519 }
520
Ryan Hamilton8d9ee76e2018-05-29 23:52:52521 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientRstStreamPacket(
522 quic::QuicPacketNumber packet_number) {
alyssara72f5352016-10-20 12:45:16523 return client_maker_.MakeRstPacket(packet_number, true, stream_id_,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52524 quic::QUIC_RST_ACKNOWLEDGEMENT);
[email protected]06ff5152013-08-29 01:03:05525 }
526
Ryan Hamilton8d9ee76e2018-05-29 23:52:52527 std::unique_ptr<quic::QuicReceivedPacket>
528 ConstructClientRstStreamCancelledPacket(
529 quic::QuicPacketNumber packet_number) {
alyssar2adf3ac2016-05-03 17:12:58530 return client_maker_.MakeRstPacket(packet_number, !kIncludeVersion,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52531 stream_id_, quic::QUIC_STREAM_CANCELLED);
rtenneti6bd660b2015-07-18 00:19:53532 }
533
Ryan Hamilton8d9ee76e2018-05-29 23:52:52534 std::unique_ptr<quic::QuicReceivedPacket>
535 ConstructClientRstStreamVaryMismatchPacket(
536 quic::QuicPacketNumber packet_number) {
alyssar2adf3ac2016-05-03 17:12:58537 return client_maker_.MakeRstPacket(packet_number, !kIncludeVersion,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52538 promise_id_,
539 quic::QUIC_PROMISE_VARY_MISMATCH);
ckrasic3865ee0f2016-02-29 22:04:56540 }
541
Fan Yang550c6282018-06-22 18:53:25542 std::unique_ptr<quic::QuicReceivedPacket>
543 ConstructClientRstStreamVaryMismatchAndRequestHeadersPacket(
544 quic::QuicPacketNumber packet_number,
545 quic::QuicStreamId stream_id,
546 bool should_include_version,
547 bool fin,
548 RequestPriority request_priority,
549 quic::QuicStreamId parent_stream_id,
550 size_t* spdy_headers_frame_length,
551 quic::QuicStreamOffset* offset) {
552 spdy::SpdyPriority priority =
553 ConvertRequestPriorityToQuicPriority(request_priority);
554 return client_maker_.MakeRstAndRequestHeadersPacket(
555 packet_number, should_include_version, promise_id_,
556 quic::QUIC_PROMISE_VARY_MISMATCH, stream_id, fin, priority,
557 std::move(request_headers_), parent_stream_id,
558 spdy_headers_frame_length, offset);
559 }
560
Ryan Hamilton8d9ee76e2018-05-29 23:52:52561 std::unique_ptr<quic::QuicReceivedPacket> ConstructAckAndRstStreamPacket(
562 quic::QuicPacketNumber packet_number,
563 quic::QuicPacketNumber largest_received,
564 quic::QuicPacketNumber smallest_received,
565 quic::QuicPacketNumber least_unacked) {
alyssar2adf3ac2016-05-03 17:12:58566 return client_maker_.MakeAckAndRstPacket(
Ryan Hamilton8d9ee76e2018-05-29 23:52:52567 packet_number, !kIncludeVersion, stream_id_,
568 quic::QUIC_STREAM_CANCELLED, largest_received, smallest_received,
569 least_unacked, !kIncludeCongestionFeedback);
xunjieli34291fe12016-03-02 13:58:38570 }
571
Ryan Hamilton8d9ee76e2018-05-29 23:52:52572 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientRstStreamErrorPacket(
573 quic::QuicPacketNumber packet_number,
maksim.sisov84e20c92016-06-23 08:49:34574 bool include_version) {
575 return client_maker_.MakeRstPacket(packet_number, include_version,
576 stream_id_,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52577 quic::QUIC_ERROR_PROCESSING_STREAM);
maksim.sisov84e20c92016-06-23 08:49:34578 }
579
Ryan Hamilton8d9ee76e2018-05-29 23:52:52580 std::unique_ptr<quic::QuicReceivedPacket> ConstructAckAndRstStreamPacket(
581 quic::QuicPacketNumber packet_number) {
xunjieli34291fe12016-03-02 13:58:38582 return ConstructAckAndRstStreamPacket(packet_number, 2, 1, 1);
[email protected]c5e1aca2014-01-30 04:03:04583 }
584
Ryan Hamilton8d9ee76e2018-05-29 23:52:52585 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientAckPacket(
586 quic::QuicPacketNumber packet_number,
587 quic::QuicPacketNumber largest_received,
588 quic::QuicPacketNumber smallest_received,
589 quic::QuicPacketNumber least_unacked) {
alyssar2adf3ac2016-05-03 17:12:58590 return client_maker_.MakeAckPacket(packet_number, largest_received,
wangyix6444ffe2017-04-25 17:49:49591 smallest_received, least_unacked,
alyssar2adf3ac2016-05-03 17:12:58592 !kIncludeCongestionFeedback);
593 }
594
Ryan Hamilton8d9ee76e2018-05-29 23:52:52595 std::unique_ptr<quic::QuicReceivedPacket> ConstructServerAckPacket(
596 quic::QuicPacketNumber packet_number,
597 quic::QuicPacketNumber largest_received,
598 quic::QuicPacketNumber smallest_received,
599 quic::QuicPacketNumber least_unacked) {
alyssar2adf3ac2016-05-03 17:12:58600 return server_maker_.MakeAckPacket(packet_number, largest_received,
wangyix6444ffe2017-04-25 17:49:49601 smallest_received, least_unacked,
alyssar2adf3ac2016-05-03 17:12:58602 !kIncludeCongestionFeedback);
[email protected]63534512012-12-23 18:49:00603 }
604
Ryan Hamilton8d9ee76e2018-05-29 23:52:52605 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientPriorityPacket(
606 quic::QuicPacketNumber packet_number,
Yixin Wangb470bc882018-02-15 18:43:57607 bool should_include_version,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52608 quic::QuicStreamId id,
609 quic::QuicStreamId parent_stream_id,
Yixin Wangb470bc882018-02-15 18:43:57610 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52611 quic::QuicStreamOffset* header_stream_offset) {
Yixin Wangb470bc882018-02-15 18:43:57612 return client_maker_.MakePriorityPacket(
613 packet_number, should_include_version, id, parent_stream_id,
614 ConvertRequestPriorityToQuicPriority(request_priority),
615 header_stream_offset);
616 }
617
Ryan Hamilton8d9ee76e2018-05-29 23:52:52618 std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket(
619 quic::QuicStreamOffset* offset) {
rch5cb522462017-04-25 20:18:36620 return client_maker_.MakeInitialSettingsPacket(1, offset);
fayang3bcb8b502016-12-07 21:44:37621 }
622
Ryan Hamilton8d9ee76e2018-05-29 23:52:52623 void ReceivePromise(quic::QuicStreamId id) {
624 auto headers = quic::test::AsHeaderList(push_promise_);
rch08e198572017-05-09 16:56:55625 QuicChromiumClientStream::Handle* stream =
ckrasic3865ee0f2016-02-29 22:04:56626 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
ckrasic32b17dcd2016-10-31 06:15:35627 stream->OnPromiseHeaderList(id, headers.uncompressed_header_bytes(),
628 headers);
ckrasic3865ee0f2016-02-29 22:04:56629 }
630
xunjieli84adaab2016-09-20 01:12:28631 void ExpectLoadTimingValid(const LoadTimingInfo& load_timing_info,
xunjieli100937eb52016-09-15 20:09:37632 bool session_reused) {
633 EXPECT_EQ(session_reused, load_timing_info.socket_reused);
xunjieli84adaab2016-09-20 01:12:28634 if (session_reused) {
635 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
636 } else {
637 ExpectConnectTimingHasTimes(
638 load_timing_info.connect_timing,
639 CONNECT_TIMING_HAS_SSL_TIMES | CONNECT_TIMING_HAS_DNS_TIMES);
640 }
641 ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info);
xunjieli100937eb52016-09-15 20:09:37642 }
643
Ryan Hamilton8d9ee76e2018-05-29 23:52:52644 quic::QuicStreamId GetNthClientInitiatedStreamId(int n) {
645 return quic::test::GetNthClientInitiatedStreamId(version_, n);
ckrasicbf2f59c2017-05-04 23:54:36646 }
647
Ryan Hamilton8d9ee76e2018-05-29 23:52:52648 quic::QuicStreamId GetNthServerInitiatedStreamId(int n) {
649 return quic::test::GetNthServerInitiatedStreamId(version_, n);
ckrasicbf2f59c2017-05-04 23:54:36650 }
651
Ryan Hamilton8d9ee76e2018-05-29 23:52:52652 const quic::QuicTransportVersion version_;
Yixin Wang079ad542018-01-11 04:06:05653 const bool client_headers_include_h2_stream_dependency_;
654
xunjieli5fafe142016-03-23 23:32:54655 BoundTestNetLog net_log_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52656 quic::test::MockSendAlgorithm* send_algorithm_;
[email protected]f702d572012-12-04 15:56:20657 scoped_refptr<TestTaskRunner> runner_;
danakjad1777e2016-04-16 00:56:42658 std::unique_ptr<MockWrite[]> mock_writes_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52659 quic::MockClock clock_;
[email protected]f702d572012-12-04 15:56:20660 TestQuicConnection* connection_;
danakjad1777e2016-04-16 00:56:42661 std::unique_ptr<QuicChromiumConnectionHelper> helper_;
rch16c74d1d2016-04-22 06:14:07662 std::unique_ptr<QuicChromiumAlarmFactory> alarm_factory_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52663 testing::StrictMock<quic::test::MockQuicConnectionVisitor> visitor_;
rch97827ee2017-05-24 23:49:12664 std::unique_ptr<UploadDataStream> upload_data_stream_;
danakjad1777e2016-04-16 00:56:42665 std::unique_ptr<QuicHttpStream> stream_;
[email protected]5db452202014-08-19 05:22:15666 TransportSecurityState transport_security_state_;
danakjad1777e2016-04-16 00:56:42667 std::unique_ptr<QuicChromiumClientSession> session_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52668 quic::QuicCryptoClientConfig crypto_config_;
[email protected]f702d572012-12-04 15:56:20669 TestCompletionCallback callback_;
670 HttpRequestInfo request_;
671 HttpRequestHeaders headers_;
672 HttpResponseInfo response_;
673 scoped_refptr<IOBufferWithSize> read_buffer_;
Ryan Hamilton0239aac2018-05-19 00:03:13674 spdy::SpdyHeaderBlock request_headers_;
675 spdy::SpdyHeaderBlock response_headers_;
bnc614a92d32016-04-04 13:56:07676 string request_data_;
677 string response_data_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52678 quic::QuicClientPushPromiseIndex push_promise_index_;
[email protected]f702d572012-12-04 15:56:20679
ckrasic3865ee0f2016-02-29 22:04:56680 // For server push testing
danakjad1777e2016-04-16 00:56:42681 std::unique_ptr<QuicHttpStream> promised_stream_;
Ryan Hamilton0239aac2018-05-19 00:03:13682 spdy::SpdyHeaderBlock push_promise_;
683 spdy::SpdyHeaderBlock promised_response_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52684 const quic::QuicStreamId promise_id_;
ckrasic3865ee0f2016-02-29 22:04:56685 string promise_url_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52686 const quic::QuicStreamId stream_id_;
ckrasic3865ee0f2016-02-29 22:04:56687
Ryan Hamilton8d9ee76e2018-05-29 23:52:52688 const quic::QuicConnectionId connection_id_;
alyssar2adf3ac2016-05-03 17:12:58689 QuicTestPacketMaker client_maker_;
690 QuicTestPacketMaker server_maker_;
[email protected]f702d572012-12-04 15:56:20691 IPEndPoint self_addr_;
692 IPEndPoint peer_addr_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52693 quic::test::MockRandom random_generator_;
rch03b7a202016-02-05 00:54:20694 ProofVerifyDetailsChromium verify_details_;
[email protected]e8ff26842013-03-22 21:02:05695 MockCryptoClientStreamFactory crypto_client_stream_factory_;
danakjad1777e2016-04-16 00:56:42696 std::unique_ptr<StaticSocketDataProvider> socket_data_;
[email protected]f702d572012-12-04 15:56:20697 std::vector<PacketToWrite> writes_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52698 quic::QuicStreamOffset response_offset_;
[email protected]f702d572012-12-04 15:56:20699};
700
Yixin Wang079ad542018-01-11 04:06:05701INSTANTIATE_TEST_CASE_P(
Bence Békyce380cb2018-04-26 23:39:55702 VersionIncludeStreamDependencySequence,
Yixin Wang079ad542018-01-11 04:06:05703 QuicHttpStreamTest,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52704 ::testing::Combine(
705 ::testing::ValuesIn(quic::AllSupportedTransportVersions()),
706 ::testing::Bool()));
[email protected]1e960032013-12-20 19:00:20707
708TEST_P(QuicHttpStreamTest, RenewStreamForAuth) {
[email protected]ed3fc15d2013-03-08 18:37:44709 Initialize();
rtennetibe635732014-10-02 22:51:42710 EXPECT_EQ(nullptr, stream_->RenewStreamForAuth());
[email protected]f702d572012-12-04 15:56:20711}
712
mmenkebd84c392015-09-02 14:12:34713TEST_P(QuicHttpStreamTest, CanReuseConnection) {
[email protected]ed3fc15d2013-03-08 18:37:44714 Initialize();
mmenkebd84c392015-09-02 14:12:34715 EXPECT_FALSE(stream_->CanReuseConnection());
[email protected]f702d572012-12-04 15:56:20716}
717
jri231c2972016-03-08 19:50:11718TEST_P(QuicHttpStreamTest, DisableConnectionMigrationForStream) {
Zhongyi Shibb28b1f2018-07-18 02:41:26719 request_.load_flags |= LOAD_DISABLE_CONNECTION_MIGRATION_TO_CELLULAR;
jri231c2972016-03-08 19:50:11720 Initialize();
xunjieli5fafe142016-03-23 23:32:54721 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27722 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:54723 net_log_.bound(), callback_.callback()));
rch08e198572017-05-09 16:56:55724 QuicChromiumClientStream::Handle* client_stream =
jri231c2972016-03-08 19:50:11725 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
Zhongyi Shibb28b1f2018-07-18 02:41:26726 EXPECT_FALSE(client_stream->can_migrate_to_cellular_network());
jri231c2972016-03-08 19:50:11727}
728
[email protected]1e960032013-12-20 19:00:20729TEST_P(QuicHttpStreamTest, GetRequest) {
730 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:45731 size_t spdy_request_header_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52732 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:36733 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:37734 AddWrite(InnerConstructRequestHeadersPacket(
ckrasicbf2f59c2017-05-04 23:54:36735 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, kFin,
736 DEFAULT_PRIORITY, &spdy_request_header_frame_length,
737 &header_stream_offset));
fayang3bcb8b502016-12-07 21:44:37738
[email protected]f702d572012-12-04 15:56:20739 Initialize();
740
741 request_.method = "GET";
rchcd379012017-04-12 21:53:32742 request_.url = GURL("https://www.example.org/");
[email protected]f702d572012-12-04 15:56:20743
xunjieli100937eb52016-09-15 20:09:37744 // Make sure getting load timing from the stream early does not crash.
745 LoadTimingInfo load_timing_info;
746 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
747
xunjieli5fafe142016-03-23 23:32:54748 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27749 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:54750 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:02751 EXPECT_EQ(OK,
752 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20753
754 // Ack the request.
wangyix6444ffe2017-04-25 17:49:49755 ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
[email protected]f702d572012-12-04 15:56:20756
robpercival214763f2016-07-01 23:27:01757 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
758 IsError(ERR_IO_PENDING));
[email protected]f702d572012-12-04 15:56:20759
bnc614a92d32016-04-04 13:56:07760 SetResponse("404 Not Found", string());
sclittlec4dc1a32015-09-24 00:15:45761 size_t spdy_response_header_frame_length;
762 ProcessPacket(ConstructResponseHeadersPacket(
763 2, kFin, &spdy_response_header_frame_length));
[email protected]f702d572012-12-04 15:56:20764
765 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:01766 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]cadac622013-06-11 16:46:36767 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:20768 EXPECT_EQ(404, response_.headers->response_code());
769 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
[email protected]6ed67432014-06-24 01:53:53770 EXPECT_FALSE(response_.response_time.is_null());
771 EXPECT_FALSE(response_.request_time.is_null());
[email protected]f702d572012-12-04 15:56:20772
773 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:02774 EXPECT_EQ(0,
775 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
776 callback_.callback()));
[email protected]f702d572012-12-04 15:56:20777 EXPECT_TRUE(stream_->IsResponseBodyComplete());
778 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:10779
xunjieli100937eb52016-09-15 20:09:37780 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
xunjieli84adaab2016-09-20 01:12:28781 ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
xunjieli100937eb52016-09-15 20:09:37782
sclittle1edeeb22015-09-02 20:46:10783 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:45784 // headers and payload.
785 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
786 stream_->GetTotalSentBytes());
787 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length),
788 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:20789}
790
xunjieli100937eb52016-09-15 20:09:37791TEST_P(QuicHttpStreamTest, LoadTimingTwoRequests) {
792 SetRequest("GET", "/", DEFAULT_PRIORITY);
793 size_t spdy_request_header_frame_length;
794
Ryan Hamilton8d9ee76e2018-05-29 23:52:52795 quic::QuicStreamOffset offset = 0;
rch5cb522462017-04-25 20:18:36796 AddWrite(ConstructInitialSettingsPacket(&offset));
xunjieli100937eb52016-09-15 20:09:37797 AddWrite(InnerConstructRequestHeadersPacket(
ckrasicbf2f59c2017-05-04 23:54:36798 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, kFin,
799 DEFAULT_PRIORITY, &spdy_request_header_frame_length, &offset));
xunjieli100937eb52016-09-15 20:09:37800
801 // SetRequest() again for second request as |request_headers_| was moved.
802 SetRequest("GET", "/", DEFAULT_PRIORITY);
803 AddWrite(InnerConstructRequestHeadersPacket(
ckrasicbf2f59c2017-05-04 23:54:36804 3, GetNthClientInitiatedStreamId(1), kIncludeVersion, kFin,
Yixin Wang7a3f1b8d2018-01-17 21:40:48805 DEFAULT_PRIORITY, GetNthClientInitiatedStreamId(0),
806 &spdy_request_header_frame_length, &offset));
wangyix6444ffe2017-04-25 17:49:49807 AddWrite(ConstructClientAckPacket(4, 3, 1, 1)); // Ack the responses.
xunjieli100937eb52016-09-15 20:09:37808
809 Initialize();
810
811 request_.method = "GET";
rchcd379012017-04-12 21:53:32812 request_.url = GURL("https://www.example.org/");
xunjieli100937eb52016-09-15 20:09:37813 // Start first request.
814 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27815 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli100937eb52016-09-15 20:09:37816 net_log_.bound(), callback_.callback()));
817 EXPECT_EQ(OK,
818 stream_->SendRequest(headers_, &response_, callback_.callback()));
819
820 // Start a second request.
Ryan Hamilton6c2a2a82017-12-15 02:06:28821 QuicHttpStream stream2(
822 session_->CreateHandle(HostPortPair("www.example.org", 443)));
xunjieli100937eb52016-09-15 20:09:37823 TestCompletionCallback callback2;
824 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27825 stream2.InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli100937eb52016-09-15 20:09:37826 net_log_.bound(), callback2.callback()));
827 EXPECT_EQ(OK,
828 stream2.SendRequest(headers_, &response_, callback2.callback()));
829
830 // Ack both requests.
wangyix6444ffe2017-04-25 17:49:49831 ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
xunjieli100937eb52016-09-15 20:09:37832
833 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
834 IsError(ERR_IO_PENDING));
835 size_t spdy_response_header_frame_length;
836 SetResponse("200 OK", string());
837 ProcessPacket(InnerConstructResponseHeadersPacket(
ckrasicbf2f59c2017-05-04 23:54:36838 2, GetNthClientInitiatedStreamId(0), kFin,
839 &spdy_response_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37840
841 // Now that the headers have been processed, the callback will return.
842 EXPECT_THAT(callback_.WaitForResult(), IsOk());
843 EXPECT_EQ(200, response_.headers->response_code());
844
845 // There is no body, so this should return immediately.
846 EXPECT_EQ(0,
847 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
848 callback_.callback()));
849 EXPECT_TRUE(stream_->IsResponseBodyComplete());
850
851 LoadTimingInfo load_timing_info;
852 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
xunjieli84adaab2016-09-20 01:12:28853 ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
xunjieli100937eb52016-09-15 20:09:37854
855 // SetResponse() again for second request as |response_headers_| was moved.
856 SetResponse("200 OK", string());
857 EXPECT_THAT(stream2.ReadResponseHeaders(callback2.callback()),
858 IsError(ERR_IO_PENDING));
859
860 ProcessPacket(InnerConstructResponseHeadersPacket(
ckrasicbf2f59c2017-05-04 23:54:36861 3, GetNthClientInitiatedStreamId(1), kFin,
862 &spdy_response_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37863
864 EXPECT_THAT(callback2.WaitForResult(), IsOk());
865
866 // There is no body, so this should return immediately.
867 EXPECT_EQ(0,
868 stream2.ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
869 callback2.callback()));
870 EXPECT_TRUE(stream2.IsResponseBodyComplete());
871
872 LoadTimingInfo load_timing_info2;
873 EXPECT_TRUE(stream2.GetLoadTimingInfo(&load_timing_info2));
xunjieli84adaab2016-09-20 01:12:28874 ExpectLoadTimingValid(load_timing_info2, /*session_reused=*/true);
xunjieli100937eb52016-09-15 20:09:37875}
876
xunjieli34291fe12016-03-02 13:58:38877// QuicHttpStream does not currently support trailers. It should ignore
878// trailers upon receiving them.
879TEST_P(QuicHttpStreamTest, GetRequestWithTrailers) {
880 SetRequest("GET", "/", DEFAULT_PRIORITY);
881 size_t spdy_request_header_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52882 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:36883 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:37884 AddWrite(InnerConstructRequestHeadersPacket(
ckrasicbf2f59c2017-05-04 23:54:36885 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, kFin,
886 DEFAULT_PRIORITY, &spdy_request_header_frame_length,
887 &header_stream_offset));
wangyix6444ffe2017-04-25 17:49:49888 AddWrite(ConstructClientAckPacket(3, 3, 1, 1)); // Ack the data packet.
xunjieli34291fe12016-03-02 13:58:38889
890 Initialize();
891
892 request_.method = "GET";
rchcd379012017-04-12 21:53:32893 request_.url = GURL("https://www.example.org/");
xunjieli34291fe12016-03-02 13:58:38894
xunjieli5fafe142016-03-23 23:32:54895 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27896 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:54897 net_log_.bound(), callback_.callback()));
898
xunjieli34291fe12016-03-02 13:58:38899 EXPECT_EQ(OK,
900 stream_->SendRequest(headers_, &response_, callback_.callback()));
xunjieli34291fe12016-03-02 13:58:38901 // Ack the request.
wangyix6444ffe2017-04-25 17:49:49902 ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
xunjieli34291fe12016-03-02 13:58:38903
robpercival214763f2016-07-01 23:27:01904 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
905 IsError(ERR_IO_PENDING));
xunjieli34291fe12016-03-02 13:58:38906
bnc614a92d32016-04-04 13:56:07907 SetResponse("200 OK", string());
xunjieli34291fe12016-03-02 13:58:38908
909 // Send the response headers.
910 size_t spdy_response_header_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52911 quic::QuicStreamOffset offset = 0;
xunjieli34291fe12016-03-02 13:58:38912 ProcessPacket(ConstructResponseHeadersPacketWithOffset(
913 2, !kFin, &spdy_response_header_frame_length, &offset));
914 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:01915 EXPECT_THAT(callback_.WaitForResult(), IsOk());
xunjieli34291fe12016-03-02 13:58:38916 ASSERT_TRUE(response_.headers.get());
917 EXPECT_EQ(200, response_.headers->response_code());
918 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
919 EXPECT_FALSE(response_.response_time.is_null());
920 EXPECT_FALSE(response_.request_time.is_null());
921
922 // Send the response body.
923 const char kResponseBody[] = "Hello world!";
924 ProcessPacket(
alyssar2adf3ac2016-05-03 17:12:58925 ConstructServerDataPacket(3, false, !kFin, /*offset=*/0, kResponseBody));
Ryan Hamilton0239aac2018-05-19 00:03:13926 spdy::SpdyHeaderBlock trailers;
xunjieli34291fe12016-03-02 13:58:38927 size_t spdy_trailers_frame_length;
928 trailers["foo"] = "bar";
Ryan Hamilton8d9ee76e2018-05-29 23:52:52929 trailers[quic::kFinalOffsetHeaderKey] =
930 base::IntToString(strlen(kResponseBody));
xunjieli34291fe12016-03-02 13:58:38931 ProcessPacket(ConstructResponseTrailersPacket(
bnc086b39e12016-06-24 13:05:26932 4, kFin, std::move(trailers), &spdy_trailers_frame_length, &offset));
xunjieli34291fe12016-03-02 13:58:38933
934 // Make sure trailers are processed.
fdoray92e35a72016-06-10 15:54:55935 base::RunLoop().RunUntilIdle();
xunjieli34291fe12016-03-02 13:58:38936
937 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
938 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
939 callback_.callback()));
940 EXPECT_TRUE(stream_->IsResponseBodyComplete());
941
942 EXPECT_EQ(OK,
943 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
944 callback_.callback()));
945
946 EXPECT_TRUE(stream_->IsResponseBodyComplete());
947 EXPECT_TRUE(AtEof());
948
949 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
950 // headers and payload.
951 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
952 stream_->GetTotalSentBytes());
953 EXPECT_EQ(
954 static_cast<int64_t>(spdy_response_header_frame_length +
955 strlen(kResponseBody) + +spdy_trailers_frame_length),
956 stream_->GetTotalReceivedBytes());
xunjieli5fafe142016-03-23 23:32:54957 // Check that NetLog was filled as expected.
958 TestNetLogEntry::List entries;
959 net_log_.GetEntries(&entries);
960 size_t pos = ExpectLogContainsSomewhere(
961 entries, /*min_offset=*/0,
mikecirone8b85c432016-09-08 19:11:00962 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
963 NetLogEventPhase::NONE);
xunjieli5fafe142016-03-23 23:32:54964 pos = ExpectLogContainsSomewhere(
965 entries, /*min_offset=*/pos,
mikecirone8b85c432016-09-08 19:11:00966 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
967 NetLogEventPhase::NONE);
xunjieli5fafe142016-03-23 23:32:54968 ExpectLogContainsSomewhere(
969 entries, /*min_offset=*/pos,
mikecirone8b85c432016-09-08 19:11:00970 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
971 NetLogEventPhase::NONE);
xunjieli34291fe12016-03-02 13:58:38972}
973
[email protected]3e7dca62013-09-10 16:14:23974// Regression test for http://crbug.com/288128
[email protected]1e960032013-12-20 19:00:20975TEST_P(QuicHttpStreamTest, GetRequestLargeResponse) {
976 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:45977 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52978 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:36979 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:37980 AddWrite(InnerConstructRequestHeadersPacket(
ckrasicbf2f59c2017-05-04 23:54:36981 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, kFin,
982 DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
983 &header_stream_offset));
[email protected]3e7dca62013-09-10 16:14:23984 Initialize();
985
986 request_.method = "GET";
rchcd379012017-04-12 21:53:32987 request_.url = GURL("https://www.example.org/");
[email protected]3e7dca62013-09-10 16:14:23988
xunjieli5fafe142016-03-23 23:32:54989 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27990 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:54991 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:02992 EXPECT_EQ(OK,
993 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:23994
995 // Ack the request.
wangyix6444ffe2017-04-25 17:49:49996 ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
[email protected]3e7dca62013-09-10 16:14:23997
robpercival214763f2016-07-01 23:27:01998 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
999 IsError(ERR_IO_PENDING));
[email protected]3e7dca62013-09-10 16:14:231000
bnc086b39e12016-06-24 13:05:261001 response_headers_[":status"] = "200 OK";
1002 response_headers_[":version"] = "HTTP/1.1";
1003 response_headers_["content-type"] = "text/plain";
1004 response_headers_["big6"] = string(1000, 'x'); // Lots of x's.
[email protected]3e7dca62013-09-10 16:14:231005
sclittlec4dc1a32015-09-24 00:15:451006 size_t spdy_response_headers_frame_length;
1007 ProcessPacket(ConstructResponseHeadersPacket(
1008 2, kFin, &spdy_response_headers_frame_length));
[email protected]3e7dca62013-09-10 16:14:231009
1010 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:011011 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]3e7dca62013-09-10 16:14:231012 ASSERT_TRUE(response_.headers.get());
1013 EXPECT_EQ(200, response_.headers->response_code());
1014 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1015
1016 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:021017 EXPECT_EQ(0,
1018 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1019 callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:231020 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1021 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101022
1023 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451024 // headers and payload.
1025 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1026 stream_->GetTotalSentBytes());
1027 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length),
1028 stream_->GetTotalReceivedBytes());
[email protected]3e7dca62013-09-10 16:14:231029}
1030
rchf9f103cbc2014-08-30 05:28:041031// Regression test for http://crbug.com/409101
1032TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendRequest) {
1033 SetRequest("GET", "/", DEFAULT_PRIORITY);
1034 Initialize();
1035
1036 request_.method = "GET";
rchcd379012017-04-12 21:53:321037 request_.url = GURL("https://www.example.org/");
rchf9f103cbc2014-08-30 05:28:041038
xunjieli5fafe142016-03-23 23:32:541039 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271040 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541041 net_log_.bound(), callback_.callback()));
rchf9f103cbc2014-08-30 05:28:041042
jri78ec06a2016-03-31 18:19:401043 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521044 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rchf9f103cbc2014-08-30 05:28:041045
1046 EXPECT_EQ(ERR_CONNECTION_CLOSED,
rjshaded5ced072015-12-18 19:26:021047 stream_->SendRequest(headers_, &response_, callback_.callback()));
sclittle1edeeb22015-09-02 20:46:101048
1049 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1050 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rchf9f103cbc2014-08-30 05:28:041051}
1052
rch03b7a202016-02-05 00:54:201053// Regression test for http://crbug.com/584441
1054TEST_P(QuicHttpStreamTest, GetSSLInfoAfterSessionClosed) {
1055 SetRequest("GET", "/", DEFAULT_PRIORITY);
1056 Initialize();
1057
1058 request_.method = "GET";
rchcd379012017-04-12 21:53:321059 request_.url = GURL("https://www.example.org/");
rch03b7a202016-02-05 00:54:201060
xunjieli5fafe142016-03-23 23:32:541061 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271062 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541063 net_log_.bound(), callback_.callback()));
rch03b7a202016-02-05 00:54:201064
1065 SSLInfo ssl_info;
rch11565e02016-02-09 20:13:471066 EXPECT_FALSE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:201067 stream_->GetSSLInfo(&ssl_info);
rch11565e02016-02-09 20:13:471068 EXPECT_TRUE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:201069
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);
rch03b7a202016-02-05 00:54:201072
rch11565e02016-02-09 20:13:471073 SSLInfo ssl_info2;
1074 stream_->GetSSLInfo(&ssl_info2);
1075 EXPECT_TRUE(ssl_info2.is_valid());
rch03b7a202016-02-05 00:54:201076}
1077
rchcd379012017-04-12 21:53:321078TEST_P(QuicHttpStreamTest, GetAlternativeService) {
1079 SetRequest("GET", "/", DEFAULT_PRIORITY);
1080 Initialize();
1081
1082 request_.method = "GET";
1083 request_.url = GURL("https://www.example.org/");
1084
1085 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271086 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
rchcd379012017-04-12 21:53:321087 net_log_.bound(), callback_.callback()));
1088
1089 AlternativeService alternative_service;
1090 EXPECT_TRUE(stream_->GetAlternativeService(&alternative_service));
1091 EXPECT_EQ(AlternativeService(kProtoQUIC, "www.example.org", 443),
1092 alternative_service);
1093
1094 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521095 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rchcd379012017-04-12 21:53:321096
1097 AlternativeService alternative_service2;
1098 EXPECT_TRUE(stream_->GetAlternativeService(&alternative_service2));
1099 EXPECT_EQ(AlternativeService(kProtoQUIC, "www.example.org", 443),
1100 alternative_service2);
1101}
1102
zhongyica364fbb2015-12-12 03:39:121103TEST_P(QuicHttpStreamTest, LogGranularQuicConnectionError) {
1104 SetRequest("GET", "/", DEFAULT_PRIORITY);
1105 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521106 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361107 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:371108 AddWrite(InnerConstructRequestHeadersPacket(
ckrasicbf2f59c2017-05-04 23:54:361109 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, kFin,
1110 DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
1111 &header_stream_offset));
fayang3bcb8b502016-12-07 21:44:371112 AddWrite(ConstructAckAndRstStreamPacket(3));
zhongyica364fbb2015-12-12 03:39:121113 Initialize();
1114
1115 request_.method = "GET";
rchcd379012017-04-12 21:53:321116 request_.url = GURL("https://www.example.org/");
zhongyica364fbb2015-12-12 03:39:121117
xunjieli5fafe142016-03-23 23:32:541118 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271119 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541120 net_log_.bound(), callback_.callback()));
zhongyica364fbb2015-12-12 03:39:121121 EXPECT_EQ(OK,
1122 stream_->SendRequest(headers_, &response_, callback_.callback()));
1123
1124 // Ack the request.
wangyix6444ffe2017-04-25 17:49:491125 ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
robpercival214763f2016-07-01 23:27:011126 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1127 IsError(ERR_IO_PENDING));
zhongyica364fbb2015-12-12 03:39:121128
Ryan Hamilton8d9ee76e2018-05-29 23:52:521129 quic::QuicConnectionCloseFrame frame;
1130 frame.error_code = quic::QUIC_PEER_GOING_AWAY;
rch1c5b74a2016-06-23 22:10:551131 session_->connection()->OnConnectionCloseFrame(frame);
zhongyica364fbb2015-12-12 03:39:121132
1133 NetErrorDetails details;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521134 EXPECT_EQ(quic::QUIC_NO_ERROR, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121135 stream_->PopulateNetErrorDetails(&details);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521136 EXPECT_EQ(quic::QUIC_PEER_GOING_AWAY, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121137}
1138
Ryan Hamiltone316e482017-08-17 02:48:531139TEST_P(QuicHttpStreamTest, LogGranularQuicErrorIfHandshakeNotConfirmed) {
rch617e0652017-04-26 17:57:511140 // By default the test setup defaults handshake to be confirmed. Manually set
1141 // it to be not confirmed.
rch617e0652017-04-26 17:57:511142 crypto_client_stream_factory_.set_handshake_mode(
Ryan Hamilton9835e662018-08-02 05:36:271143 MockCryptoClientStream::ZERO_RTT);
rch617e0652017-04-26 17:57:511144
zhongyica364fbb2015-12-12 03:39:121145 SetRequest("GET", "/", DEFAULT_PRIORITY);
1146 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521147 quic::QuicStreamOffset header_stream_offset = 0;
1148 client_maker_.SetEncryptionLevel(quic::ENCRYPTION_INITIAL);
1149 client_maker_.SetLongHeaderType(quic::ZERO_RTT_PROTECTED);
fayang3bcb8b502016-12-07 21:44:371150 AddWrite(InnerConstructRequestHeadersPacket(
ckrasicbf2f59c2017-05-04 23:54:361151 1, GetNthClientInitiatedStreamId(0), kIncludeVersion, kFin,
1152 DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
1153 &header_stream_offset));
zhongyica364fbb2015-12-12 03:39:121154 Initialize();
1155
1156 request_.method = "GET";
rchcd379012017-04-12 21:53:321157 request_.url = GURL("https://www.example.org/");
zhongyica364fbb2015-12-12 03:39:121158
xunjieli5fafe142016-03-23 23:32:541159 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271160 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541161 net_log_.bound(), callback_.callback()));
zhongyica364fbb2015-12-12 03:39:121162 EXPECT_EQ(OK,
1163 stream_->SendRequest(headers_, &response_, callback_.callback()));
1164
1165 // Ack the request.
wangyix6444ffe2017-04-25 17:49:491166 ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
robpercival214763f2016-07-01 23:27:011167 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1168 IsError(ERR_IO_PENDING));
zhongyica364fbb2015-12-12 03:39:121169
Ryan Hamilton8d9ee76e2018-05-29 23:52:521170 quic::QuicConnectionCloseFrame frame;
1171 frame.error_code = quic::QUIC_PEER_GOING_AWAY;
rch1c5b74a2016-06-23 22:10:551172 session_->connection()->OnConnectionCloseFrame(frame);
zhongyica364fbb2015-12-12 03:39:121173
1174 NetErrorDetails details;
zhongyica364fbb2015-12-12 03:39:121175 stream_->PopulateNetErrorDetails(&details);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521176 EXPECT_EQ(quic::QUIC_PEER_GOING_AWAY, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121177}
1178
rch11a114a2014-09-04 23:41:591179// Regression test for http://crbug.com/409871
1180TEST_P(QuicHttpStreamTest, SessionClosedBeforeReadResponseHeaders) {
1181 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451182 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521183 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361184 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:371185 AddWrite(InnerConstructRequestHeadersPacket(
ckrasicbf2f59c2017-05-04 23:54:361186 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, kFin,
1187 DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
1188 &header_stream_offset));
rch11a114a2014-09-04 23:41:591189 Initialize();
1190
1191 request_.method = "GET";
rchcd379012017-04-12 21:53:321192 request_.url = GURL("https://www.example.org/");
rch11a114a2014-09-04 23:41:591193
xunjieli5fafe142016-03-23 23:32:541194 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271195 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541196 net_log_.bound(), callback_.callback()));
rch11a114a2014-09-04 23:41:591197
rjshaded5ced072015-12-18 19:26:021198 EXPECT_EQ(OK,
1199 stream_->SendRequest(headers_, &response_, callback_.callback()));
rch11a114a2014-09-04 23:41:591200
jri78ec06a2016-03-31 18:19:401201 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521202 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rch11a114a2014-09-04 23:41:591203
1204 EXPECT_NE(OK, stream_->ReadResponseHeaders(callback_.callback()));
sclittle1edeeb22015-09-02 20:46:101205
1206 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451207 // headers and payload.
1208 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1209 stream_->GetTotalSentBytes());
sclittle1edeeb22015-09-02 20:46:101210 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rch11a114a2014-09-04 23:41:591211}
1212
[email protected]1e960032013-12-20 19:00:201213TEST_P(QuicHttpStreamTest, SendPostRequest) {
1214 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451215 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521216 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361217 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
Yixin Wange7ecc472018-03-06 19:00:251218
1219 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1220 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, kFin,
1221 DEFAULT_PRIORITY, 0, &header_stream_offset,
1222 &spdy_request_headers_frame_length, {kUploadData}));
1223
1224 AddWrite(ConstructClientAckPacket(3, 3, 1, 1));
[email protected]f702d572012-12-04 15:56:201225
1226 Initialize();
1227
danakjad1777e2016-04-16 00:56:421228 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:191229 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
ricea2deef682016-09-09 08:04:071230 kUploadData, strlen(kUploadData)));
rch97827ee2017-05-24 23:49:121231 upload_data_stream_ =
Jeremy Roman0579ed62017-08-29 15:56:191232 std::make_unique<ElementsUploadDataStream>(std::move(element_readers), 0);
[email protected]f702d572012-12-04 15:56:201233 request_.method = "POST";
rchcd379012017-04-12 21:53:321234 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121235 request_.upload_data_stream = upload_data_stream_.get();
Bence Békyd8a21fc32018-06-27 18:29:581236 ASSERT_THAT(request_.upload_data_stream->Init(CompletionOnceCallback(),
tfarina428341112016-09-22 13:38:201237 NetLogWithSource()),
1238 IsOk());
[email protected]f702d572012-12-04 15:56:201239
xunjieli5fafe142016-03-23 23:32:541240 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271241 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541242 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021243 EXPECT_EQ(OK,
1244 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:201245
1246 // Ack both packets in the request.
wangyix6444ffe2017-04-25 17:49:491247 ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
[email protected]f702d572012-12-04 15:56:201248
1249 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071250 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451251 size_t spdy_response_headers_frame_length;
1252 ProcessPacket(ConstructResponseHeadersPacket(
1253 2, !kFin, &spdy_response_headers_frame_length));
[email protected]f702d572012-12-04 15:56:201254
rchfb47f712017-05-21 03:24:001255 // The headers have already arrived.
1256 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]cadac622013-06-11 16:46:361257 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:201258 EXPECT_EQ(200, response_.headers->response_code());
1259 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1260
1261 // Send the response body.
1262 const char kResponseBody[] = "Hello world!";
alyssar2adf3ac2016-05-03 17:12:581263 ProcessPacket(ConstructServerDataPacket(3, false, kFin, 0, kResponseBody));
[email protected]f702d572012-12-04 15:56:201264 // Since the body has already arrived, this should return immediately.
1265 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
1266 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1267 callback_.callback()));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291268 EXPECT_EQ(0,
1269 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1270 callback_.callback()));
1271
1272 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1273 EXPECT_TRUE(AtEof());
1274
1275 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
1276 // headers and payload.
1277 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
1278 strlen(kUploadData)),
1279 stream_->GetTotalSentBytes());
1280 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1281 strlen(kResponseBody)),
1282 stream_->GetTotalReceivedBytes());
1283}
1284
1285TEST_P(QuicHttpStreamTest, SendPostRequestAndReceiveSoloFin) {
1286 SetRequest("POST", "/", DEFAULT_PRIORITY);
1287 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521288 quic::QuicStreamOffset header_stream_offset = 0;
Ryan Hamilton2ef0a9c2017-07-25 03:18:291289 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
Yixin Wange7ecc472018-03-06 19:00:251290 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1291 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, kFin,
1292 DEFAULT_PRIORITY, 0, &header_stream_offset,
1293 &spdy_request_headers_frame_length, {kUploadData}));
1294 AddWrite(ConstructClientAckPacket(3, 3, 1, 1));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291295
1296 Initialize();
1297
1298 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:191299 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
Ryan Hamilton2ef0a9c2017-07-25 03:18:291300 kUploadData, strlen(kUploadData)));
1301 upload_data_stream_ =
Jeremy Roman0579ed62017-08-29 15:56:191302 std::make_unique<ElementsUploadDataStream>(std::move(element_readers), 0);
Ryan Hamilton2ef0a9c2017-07-25 03:18:291303 request_.method = "POST";
1304 request_.url = GURL("https://www.example.org/");
1305 request_.upload_data_stream = upload_data_stream_.get();
Bence Békyd8a21fc32018-06-27 18:29:581306 ASSERT_THAT(request_.upload_data_stream->Init(CompletionOnceCallback(),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291307 NetLogWithSource()),
1308 IsOk());
1309
1310 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271311 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
Ryan Hamilton2ef0a9c2017-07-25 03:18:291312 net_log_.bound(), callback_.callback()));
1313 EXPECT_EQ(OK,
1314 stream_->SendRequest(headers_, &response_, callback_.callback()));
1315
1316 // Ack both packets in the request.
1317 ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
1318
1319 // Send the response headers (but not the body).
1320 SetResponse("200 OK", string());
1321 size_t spdy_response_headers_frame_length;
1322 ProcessPacket(ConstructResponseHeadersPacket(
1323 2, !kFin, &spdy_response_headers_frame_length));
1324
1325 // The headers have already arrived.
1326 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
1327 ASSERT_TRUE(response_.headers.get());
1328 EXPECT_EQ(200, response_.headers->response_code());
1329 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1330
1331 // Send the response body.
1332 const char kResponseBody[] = "Hello world!";
1333 ProcessPacket(ConstructServerDataPacket(3, false, !kFin, 0, kResponseBody));
1334 // Since the body has already arrived, this should return immediately.
1335 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
1336 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1337 callback_.callback()));
1338 ProcessPacket(ConstructServerDataPacket(4, false, kFin,
1339 arraysize(kResponseBody) - 1, ""));
1340 EXPECT_EQ(0,
1341 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1342 callback_.callback()));
[email protected]f702d572012-12-04 15:56:201343
1344 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1345 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101346
1347 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451348 // headers and payload.
1349 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
1350 strlen(kUploadData)),
sclittle1edeeb22015-09-02 20:46:101351 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451352 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1353 strlen(kResponseBody)),
sclittle1edeeb22015-09-02 20:46:101354 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:201355}
1356
[email protected]1e960032013-12-20 19:00:201357TEST_P(QuicHttpStreamTest, SendChunkedPostRequest) {
1358 SetRequest("POST", "/", DEFAULT_PRIORITY);
[email protected]c9e49a02013-02-26 05:56:471359 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:451360 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521361 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361362 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
Yixin Wange7ecc472018-03-06 19:00:251363 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
ckrasicbf2f59c2017-05-04 23:54:361364 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, !kFin,
Yixin Wange7ecc472018-03-06 19:00:251365 DEFAULT_PRIORITY, 0, &header_stream_offset,
1366 &spdy_request_headers_frame_length, {kUploadData}));
1367 AddWrite(ConstructClientDataPacket(3, kIncludeVersion, kFin, chunk_size,
alyssar2adf3ac2016-05-03 17:12:581368 kUploadData));
Yixin Wange7ecc472018-03-06 19:00:251369 AddWrite(ConstructClientAckPacket(4, 3, 1, 1));
[email protected]c9e49a02013-02-26 05:56:471370 Initialize();
1371
Jeremy Roman0579ed62017-08-29 15:56:191372 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121373 auto* chunked_upload_stream =
1374 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1375 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
[email protected]c9e49a02013-02-26 05:56:471376
1377 request_.method = "POST";
rchcd379012017-04-12 21:53:321378 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121379 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071380 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina428341112016-09-22 13:38:201381 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]c9e49a02013-02-26 05:56:471382
xunjieli5fafe142016-03-23 23:32:541383 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271384 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541385 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021386 ASSERT_EQ(ERR_IO_PENDING,
1387 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]c9e49a02013-02-26 05:56:471388
rch97827ee2017-05-24 23:49:121389 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
robpercival214763f2016-07-01 23:27:011390 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]c9e49a02013-02-26 05:56:471391
1392 // Ack both packets in the request.
wangyix6444ffe2017-04-25 17:49:491393 ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
[email protected]c9e49a02013-02-26 05:56:471394
1395 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071396 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451397 size_t spdy_response_headers_frame_length;
1398 ProcessPacket(ConstructResponseHeadersPacket(
1399 2, !kFin, &spdy_response_headers_frame_length));
[email protected]c9e49a02013-02-26 05:56:471400
rchfb47f712017-05-21 03:24:001401 // The headers have already arrived.
1402 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]cadac622013-06-11 16:46:361403 ASSERT_TRUE(response_.headers.get());
[email protected]c9e49a02013-02-26 05:56:471404 EXPECT_EQ(200, response_.headers->response_code());
1405 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1406
1407 // Send the response body.
1408 const char kResponseBody[] = "Hello world!";
alyssar2adf3ac2016-05-03 17:12:581409 ProcessPacket(ConstructServerDataPacket(
1410 3, false, kFin, response_data_.length(), kResponseBody));
[email protected]c9e49a02013-02-26 05:56:471411
1412 // Since the body has already arrived, this should return immediately.
1413 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1414 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1415 callback_.callback()));
1416
1417 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1418 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101419
1420 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451421 // headers and payload.
1422 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
1423 strlen(kUploadData) * 2),
sclittle1edeeb22015-09-02 20:46:101424 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451425 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1426 strlen(kResponseBody)),
sclittle1edeeb22015-09-02 20:46:101427 stream_->GetTotalReceivedBytes());
[email protected]c9e49a02013-02-26 05:56:471428}
1429
[email protected]16ba7742014-08-22 00:57:251430TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithFinalEmptyDataPacket) {
1431 SetRequest("POST", "/", DEFAULT_PRIORITY);
1432 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:451433 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521434 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361435 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
Yixin Wange7ecc472018-03-06 19:00:251436 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
ckrasicbf2f59c2017-05-04 23:54:361437 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, !kFin,
Yixin Wange7ecc472018-03-06 19:00:251438 DEFAULT_PRIORITY, 0, &header_stream_offset,
1439 &spdy_request_headers_frame_length, {kUploadData}));
1440 AddWrite(ConstructClientDataPacket(3, kIncludeVersion, kFin, chunk_size, ""));
1441 AddWrite(ConstructClientAckPacket(4, 3, 1, 1));
[email protected]16ba7742014-08-22 00:57:251442 Initialize();
1443
Jeremy Roman0579ed62017-08-29 15:56:191444 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121445 auto* chunked_upload_stream =
1446 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1447 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
[email protected]16ba7742014-08-22 00:57:251448
1449 request_.method = "POST";
rchcd379012017-04-12 21:53:321450 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121451 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071452 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina428341112016-09-22 13:38:201453 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]16ba7742014-08-22 00:57:251454
xunjieli5fafe142016-03-23 23:32:541455 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271456 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541457 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021458 ASSERT_EQ(ERR_IO_PENDING,
1459 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251460
rch97827ee2017-05-24 23:49:121461 chunked_upload_stream->AppendData(nullptr, 0, true);
robpercival214763f2016-07-01 23:27:011462 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]16ba7742014-08-22 00:57:251463
wangyix6444ffe2017-04-25 17:49:491464 ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
[email protected]16ba7742014-08-22 00:57:251465
1466 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071467 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451468 size_t spdy_response_headers_frame_length;
1469 ProcessPacket(ConstructResponseHeadersPacket(
1470 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251471
rchfb47f712017-05-21 03:24:001472 // The headers have already arrived.
1473 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]16ba7742014-08-22 00:57:251474 ASSERT_TRUE(response_.headers.get());
1475 EXPECT_EQ(200, response_.headers->response_code());
1476 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1477
1478 // Send the response body.
1479 const char kResponseBody[] = "Hello world!";
alyssar2adf3ac2016-05-03 17:12:581480 ProcessPacket(ConstructServerDataPacket(
1481 3, false, kFin, response_data_.length(), kResponseBody));
[email protected]16ba7742014-08-22 00:57:251482
rchb27683c2015-07-29 23:53:501483 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251484 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1485 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1486 callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251487 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1488 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101489
1490 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451491 // headers and payload.
1492 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
1493 strlen(kUploadData)),
sclittle1edeeb22015-09-02 20:46:101494 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451495 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1496 strlen(kResponseBody)),
sclittle1edeeb22015-09-02 20:46:101497 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251498}
1499
1500TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithOneEmptyDataPacket) {
1501 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451502 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521503 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361504 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:371505 AddWrite(InnerConstructRequestHeadersPacket(
ckrasicbf2f59c2017-05-04 23:54:361506 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, !kFin,
1507 DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
1508 &header_stream_offset));
fayang3bcb8b502016-12-07 21:44:371509 AddWrite(ConstructClientDataPacket(3, kIncludeVersion, kFin, 0, ""));
wangyix6444ffe2017-04-25 17:49:491510 AddWrite(ConstructClientAckPacket(4, 3, 1, 1));
[email protected]16ba7742014-08-22 00:57:251511 Initialize();
1512
Jeremy Roman0579ed62017-08-29 15:56:191513 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121514 auto* chunked_upload_stream =
1515 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
[email protected]16ba7742014-08-22 00:57:251516
1517 request_.method = "POST";
rchcd379012017-04-12 21:53:321518 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121519 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071520 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina428341112016-09-22 13:38:201521 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]16ba7742014-08-22 00:57:251522
xunjieli5fafe142016-03-23 23:32:541523 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271524 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541525 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021526 ASSERT_EQ(ERR_IO_PENDING,
1527 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251528
rch97827ee2017-05-24 23:49:121529 chunked_upload_stream->AppendData(nullptr, 0, true);
robpercival214763f2016-07-01 23:27:011530 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]16ba7742014-08-22 00:57:251531
wangyix6444ffe2017-04-25 17:49:491532 ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
[email protected]16ba7742014-08-22 00:57:251533
1534 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071535 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451536 size_t spdy_response_headers_frame_length;
1537 ProcessPacket(ConstructResponseHeadersPacket(
1538 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251539
rchfb47f712017-05-21 03:24:001540 // The headers have already arrived.
1541 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]16ba7742014-08-22 00:57:251542 ASSERT_TRUE(response_.headers.get());
1543 EXPECT_EQ(200, response_.headers->response_code());
1544 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1545
1546 // Send the response body.
1547 const char kResponseBody[] = "Hello world!";
alyssar2adf3ac2016-05-03 17:12:581548 ProcessPacket(ConstructServerDataPacket(
1549 3, false, kFin, response_data_.length(), kResponseBody));
[email protected]16ba7742014-08-22 00:57:251550
rchb27683c2015-07-29 23:53:501551 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251552 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1553 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1554 callback_.callback()));
1555
1556 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1557 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101558
1559 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451560 // headers and payload.
1561 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1562 stream_->GetTotalSentBytes());
1563 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1564 strlen(kResponseBody)),
sclittle1edeeb22015-09-02 20:46:101565 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251566}
1567
[email protected]1e960032013-12-20 19:00:201568TEST_P(QuicHttpStreamTest, DestroyedEarly) {
1569 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451570 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521571 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361572 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:371573 AddWrite(InnerConstructRequestHeadersPacket(
ckrasicbf2f59c2017-05-04 23:54:361574 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, kFin,
1575 DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
1576 &header_stream_offset));
fayang3bcb8b502016-12-07 21:44:371577 AddWrite(ConstructAckAndRstStreamPacket(3));
[email protected]63534512012-12-23 18:49:001578 Initialize();
1579
1580 request_.method = "GET";
rchcd379012017-04-12 21:53:321581 request_.url = GURL("https://www.example.org/");
[email protected]63534512012-12-23 18:49:001582
xunjieli5fafe142016-03-23 23:32:541583 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271584 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541585 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021586 EXPECT_EQ(OK,
1587 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]63534512012-12-23 18:49:001588
1589 // Ack the request.
wangyix6444ffe2017-04-25 17:49:491590 ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
rchfb47f712017-05-21 03:24:001591 EXPECT_THAT(stream_->ReadResponseHeaders(
1592 base::Bind(&QuicHttpStreamTest::CloseStream,
1593 base::Unretained(this), stream_.get())),
robpercival214763f2016-07-01 23:27:011594 IsError(ERR_IO_PENDING));
[email protected]63534512012-12-23 18:49:001595
1596 // Send the response with a body.
[email protected]1e960032013-12-20 19:00:201597 SetResponse("404 OK", "hello world!");
[email protected]63534512012-12-23 18:49:001598 // In the course of processing this packet, the QuicHttpStream close itself.
rchfb47f712017-05-21 03:24:001599 size_t response_size = 0;
rch1bcfddf22017-06-03 00:26:291600 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin, &response_size));
[email protected]63534512012-12-23 18:49:001601
fdoray92e35a72016-06-10 15:54:551602 base::RunLoop().RunUntilIdle();
rchb27683c2015-07-29 23:53:501603
[email protected]63534512012-12-23 18:49:001604 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101605
1606 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451607 // headers and payload.
1608 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1609 stream_->GetTotalSentBytes());
rchfb47f712017-05-21 03:24:001610 // The stream was closed after receiving the headers.
1611 EXPECT_EQ(static_cast<int64_t>(response_size),
1612 stream_->GetTotalReceivedBytes());
[email protected]63534512012-12-23 18:49:001613}
1614
[email protected]1e960032013-12-20 19:00:201615TEST_P(QuicHttpStreamTest, Priority) {
1616 SetRequest("GET", "/", MEDIUM);
sclittlec4dc1a32015-09-24 00:15:451617 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521618 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361619 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:371620 AddWrite(InnerConstructRequestHeadersPacket(
ckrasicbf2f59c2017-05-04 23:54:361621 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, kFin, MEDIUM,
fayang3bcb8b502016-12-07 21:44:371622 &spdy_request_headers_frame_length, &header_stream_offset));
[email protected]24e5bc52013-09-18 15:36:581623 Initialize();
1624
1625 request_.method = "GET";
rchcd379012017-04-12 21:53:321626 request_.url = GURL("https://www.example.org/");
[email protected]24e5bc52013-09-18 15:36:581627
Steven Valdezb4ff0412018-01-18 22:39:271628 EXPECT_EQ(OK,
1629 stream_->InitializeStream(&request_, true, MEDIUM, net_log_.bound(),
1630 callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581631
rjshaded5ced072015-12-18 19:26:021632 EXPECT_EQ(OK,
1633 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581634
[email protected]24e5bc52013-09-18 15:36:581635 // Ack the request.
wangyix6444ffe2017-04-25 17:49:491636 ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
robpercival214763f2016-07-01 23:27:011637 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1638 IsError(ERR_IO_PENDING));
[email protected]24e5bc52013-09-18 15:36:581639
1640 // Send the response with a body.
[email protected]1e960032013-12-20 19:00:201641 SetResponse("404 OK", "hello world!");
rchfb47f712017-05-21 03:24:001642 size_t response_size = 0;
1643 ProcessPacket(ConstructResponseHeadersPacket(2, kFin, &response_size));
[email protected]24e5bc52013-09-18 15:36:581644
rchfb47f712017-05-21 03:24:001645 EXPECT_EQ(OK, callback_.WaitForResult());
rchb27683c2015-07-29 23:53:501646
[email protected]24e5bc52013-09-18 15:36:581647 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101648
1649 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451650 // headers and payload.
1651 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1652 stream_->GetTotalSentBytes());
rchfb47f712017-05-21 03:24:001653 EXPECT_EQ(static_cast<int64_t>(response_size),
1654 stream_->GetTotalReceivedBytes());
[email protected]24e5bc52013-09-18 15:36:581655}
1656
xunjieli8dff50b2016-07-22 14:19:061657TEST_P(QuicHttpStreamTest, SessionClosedDuringDoLoop) {
1658 SetRequest("POST", "/", DEFAULT_PRIORITY);
1659 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521660 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361661 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
Yixin Wange7ecc472018-03-06 19:00:251662 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
ckrasicbf2f59c2017-05-04 23:54:361663 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, !kFin,
Yixin Wange7ecc472018-03-06 19:00:251664 DEFAULT_PRIORITY, 0, &header_stream_offset,
1665 &spdy_request_headers_frame_length, {kUploadData}));
xunjieli8dff50b2016-07-22 14:19:061666 // Second data write will result in a synchronous failure which will close
1667 // the session.
1668 AddWrite(SYNCHRONOUS, ERR_FAILED);
1669 Initialize();
1670
Jeremy Roman0579ed62017-08-29 15:56:191671 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121672 auto* chunked_upload_stream =
1673 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
xunjieli8dff50b2016-07-22 14:19:061674
1675 request_.method = "POST";
rchcd379012017-04-12 21:53:321676 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121677 request_.upload_data_stream = upload_data_stream_.get();
xunjieli8dff50b2016-07-22 14:19:061678 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina428341112016-09-22 13:38:201679 TestCompletionCallback().callback(), NetLogWithSource()));
xunjieli8dff50b2016-07-22 14:19:061680
1681 size_t chunk_size = strlen(kUploadData);
rch97827ee2017-05-24 23:49:121682 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
xunjieli8dff50b2016-07-22 14:19:061683 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271684 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli8dff50b2016-07-22 14:19:061685 net_log_.bound(), callback_.callback()));
1686 QuicHttpStream* stream = stream_.get();
1687 DeleteStreamCallback delete_stream_callback(std::move(stream_));
1688 // SendRequest() completes asynchronously after the final chunk is added.
Yixin Wange7ecc472018-03-06 19:00:251689 // Error does not surface yet since packet write is triggered by a packet
1690 // flusher that tries to bundle request body writes.
xunjieli8dff50b2016-07-22 14:19:061691 ASSERT_EQ(ERR_IO_PENDING,
1692 stream->SendRequest(headers_, &response_, callback_.callback()));
rch97827ee2017-05-24 23:49:121693 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
xunjieli8dff50b2016-07-22 14:19:061694 int rv = callback_.WaitForResult();
Yixin Wange7ecc472018-03-06 19:00:251695 EXPECT_EQ(OK, rv);
1696 // Error will be surfaced once an attempt to read the response occurs.
1697 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1698 stream->ReadResponseHeaders(callback_.callback()));
xunjieli8dff50b2016-07-22 14:19:061699}
1700
rtenneti15656ae2016-01-23 03:05:031701TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersComplete) {
1702 SetRequest("POST", "/", DEFAULT_PRIORITY);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521703 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361704 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
rtenneti15656ae2016-01-23 03:05:031705 AddWrite(SYNCHRONOUS, ERR_FAILED);
1706 Initialize();
1707
Jeremy Roman0579ed62017-08-29 15:56:191708 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
Yixin Wange7ecc472018-03-06 19:00:251709 auto* chunked_upload_stream =
1710 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
rtenneti15656ae2016-01-23 03:05:031711
1712 request_.method = "POST";
rchcd379012017-04-12 21:53:321713 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121714 request_.upload_data_stream = upload_data_stream_.get();
rtenneti15656ae2016-01-23 03:05:031715 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina428341112016-09-22 13:38:201716 TestCompletionCallback().callback(), NetLogWithSource()));
rtenneti15656ae2016-01-23 03:05:031717
xunjieli5fafe142016-03-23 23:32:541718 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271719 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541720 net_log_.bound(), callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:251721 ASSERT_EQ(ERR_IO_PENDING,
rtenneti15656ae2016-01-23 03:05:031722 stream_->SendRequest(headers_, &response_, callback_.callback()));
mmenkeffff3642017-06-15 17:37:241723
Yixin Wange7ecc472018-03-06 19:00:251724 // Error will be surfaced once |upload_data_stream| triggers the next write.
1725 size_t chunk_size = strlen(kUploadData);
1726 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1727 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR, callback_.WaitForResult());
1728
1729 EXPECT_LE(0, stream_->GetTotalSentBytes());
1730 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1731}
1732
1733TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersCompleteReadResponse) {
1734 SetRequest("POST", "/", DEFAULT_PRIORITY);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521735 quic::QuicStreamOffset header_stream_offset = 0;
Yixin Wange7ecc472018-03-06 19:00:251736 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
1737 AddWrite(SYNCHRONOUS, ERR_FAILED);
1738 Initialize();
1739
1740 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
1741 auto* chunked_upload_stream =
1742 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1743
1744 request_.method = "POST";
1745 request_.url = GURL("https://www.example.org/");
1746 request_.upload_data_stream = upload_data_stream_.get();
1747
1748 size_t chunk_size = strlen(kUploadData);
1749 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1750
1751 ASSERT_EQ(OK, request_.upload_data_stream->Init(
1752 TestCompletionCallback().callback(), NetLogWithSource()));
1753
1754 ASSERT_EQ(OK,
1755 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1756 net_log_.bound(), callback_.callback()));
1757 ASSERT_EQ(OK,
1758 stream_->SendRequest(headers_, &response_, callback_.callback()));
1759
1760 // Error will be surfaced once an attempt to read the response occurs.
1761 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1762 stream_->ReadResponseHeaders(callback_.callback()));
1763
mmenkeffff3642017-06-15 17:37:241764 EXPECT_LE(0, stream_->GetTotalSentBytes());
1765 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rtenneti15656ae2016-01-23 03:05:031766}
1767
1768TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBodyComplete) {
1769 SetRequest("POST", "/", DEFAULT_PRIORITY);
1770 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521771 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361772 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:371773 AddWrite(InnerConstructRequestHeadersPacket(
ckrasicbf2f59c2017-05-04 23:54:361774 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, !kFin,
1775 DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
1776 &header_stream_offset));
rtenneti15656ae2016-01-23 03:05:031777 AddWrite(SYNCHRONOUS, ERR_FAILED);
1778 Initialize();
1779
Jeremy Roman0579ed62017-08-29 15:56:191780 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121781 auto* chunked_upload_stream =
1782 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
rtenneti15656ae2016-01-23 03:05:031783
1784 request_.method = "POST";
rchcd379012017-04-12 21:53:321785 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121786 request_.upload_data_stream = upload_data_stream_.get();
rtenneti15656ae2016-01-23 03:05:031787 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina428341112016-09-22 13:38:201788 TestCompletionCallback().callback(), NetLogWithSource()));
rtenneti15656ae2016-01-23 03:05:031789
xunjieli5fafe142016-03-23 23:32:541790 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271791 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541792 net_log_.bound(), callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:251793 ASSERT_EQ(ERR_IO_PENDING,
rtenneti15656ae2016-01-23 03:05:031794 stream_->SendRequest(headers_, &response_, callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:251795
1796 size_t chunk_size = strlen(kUploadData);
1797 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1798 // Error does not surface yet since packet write is triggered by a packet
1799 // flusher that tries to bundle request body writes.
1800 ASSERT_EQ(OK, callback_.WaitForResult());
1801 // Error will be surfaced once an attempt to read the response occurs.
1802 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1803 stream_->ReadResponseHeaders(callback_.callback()));
1804
1805 EXPECT_LE(0, stream_->GetTotalSentBytes());
1806 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1807}
1808
1809TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBundledBodyComplete) {
1810 SetRequest("POST", "/", DEFAULT_PRIORITY);
1811 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521812 quic::QuicStreamOffset header_stream_offset = 0;
Yixin Wange7ecc472018-03-06 19:00:251813 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
1814 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1815 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, !kFin,
1816 DEFAULT_PRIORITY, 0, &header_stream_offset,
1817 &spdy_request_headers_frame_length, {kUploadData}));
1818 AddWrite(SYNCHRONOUS, ERR_FAILED);
1819 Initialize();
1820
1821 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
1822 auto* chunked_upload_stream =
1823 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1824
1825 request_.method = "POST";
1826 request_.url = GURL("https://www.example.org/");
1827 request_.upload_data_stream = upload_data_stream_.get();
1828
1829 size_t chunk_size = strlen(kUploadData);
1830 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
1831
1832 ASSERT_EQ(OK, request_.upload_data_stream->Init(
1833 TestCompletionCallback().callback(), NetLogWithSource()));
1834
1835 ASSERT_EQ(OK,
1836 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1837 net_log_.bound(), callback_.callback()));
1838 ASSERT_EQ(ERR_IO_PENDING,
1839 stream_->SendRequest(headers_, &response_, callback_.callback()));
1840
1841 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1842
1843 // Error does not surface yet since packet write is triggered by a packet
1844 // flusher that tries to bundle request body writes.
1845 ASSERT_EQ(OK, callback_.WaitForResult());
1846 // Error will be surfaced once an attempt to read the response occurs.
1847 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1848 stream_->ReadResponseHeaders(callback_.callback()));
1849
1850 EXPECT_LE(0, stream_->GetTotalSentBytes());
1851 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rtenneti15656ae2016-01-23 03:05:031852}
1853
ckrasic3865ee0f2016-02-29 22:04:561854TEST_P(QuicHttpStreamTest, ServerPushGetRequest) {
1855 SetRequest("GET", "/", DEFAULT_PRIORITY);
1856 Initialize();
1857
1858 // Initialize the first stream, for receiving the promise on.
1859 request_.method = "GET";
rchcd379012017-04-12 21:53:321860 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:561861
xunjieli5fafe142016-03-23 23:32:541862 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271863 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541864 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561865
1866 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
1867 // packet, but does it matter?
1868 ReceivePromise(promise_id_);
1869 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
1870
1871 request_.url = GURL(promise_url_);
1872
1873 // Make the second stream that will exercise the first step of the
1874 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:271875 EXPECT_EQ(OK, promised_stream_->InitializeStream(
1876 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
1877 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561878
1879 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:251880 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:561881 size_t spdy_response_headers_frame_length;
1882 ProcessPacket(InnerConstructResponseHeadersPacket(
1883 1, promise_id_, false, &spdy_response_headers_frame_length));
1884
1885 // Receive the promised response body.
1886 const char kResponseBody[] = "Hello world!";
alyssar2adf3ac2016-05-03 17:12:581887 ProcessPacket(InnerConstructDataPacket(2, promise_id_, false, kFin, 0,
1888 kResponseBody, &server_maker_));
ckrasic3865ee0f2016-02-29 22:04:561889
1890 // Now sending a matching request will have successful rendezvous
1891 // with the promised stream.
1892 EXPECT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
1893 callback_.callback()));
1894
1895 EXPECT_EQ(
1896 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
1897 ->id(),
1898 promise_id_);
1899
1900 // The headers will be immediately available.
robpercival214763f2016-07-01 23:27:011901 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
1902 IsOk());
ckrasic3865ee0f2016-02-29 22:04:561903
1904 // As will be the body.
1905 EXPECT_EQ(
1906 static_cast<int>(strlen(kResponseBody)),
1907 promised_stream_->ReadResponseBody(
1908 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
1909 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
1910 EXPECT_TRUE(AtEof());
1911
1912 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1913 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1914 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
1915 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1916 strlen(kResponseBody)),
1917 promised_stream_->GetTotalReceivedBytes());
1918}
1919
1920TEST_P(QuicHttpStreamTest, ServerPushGetRequestSlowResponse) {
1921 SetRequest("GET", "/", DEFAULT_PRIORITY);
1922 Initialize();
1923
1924 // Initialize the first stream, for receiving the promise on.
1925 request_.method = "GET";
rchcd379012017-04-12 21:53:321926 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:561927
xunjieli5fafe142016-03-23 23:32:541928 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271929 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541930 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561931
1932 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
1933 // packet, but does it matter?
1934 ReceivePromise(promise_id_);
1935 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
1936
1937 request_.url = GURL(promise_url_);
1938
1939 // Make the second stream that will exercise the first step of the
1940 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:271941 EXPECT_EQ(OK, promised_stream_->InitializeStream(
1942 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
1943 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561944
1945 // Now sending a matching request will rendezvous with the promised
1946 // stream, but pending secondary validation.
1947 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
1948 headers_, &response_, callback_.callback()));
1949
1950 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:251951 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:561952 size_t spdy_response_headers_frame_length;
1953 ProcessPacket(InnerConstructResponseHeadersPacket(
1954 1, promise_id_, false, &spdy_response_headers_frame_length));
1955
1956 // Receive the promised response body.
1957 const char kResponseBody[] = "Hello world!";
alyssar2adf3ac2016-05-03 17:12:581958 ProcessPacket(InnerConstructDataPacket(2, promise_id_, false, kFin, 0,
1959 kResponseBody, &server_maker_));
ckrasic3865ee0f2016-02-29 22:04:561960
fdoray92e35a72016-06-10 15:54:551961 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:561962
1963 // Rendezvous should have succeeded now, so the promised stream
1964 // should point at our push stream, and we should be able read
1965 // headers and data from it.
robpercival214763f2016-07-01 23:27:011966 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:561967
1968 EXPECT_EQ(
1969 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
1970 ->id(),
1971 promise_id_);
1972
robpercival214763f2016-07-01 23:27:011973 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
1974 IsOk());
ckrasic3865ee0f2016-02-29 22:04:561975
1976 EXPECT_EQ(
1977 static_cast<int>(strlen(kResponseBody)),
1978 promised_stream_->ReadResponseBody(
1979 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
1980
1981 // Callback should return
1982 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
1983 EXPECT_TRUE(AtEof());
1984
1985 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1986 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1987 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
1988 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1989 strlen(kResponseBody)),
1990 promised_stream_->GetTotalReceivedBytes());
1991}
1992
ckrasic2c63f9b2016-08-16 23:54:071993// Verify fix for crbug.com/637349
1994TEST_P(QuicHttpStreamTest, ServerPushCancelHttpStreamBeforeResponse) {
1995 SetRequest("GET", "/", DEFAULT_PRIORITY);
1996 Initialize();
1997
1998 // Initialize the first stream, for receiving the promise on.
1999 request_.method = "GET";
rchcd379012017-04-12 21:53:322000 request_.url = GURL("https://www.example.org/");
ckrasic2c63f9b2016-08-16 23:54:072001
2002 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272003 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
ckrasic2c63f9b2016-08-16 23:54:072004 net_log_.bound(), callback_.callback()));
2005
2006 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2007 // packet, but does it matter?
2008 ReceivePromise(promise_id_);
2009 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2010
2011 request_.url = GURL(promise_url_);
2012
2013 // Make the second stream that will exercise the first step of the
2014 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272015 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2016 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2017 callback_.callback()));
ckrasic2c63f9b2016-08-16 23:54:072018
2019 // Now sending a matching request will rendezvous with the promised
2020 // stream, but pending secondary validation.
2021 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2022 headers_, &response_, callback_.callback()));
2023
2024 base::RunLoop().RunUntilIdle();
2025
2026 // Cause of FinalValidation() crash as per bug.
2027 promised_stream_.reset();
2028
2029 // Receive the promised response headers.
2030 response_headers_ = promised_response_.Clone();
2031 size_t spdy_response_headers_frame_length;
2032 ProcessPacket(InnerConstructResponseHeadersPacket(
2033 1, promise_id_, false, &spdy_response_headers_frame_length));
2034}
2035
ckrasic3865ee0f2016-02-29 22:04:562036TEST_P(QuicHttpStreamTest, ServerPushCrossOriginOK) {
2037 SetRequest("GET", "/", DEFAULT_PRIORITY);
2038 Initialize();
2039
2040 // Initialize the first stream, for receiving the promise on.
2041 request_.method = "GET";
rchcd379012017-04-12 21:53:322042 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562043
xunjieli5fafe142016-03-23 23:32:542044 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272045 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542046 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562047
2048 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2049 // packet, but does it matter?
2050
2051 push_promise_[":authority"] = "mail.example.org";
Ryan Hamilton8d9ee76e2018-05-29 23:52:522052 promise_url_ = quic::SpdyUtils::GetPromisedUrlFromHeaders(push_promise_);
ckrasic3865ee0f2016-02-29 22:04:562053
2054 ReceivePromise(promise_id_);
2055 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2056
2057 request_.url = GURL(promise_url_);
2058
2059 // Make the second stream that will exercise the first step of the
2060 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272061 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2062 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2063 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562064
2065 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252066 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562067 size_t spdy_response_headers_frame_length;
2068 ProcessPacket(InnerConstructResponseHeadersPacket(
2069 1, promise_id_, false, &spdy_response_headers_frame_length));
2070
2071 // Receive the promised response body.
2072 const char kResponseBody[] = "Hello world!";
alyssar2adf3ac2016-05-03 17:12:582073 ProcessPacket(InnerConstructDataPacket(2, promise_id_, false, kFin, 0,
2074 kResponseBody, &server_maker_));
ckrasic3865ee0f2016-02-29 22:04:562075
2076 // Now sending a matching request will have successful rendezvous
2077 // with the promised stream.
2078 EXPECT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
2079 callback_.callback()));
2080
2081 EXPECT_EQ(
2082 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2083 ->id(),
2084 promise_id_);
2085
2086 // The headers will be immediately available.
robpercival214763f2016-07-01 23:27:012087 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2088 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562089
2090 // As will be the body.
2091 EXPECT_EQ(
2092 static_cast<int>(strlen(kResponseBody)),
2093 promised_stream_->ReadResponseBody(
2094 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2095 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2096 EXPECT_TRUE(AtEof());
2097
2098 EXPECT_EQ(0, stream_->GetTotalSentBytes());
2099 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2100 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2101 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
2102 strlen(kResponseBody)),
2103 promised_stream_->GetTotalReceivedBytes());
2104}
2105
2106TEST_P(QuicHttpStreamTest, ServerPushCrossOriginFail) {
2107 SetRequest("GET", "/", DEFAULT_PRIORITY);
2108 Initialize();
2109
2110 // Initialize the first stream, for receiving the promise on.
2111 request_.method = "GET";
rchcd379012017-04-12 21:53:322112 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562113
xunjieli5fafe142016-03-23 23:32:542114 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272115 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542116 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562117
2118 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2119 // packet, but does it matter?
2120 push_promise_[":authority"] = "www.notexample.org";
Ryan Hamilton8d9ee76e2018-05-29 23:52:522121 promise_url_ = quic::SpdyUtils::GetPromisedUrlFromHeaders(push_promise_);
ckrasic3865ee0f2016-02-29 22:04:562122
2123 ReceivePromise(promise_id_);
2124 // The promise will have been rejected because the cert doesn't
2125 // match.
2126 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
2127}
2128
2129TEST_P(QuicHttpStreamTest, ServerPushVaryCheckOK) {
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 push_promise_["accept-encoding"] = "gzip";
ckrasic3865ee0f2016-02-29 22:04:562142
2143 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2144 // packet, but does it matter?
2145 ReceivePromise(promise_id_);
2146 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2147
2148 request_.url = GURL(promise_url_);
2149
2150 // Make the second stream that will exercise the first step of the
2151 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272152 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2153 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2154 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562155
2156 headers_.SetHeader("accept-encoding", "gzip");
2157
2158 // Now sending a matching request will rendezvous with the promised
2159 // stream, but pending secondary validation.
2160 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2161 headers_, &response_, callback_.callback()));
2162
2163 // Receive the promised response headers.
2164 promised_response_["vary"] = "accept-encoding";
bnc94893a72016-06-30 13:45:252165 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562166 size_t spdy_response_headers_frame_length;
2167 ProcessPacket(InnerConstructResponseHeadersPacket(
2168 1, promise_id_, false, &spdy_response_headers_frame_length));
2169
2170 // Receive the promised response body.
2171 const char kResponseBody[] = "Hello world!";
alyssar2adf3ac2016-05-03 17:12:582172 ProcessPacket(InnerConstructDataPacket(2, promise_id_, false, kFin, 0,
2173 kResponseBody, &server_maker_));
ckrasic3865ee0f2016-02-29 22:04:562174
fdoray92e35a72016-06-10 15:54:552175 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562176
2177 // Rendezvous should have succeeded now, so the promised stream
2178 // should point at our push stream, and we should be able read
2179 // headers and data from it.
robpercival214763f2016-07-01 23:27:012180 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562181
2182 EXPECT_EQ(
2183 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2184 ->id(),
2185 promise_id_);
2186
robpercival214763f2016-07-01 23:27:012187 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2188 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562189
2190 EXPECT_EQ(
2191 static_cast<int>(strlen(kResponseBody)),
2192 promised_stream_->ReadResponseBody(
2193 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2194
2195 // Callback should return
2196 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2197 EXPECT_TRUE(AtEof());
2198
2199 EXPECT_EQ(0, stream_->GetTotalSentBytes());
2200 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2201 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2202 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
2203 strlen(kResponseBody)),
2204 promised_stream_->GetTotalReceivedBytes());
2205}
2206
2207TEST_P(QuicHttpStreamTest, ServerPushVaryCheckFail) {
2208 SetRequest("GET", "/", DEFAULT_PRIORITY);
2209 request_headers_[":scheme"] = "https";
2210 request_headers_[":path"] = "/bar";
2211 request_headers_["accept-encoding"] = "sdch";
2212
2213 size_t spdy_request_header_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:522214 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:362215 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
Yixin Wangb470bc882018-02-15 18:43:572216
Ryan Hamilton8d9ee76e2018-05-29 23:52:522217 quic::QuicPacketNumber client_packet_number = 2;
Yixin Wangb470bc882018-02-15 18:43:572218 if (client_headers_include_h2_stream_dependency_ &&
Zhongyi Shi7b4f22b2018-08-23 17:22:262219 version_ >= quic::QUIC_VERSION_43) {
Yixin Wangb470bc882018-02-15 18:43:572220 AddWrite(ConstructClientPriorityPacket(
2221 client_packet_number++, kIncludeVersion, promise_id_, 0,
2222 DEFAULT_PRIORITY, &header_stream_offset));
2223 }
Michael Warresabba8b7d2018-07-20 22:50:272224 AddWrite(ConstructClientRstStreamVaryMismatchAndRequestHeadersPacket(
2225 client_packet_number++, stream_id_ + 2, !kIncludeVersion, kFin,
2226 DEFAULT_PRIORITY, promise_id_, &spdy_request_header_frame_length,
2227 &header_stream_offset));
Yixin Wangb470bc882018-02-15 18:43:572228 AddWrite(ConstructClientAckPacket(client_packet_number++, 3, 1, 1));
2229 AddWrite(ConstructClientRstStreamCancelledPacket(client_packet_number++));
2230
ckrasic3865ee0f2016-02-29 22:04:562231 Initialize();
2232
2233 // Initialize the first stream, for receiving the promise on.
2234 request_.method = "GET";
rchcd379012017-04-12 21:53:322235 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562236
xunjieli5fafe142016-03-23 23:32:542237 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272238 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542239 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562240
2241 push_promise_["accept-encoding"] = "gzip";
ckrasic3865ee0f2016-02-29 22:04:562242
2243 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2244 // packet, but does it matter?
2245 ReceivePromise(promise_id_);
2246 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2247
2248 request_.url = GURL(promise_url_);
2249
2250 // Make the second stream that will exercise the first step of the
2251 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272252 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2253 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2254 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562255
2256 headers_.SetHeader("accept-encoding", "sdch");
2257
2258 // Now sending a matching request will rendezvous with the promised
2259 // stream, but pending secondary validation.
2260 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2261 headers_, &response_, callback_.callback()));
2262
2263 // Receive the promised response headers.
2264 promised_response_["vary"] = "accept-encoding";
bnc94893a72016-06-30 13:45:252265 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562266 size_t spdy_response_headers_frame_length;
2267 ProcessPacket(InnerConstructResponseHeadersPacket(
2268 1, promise_id_, false, &spdy_response_headers_frame_length));
2269
fdoray92e35a72016-06-10 15:54:552270 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562271
2272 // Rendezvous should have failed due to vary mismatch, so the
2273 // promised stream should have been aborted, and instead we have a
2274 // new, regular client initiated stream.
robpercival214763f2016-07-01 23:27:012275 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562276
2277 // Not a server-initiated stream.
2278 EXPECT_NE(
2279 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2280 ->id(),
2281 promise_id_);
2282
2283 // Instead, a new client-initiated stream.
2284 EXPECT_EQ(
2285 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2286 ->id(),
2287 stream_id_ + 2);
2288
2289 // After rendezvous failure, the push stream has been cancelled.
2290 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
2291
2292 // The rest of the test verifies that the retried as
2293 // client-initiated version of |promised_stream_| works as intended.
2294
2295 // Ack the request.
wangyix6444ffe2017-04-25 17:49:492296 ProcessPacket(ConstructServerAckPacket(2, 0, 0, 0));
ckrasic3865ee0f2016-02-29 22:04:562297
bnc614a92d32016-04-04 13:56:072298 SetResponse("404 Not Found", string());
ckrasic3865ee0f2016-02-29 22:04:562299 size_t spdy_response_header_frame_length;
2300 ProcessPacket(InnerConstructResponseHeadersPacket(
2301 3, stream_id_ + 2, kFin, &spdy_response_header_frame_length));
2302
fdoray92e35a72016-06-10 15:54:552303 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562304
robpercival214763f2016-07-01 23:27:012305 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2306 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562307 ASSERT_TRUE(response_.headers.get());
2308 EXPECT_EQ(404, response_.headers->response_code());
2309 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
2310 EXPECT_FALSE(response_.response_time.is_null());
2311 EXPECT_FALSE(response_.request_time.is_null());
2312
2313 // There is no body, so this should return immediately.
2314 EXPECT_EQ(
2315 0, promised_stream_->ReadResponseBody(
2316 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2317 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2318
2319 stream_->Close(true);
2320
2321 EXPECT_TRUE(AtEof());
2322
2323 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
2324 // headers and payload.
2325 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
2326 promised_stream_->GetTotalSentBytes());
2327 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length),
2328 promised_stream_->GetTotalReceivedBytes());
2329}
2330
maksim.sisov84e20c92016-06-23 08:49:342331TEST_P(QuicHttpStreamTest, DataReadErrorSynchronous) {
2332 SetRequest("POST", "/", DEFAULT_PRIORITY);
2333 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:522334 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:362335 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
Yixin Wange7ecc472018-03-06 19:00:252336 AddWrite(ConstructRequestAndRstPacket(
ckrasicbf2f59c2017-05-04 23:54:362337 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, !kFin,
Yixin Wange7ecc472018-03-06 19:00:252338 DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
Ryan Hamilton8d9ee76e2018-05-29 23:52:522339 &header_stream_offset, quic::QUIC_ERROR_PROCESSING_STREAM, 0));
maksim.sisov84e20c92016-06-23 08:49:342340
2341 Initialize();
2342
Jeremy Roman0579ed62017-08-29 15:56:192343 upload_data_stream_ = std::make_unique<ReadErrorUploadDataStream>(
maksim.sisov84e20c92016-06-23 08:49:342344 ReadErrorUploadDataStream::FailureMode::SYNC);
2345 request_.method = "POST";
rchcd379012017-04-12 21:53:322346 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122347 request_.upload_data_stream = upload_data_stream_.get();
maksim.sisov84e20c92016-06-23 08:49:342348 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina428341112016-09-22 13:38:202349 TestCompletionCallback().callback(), NetLogWithSource()));
maksim.sisov84e20c92016-06-23 08:49:342350
2351 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272352 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
maksim.sisov84e20c92016-06-23 08:49:342353 net_log_.bound(), callback_.callback()));
2354
2355 int result = stream_->SendRequest(headers_, &response_, callback_.callback());
robpercival214763f2016-07-01 23:27:012356 EXPECT_THAT(result, IsError(ERR_FAILED));
maksim.sisov84e20c92016-06-23 08:49:342357
2358 EXPECT_TRUE(AtEof());
2359
2360 // QuicHttpStream::GetTotalSent/ReceivedBytes includes only headers.
2361 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
2362 stream_->GetTotalSentBytes());
2363 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2364}
2365
2366TEST_P(QuicHttpStreamTest, DataReadErrorAsynchronous) {
2367 SetRequest("POST", "/", DEFAULT_PRIORITY);
2368 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:522369 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:362370 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:372371 AddWrite(InnerConstructRequestHeadersPacket(
ckrasicbf2f59c2017-05-04 23:54:362372 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, !kFin,
2373 DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
2374 &header_stream_offset));
fayang3bcb8b502016-12-07 21:44:372375 AddWrite(ConstructClientRstStreamErrorPacket(3, !kIncludeVersion));
maksim.sisov84e20c92016-06-23 08:49:342376
2377 Initialize();
2378
Jeremy Roman0579ed62017-08-29 15:56:192379 upload_data_stream_ = std::make_unique<ReadErrorUploadDataStream>(
maksim.sisov84e20c92016-06-23 08:49:342380 ReadErrorUploadDataStream::FailureMode::ASYNC);
2381 request_.method = "POST";
rchcd379012017-04-12 21:53:322382 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122383 request_.upload_data_stream = upload_data_stream_.get();
maksim.sisov84e20c92016-06-23 08:49:342384 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina428341112016-09-22 13:38:202385 TestCompletionCallback().callback(), NetLogWithSource()));
maksim.sisov84e20c92016-06-23 08:49:342386
2387 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272388 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
maksim.sisov84e20c92016-06-23 08:49:342389 net_log_.bound(), callback_.callback()));
2390
2391 int result = stream_->SendRequest(headers_, &response_, callback_.callback());
2392
wangyix6444ffe2017-04-25 17:49:492393 ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
maksim.sisov84e20c92016-06-23 08:49:342394 SetResponse("200 OK", string());
2395
robpercival214763f2016-07-01 23:27:012396 EXPECT_THAT(result, IsError(ERR_IO_PENDING));
2397 EXPECT_THAT(callback_.GetResult(result), IsError(ERR_FAILED));
maksim.sisov84e20c92016-06-23 08:49:342398
2399 EXPECT_TRUE(AtEof());
2400
2401 // QuicHttpStream::GetTotalSent/ReceivedBytes includes only headers.
2402 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
2403 stream_->GetTotalSentBytes());
2404 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2405}
2406
[email protected]f702d572012-12-04 15:56:202407} // namespace test
[email protected]f702d572012-12-04 15:56:202408} // namespace net