blob: 94686e0d032fb7f0ef61b93070b9f86ed8c564c6 [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
rch675757b2016-07-29 16:40:115#include "net/quic/chromium/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"
rch675757b2016-07-29 16:40:1129#include "net/quic/chromium/crypto/proof_verifier_chromium.h"
rch223465c2016-12-08 21:17:2930#include "net/quic/chromium/mock_crypto_client_stream_factory.h"
rch675757b2016-07-29 16:40:1131#include "net/quic/chromium/quic_chromium_alarm_factory.h"
32#include "net/quic/chromium/quic_chromium_connection_helper.h"
33#include "net/quic/chromium/quic_chromium_packet_reader.h"
34#include "net/quic/chromium/quic_chromium_packet_writer.h"
rch223465c2016-12-08 21:17:2935#include "net/quic/chromium/quic_http_utils.h"
rchfaf834e2016-12-21 17:55:0236#include "net/quic/chromium/quic_server_info.h"
Zhongyi Shi0e52ce72018-03-20 22:31:0037#include "net/quic/chromium/quic_stream_factory.h"
rch223465c2016-12-08 21:17:2938#include "net/quic/chromium/quic_test_packet_maker.h"
rch1e369362017-04-03 19:44:5139#include "net/quic/chromium/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:
tfarina42834112016-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()),
[email protected]f702d572012-12-04 15:56:20196 read_buffer_(new 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() {
Ryan Hamilton8d9ee76e2018-05-29 23:52:52223 session_->CloseSessionOnError(ERR_ABORTED, quic::QUIC_INTERNAL_ERROR);
[email protected]f702d572012-12-04 15:56:20224 for (size_t i = 0; i < writes_.size(); i++) {
225 delete writes_[i].packet;
226 }
227 }
228
229 // Adds a packet to the list of expected writes.
Ryan Hamilton8d9ee76e2018-05-29 23:52:52230 void AddWrite(std::unique_ptr<quic::QuicReceivedPacket> packet) {
[email protected]1e960032013-12-20 19:00:20231 writes_.push_back(PacketToWrite(SYNCHRONOUS, packet.release()));
[email protected]f702d572012-12-04 15:56:20232 }
233
rtenneti15656ae2016-01-23 03:05:03234 void AddWrite(IoMode mode, int rv) {
235 writes_.push_back(PacketToWrite(mode, rv));
236 }
237
[email protected]f702d572012-12-04 15:56:20238 // Returns the packet to be written at position |pos|.
Ryan Hamilton8d9ee76e2018-05-29 23:52:52239 quic::QuicReceivedPacket* GetWrite(size_t pos) { return writes_[pos].packet; }
[email protected]f702d572012-12-04 15:56:20240
241 bool AtEof() {
rch37de576c2015-05-17 20:28:17242 return socket_data_->AllReadDataConsumed() &&
243 socket_data_->AllWriteDataConsumed();
[email protected]f702d572012-12-04 15:56:20244 }
245
Ryan Hamilton8d9ee76e2018-05-29 23:52:52246 void ProcessPacket(std::unique_ptr<quic::QuicReceivedPacket> packet) {
fayang91ca2012016-11-22 07:42:46247 connection_->ProcessUdpPacket(
Ryan Hamilton8d9ee76e2018-05-29 23:52:52248 quic::QuicSocketAddress(quic::QuicSocketAddressImpl(self_addr_)),
249 quic::QuicSocketAddress(quic::QuicSocketAddressImpl(peer_addr_)),
250 *packet);
[email protected]f702d572012-12-04 15:56:20251 }
252
253 // Configures the test fixture to use the list of expected writes.
254 void Initialize() {
255 mock_writes_.reset(new MockWrite[writes_.size()]);
256 for (size_t i = 0; i < writes_.size(); i++) {
rtenneti15656ae2016-01-23 03:05:03257 if (writes_[i].packet == nullptr) {
258 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].rv, i);
259 } else {
260 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].packet->data(),
261 writes_[i].packet->length());
262 }
bnc614a92d32016-04-04 13:56:07263 }
[email protected]f702d572012-12-04 15:56:20264
rtennetibe635732014-10-02 22:51:42265 socket_data_.reset(new StaticSocketDataProvider(
Ryan Sleevib8d7ea02018-05-07 20:01:01266 base::span<MockRead>(),
267 base::make_span(mock_writes_.get(), writes_.size())));
[email protected]f702d572012-12-04 15:56:20268
danakjad1777e2016-04-16 00:56:42269 std::unique_ptr<MockUDPClientSocket> socket(new MockUDPClientSocket(
xunjielib53b38c2016-03-24 15:54:36270 socket_data_.get(), net_log_.bound().net_log()));
[email protected]e13201d82012-12-12 05:00:32271 socket->Connect(peer_addr_);
[email protected]f702d572012-12-04 15:56:20272 runner_ = new TestTaskRunner(&clock_);
Ryan Hamilton8d9ee76e2018-05-29 23:52:52273 send_algorithm_ = new quic::test::MockSendAlgorithm();
rch7dd15702015-07-01 18:57:57274 EXPECT_CALL(*send_algorithm_, InRecovery()).WillRepeatedly(Return(false));
275 EXPECT_CALL(*send_algorithm_, InSlowStart()).WillRepeatedly(Return(false));
rjshaded5ced072015-12-18 19:26:02276 EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
Dan Zhangf11470172017-09-18 22:02:09277 .Times(testing::AtLeast(1));
rtenneti44f4a2e2015-08-07 14:00:07278 EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
Ryan Hamilton8d9ee76e2018-05-29 23:52:52279 .WillRepeatedly(Return(quic::kMaxPacketSize));
jokulik0e0a00c32016-06-13 21:51:58280 EXPECT_CALL(*send_algorithm_, PacingRate(_))
Ryan Hamilton8d9ee76e2018-05-29 23:52:52281 .WillRepeatedly(Return(quic::QuicBandwidth::Zero()));
Michael Warres74ee3ce2017-10-09 15:26:37282 EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true));
rtenneti44f4a2e2015-08-07 14:00:07283 EXPECT_CALL(*send_algorithm_, BandwidthEstimate())
Ryan Hamilton8d9ee76e2018-05-29 23:52:52284 .WillRepeatedly(Return(quic::QuicBandwidth::Zero()));
rch1e543ec2015-03-29 07:04:40285 EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(AnyNumber());
rch08cae032017-03-29 00:59:15286 EXPECT_CALL(*send_algorithm_, OnApplicationLimited(_)).Times(AnyNumber());
rch0d5bcf62017-05-24 22:48:45287 EXPECT_CALL(*send_algorithm_, GetCongestionControlType())
288 .Times(AnyNumber());
rch16c74d1d2016-04-22 06:14:07289 helper_.reset(
290 new QuicChromiumConnectionHelper(&clock_, &random_generator_));
291 alarm_factory_.reset(new QuicChromiumAlarmFactory(runner_.get(), &clock_));
292
Michael Warres74ee3ce2017-10-09 15:26:37293 connection_ = new TestQuicConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:52294 quic::test::SupportedVersions(
295 quic::ParsedQuicVersion(quic::PROTOCOL_QUIC_CRYPTO, version_)),
Dan Zhangfefaf5b2017-12-11 17:06:24296 connection_id_, peer_addr_, helper_.get(), alarm_factory_.get(),
Ryan Hamilton9edcf1a2017-11-22 05:55:17297 new QuicChromiumPacketWriter(
298 socket.get(), base::ThreadTaskRunnerHandle::Get().get()));
[email protected]f702d572012-12-04 15:56:20299 connection_->set_visitor(&visitor_);
[email protected]fee17f72013-02-03 07:47:41300 connection_->SetSendAlgorithm(send_algorithm_);
rch03b7a202016-02-05 00:54:20301
302 // Load a certificate that is valid for *.example.org
303 scoped_refptr<X509Certificate> test_cert(
304 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
305 EXPECT_TRUE(test_cert.get());
306
307 verify_details_.cert_verify_result.verified_cert = test_cert;
308 verify_details_.cert_verify_result.is_issued_by_known_root = true;
309 crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details_);
310
xunjieli84adaab2016-09-20 01:12:28311 base::TimeTicks dns_end = base::TimeTicks::Now();
312 base::TimeTicks dns_start = dns_end - base::TimeDelta::FromMilliseconds(1);
ckrasic4f9d88d2015-07-22 22:23:16313 session_.reset(new QuicChromiumClientSession(
xunjielib53b38c2016-03-24 15:54:36314 connection_, std::move(socket),
rtenneti1cd3b162015-09-29 02:58:28315 /*stream_factory=*/nullptr, &crypto_client_stream_factory_, &clock_,
bnc614a92d32016-04-04 13:56:07316 &transport_security_state_,
danakjad1777e2016-04-16 00:56:42317 base::WrapUnique(static_cast<QuicServerInfo*>(nullptr)),
Paul Jensen8e3c5d32018-02-19 17:06:33318 QuicSessionKey(kDefaultServerHostName, kDefaultServerPort,
319 PRIVACY_MODE_DISABLED, SocketTag()),
Zhongyi Shi757fcce2018-06-27 05:41:27320 /*require_confirmation=*/false, /*migrate_session_early_v2=*/false,
321 /*migrate_session_on_network_change_v2=*/false,
322 /*default_network=*/NetworkChangeNotifier::kInvalidNetworkHandle,
Zhongyi Shi73f23ca872017-12-13 18:37:13323 base::TimeDelta::FromSeconds(kMaxTimeOnNonDefaultNetworkSecs),
Zhongyi Shi8b1e43f2017-12-13 20:46:30324 kMaxMigrationsToNonDefaultNetworkOnPathDegrading,
Zhongyi Shi5f587cc2017-11-21 23:24:17325 kQuicYieldAfterPacketsRead,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52326 quic::QuicTime::Delta::FromMilliseconds(
327 kQuicYieldAfterDurationMilliseconds),
Yixin Wang079ad542018-01-11 04:06:05328 client_headers_include_h2_stream_dependency_, /*cert_verify_flags=*/0,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52329 quic::test::DefaultQuicConfig(), &crypto_config_, "CONNECTION_UNKNOWN",
330 dns_start, dns_end, &push_promise_index_, nullptr,
xunjieli84adaab2016-09-20 01:12:28331 base::ThreadTaskRunnerHandle::Get().get(),
xunjieli5fafe142016-03-23 23:32:54332 /*socket_performance_watcher=*/nullptr, net_log_.bound().net_log()));
rtennetid39bd762015-06-12 01:05:52333 session_->Initialize();
xunjieli100937eb52016-09-15 20:09:37334 TestCompletionCallback callback;
rchf0b18c8a2017-05-05 19:31:57335
rch433bf5f2017-02-14 04:10:47336 session_->CryptoConnect(callback.callback());
Ryan Hamilton6c2a2a82017-12-15 02:06:28337 stream_ = std::make_unique<QuicHttpStream>(
338 session_->CreateHandle(HostPortPair("www.example.org", 443)));
339 promised_stream_ = std::make_unique<QuicHttpStream>(
340 session_->CreateHandle(HostPortPair("www.example.org", 443)));
ckrasic3865ee0f2016-02-29 22:04:56341 push_promise_[":path"] = "/bar";
342 push_promise_[":authority"] = "www.example.org";
343 push_promise_[":version"] = "HTTP/1.1";
344 push_promise_[":method"] = "GET";
345 push_promise_[":scheme"] = "https";
346
347 promised_response_[":status"] = "200 OK";
348 promised_response_[":version"] = "HTTP/1.1";
349 promised_response_["content-type"] = "text/plain";
350
Ryan Hamilton8d9ee76e2018-05-29 23:52:52351 promise_url_ = quic::SpdyUtils::GetPromisedUrlFromHeaders(push_promise_);
[email protected]6cca996b2013-01-25 07:43:36352 }
353
bnc614a92d32016-04-04 13:56:07354 void SetRequest(const string& method,
355 const string& path,
[email protected]1e960032013-12-20 19:00:20356 RequestPriority priority) {
rchcd379012017-04-12 21:53:32357 request_headers_ = client_maker_.GetRequestHeaders(method, "https", path);
[email protected]6cca996b2013-01-25 07:43:36358 }
359
bnc614a92d32016-04-04 13:56:07360 void SetResponse(const string& status, const string& body) {
alyssar2adf3ac2016-05-03 17:12:58361 response_headers_ = server_maker_.GetResponseHeaders(status);
[email protected]92bf17c2014-03-03 21:14:03362 response_data_ = body;
[email protected]6cca996b2013-01-25 07:43:36363 }
[email protected]f702d572012-12-04 15:56:20364
Ryan Hamilton8d9ee76e2018-05-29 23:52:52365 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructDataPacket(
366 quic::QuicPacketNumber packet_number,
367 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56368 bool should_include_version,
369 bool fin,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52370 quic::QuicStreamOffset offset,
371 quic::QuicStringPiece data,
alyssar2adf3ac2016-05-03 17:12:58372 QuicTestPacketMaker* maker) {
373 return maker->MakeDataPacket(packet_number, stream_id,
ckrasic3865ee0f2016-02-29 22:04:56374 should_include_version, fin, offset, data);
375 }
376
Ryan Hamilton8d9ee76e2018-05-29 23:52:52377 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientDataPacket(
378 quic::QuicPacketNumber packet_number,
[email protected]e8ff26842013-03-22 21:02:05379 bool should_include_version,
[email protected]f702d572012-12-04 15:56:20380 bool fin,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52381 quic::QuicStreamOffset offset,
382 quic::QuicStringPiece data) {
ckrasic3865ee0f2016-02-29 22:04:56383 return InnerConstructDataPacket(packet_number, stream_id_,
alyssar2adf3ac2016-05-03 17:12:58384 should_include_version, fin, offset, data,
385 &client_maker_);
386 }
387
Ryan Hamilton8d9ee76e2018-05-29 23:52:52388 std::unique_ptr<quic::QuicReceivedPacket> ConstructServerDataPacket(
389 quic::QuicPacketNumber packet_number,
alyssar2adf3ac2016-05-03 17:12:58390 bool should_include_version,
391 bool fin,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52392 quic::QuicStreamOffset offset,
393 quic::QuicStringPiece data) {
alyssar2adf3ac2016-05-03 17:12:58394 return InnerConstructDataPacket(packet_number, stream_id_,
395 should_include_version, fin, offset, data,
396 &server_maker_);
ckrasic3865ee0f2016-02-29 22:04:56397 }
398
Ryan Hamilton8d9ee76e2018-05-29 23:52:52399 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructRequestHeadersPacket(
400 quic::QuicPacketNumber packet_number,
401 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56402 bool should_include_version,
403 bool fin,
404 RequestPriority request_priority,
xunjieli100937eb52016-09-15 20:09:37405 size_t* spdy_headers_frame_length,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52406 quic::QuicStreamOffset* offset) {
Yixin Wang7a3f1b8d2018-01-17 21:40:48407 return InnerConstructRequestHeadersPacket(
408 packet_number, stream_id, should_include_version, fin, request_priority,
409 0, spdy_headers_frame_length, offset);
410 }
411
Ryan Hamilton8d9ee76e2018-05-29 23:52:52412 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructRequestHeadersPacket(
413 quic::QuicPacketNumber packet_number,
414 quic::QuicStreamId stream_id,
Yixin Wang7a3f1b8d2018-01-17 21:40:48415 bool should_include_version,
416 bool fin,
417 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52418 quic::QuicStreamId parent_stream_id,
Yixin Wang7a3f1b8d2018-01-17 21:40:48419 size_t* spdy_headers_frame_length,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52420 quic::QuicStreamOffset* offset) {
Ryan Hamilton0239aac2018-05-19 00:03:13421 spdy::SpdyPriority priority =
ckrasic3865ee0f2016-02-29 22:04:56422 ConvertRequestPriorityToQuicPriority(request_priority);
alyssar2adf3ac2016-05-03 17:12:58423 return client_maker_.MakeRequestHeadersPacket(
ckrasic3865ee0f2016-02-29 22:04:56424 packet_number, stream_id, should_include_version, fin, priority,
Yixin Wang7a3f1b8d2018-01-17 21:40:48425 std::move(request_headers_), parent_stream_id,
426 spdy_headers_frame_length, offset);
[email protected]f702d572012-12-04 15:56:20427 }
428
Ryan Hamilton8d9ee76e2018-05-29 23:52:52429 std::unique_ptr<quic::QuicReceivedPacket>
Yixin Wange7ecc472018-03-06 19:00:25430 ConstructRequestHeadersAndDataFramesPacket(
Ryan Hamilton8d9ee76e2018-05-29 23:52:52431 quic::QuicPacketNumber packet_number,
432 quic::QuicStreamId stream_id,
Yixin Wange7ecc472018-03-06 19:00:25433 bool should_include_version,
434 bool fin,
435 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52436 quic::QuicStreamId parent_stream_id,
437 quic::QuicStreamOffset* offset,
Yixin Wange7ecc472018-03-06 19:00:25438 size_t* spdy_headers_frame_length,
439 const std::vector<std::string>& data_writes) {
Ryan Hamilton0239aac2018-05-19 00:03:13440 spdy::SpdyPriority priority =
Yixin Wange7ecc472018-03-06 19:00:25441 ConvertRequestPriorityToQuicPriority(request_priority);
442 return client_maker_.MakeRequestHeadersAndMultipleDataFramesPacket(
443 packet_number, stream_id, should_include_version, fin, priority,
444 std::move(request_headers_), parent_stream_id, offset,
445 spdy_headers_frame_length, data_writes);
446 }
447
Ryan Hamilton8d9ee76e2018-05-29 23:52:52448 std::unique_ptr<quic::QuicReceivedPacket> ConstructRequestAndRstPacket(
449 quic::QuicPacketNumber packet_number,
450 quic::QuicStreamId stream_id,
Yixin Wange7ecc472018-03-06 19:00:25451 bool should_include_version,
452 bool fin,
453 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52454 quic::QuicStreamId parent_stream_id,
Yixin Wange7ecc472018-03-06 19:00:25455 size_t* spdy_headers_frame_length,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52456 quic::QuicStreamOffset* header_stream_offset,
457 quic::QuicRstStreamErrorCode error_code,
Yixin Wange7ecc472018-03-06 19:00:25458 size_t bytes_written) {
Ryan Hamilton0239aac2018-05-19 00:03:13459 spdy::SpdyPriority priority =
Yixin Wange7ecc472018-03-06 19:00:25460 ConvertRequestPriorityToQuicPriority(request_priority);
461 return client_maker_.MakeRequestHeadersAndRstPacket(
462 packet_number, stream_id, should_include_version, fin, priority,
463 std::move(request_headers_), parent_stream_id,
464 spdy_headers_frame_length, header_stream_offset, error_code,
465 bytes_written);
466 }
467
Ryan Hamilton8d9ee76e2018-05-29 23:52:52468 std::unique_ptr<quic::QuicReceivedPacket> ConstructRequestHeadersPacket(
469 quic::QuicPacketNumber packet_number,
rtennetif4bdb542015-01-21 14:33:05470 bool fin,
sclittlec4dc1a32015-09-24 00:15:45471 RequestPriority request_priority,
472 size_t* spdy_headers_frame_length) {
ckrasic3865ee0f2016-02-29 22:04:56473 return InnerConstructRequestHeadersPacket(
474 packet_number, stream_id_, kIncludeVersion, fin, request_priority,
xunjieli100937eb52016-09-15 20:09:37475 spdy_headers_frame_length, nullptr);
ckrasic3865ee0f2016-02-29 22:04:56476 }
477
Ryan Hamilton8d9ee76e2018-05-29 23:52:52478 std::unique_ptr<quic::QuicReceivedPacket> InnerConstructResponseHeadersPacket(
479 quic::QuicPacketNumber packet_number,
480 quic::QuicStreamId stream_id,
ckrasic3865ee0f2016-02-29 22:04:56481 bool fin,
482 size_t* spdy_headers_frame_length) {
alyssar2adf3ac2016-05-03 17:12:58483 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26484 packet_number, stream_id, !kIncludeVersion, fin,
485 std::move(response_headers_), spdy_headers_frame_length,
486 &response_offset_);
[email protected]1e960032013-12-20 19:00:20487 }
488
Ryan Hamilton8d9ee76e2018-05-29 23:52:52489 std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseHeadersPacket(
490 quic::QuicPacketNumber packet_number,
sclittlec4dc1a32015-09-24 00:15:45491 bool fin,
492 size_t* spdy_headers_frame_length) {
ckrasic3865ee0f2016-02-29 22:04:56493 return InnerConstructResponseHeadersPacket(packet_number, stream_id_, fin,
494 spdy_headers_frame_length);
[email protected]1e960032013-12-20 19:00:20495 }
496
Ryan Hamilton8d9ee76e2018-05-29 23:52:52497 std::unique_ptr<quic::QuicReceivedPacket>
498 ConstructResponseHeadersPacketWithOffset(quic::QuicPacketNumber packet_number,
499 bool fin,
500 size_t* spdy_headers_frame_length,
501 quic::QuicStreamOffset* offset) {
alyssar2adf3ac2016-05-03 17:12:58502 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26503 packet_number, stream_id_, !kIncludeVersion, fin,
504 std::move(response_headers_), spdy_headers_frame_length, offset);
xunjieli34291fe12016-03-02 13:58:38505 }
506
Ryan Hamilton8d9ee76e2018-05-29 23:52:52507 std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseTrailersPacket(
508 quic::QuicPacketNumber packet_number,
xunjieli34291fe12016-03-02 13:58:38509 bool fin,
Ryan Hamilton0239aac2018-05-19 00:03:13510 spdy::SpdyHeaderBlock trailers,
xunjieli34291fe12016-03-02 13:58:38511 size_t* spdy_headers_frame_length,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52512 quic::QuicStreamOffset* offset) {
alyssar2adf3ac2016-05-03 17:12:58513 return server_maker_.MakeResponseHeadersPacket(
bnc086b39e12016-06-24 13:05:26514 packet_number, stream_id_, !kIncludeVersion, fin, std::move(trailers),
alyssar2adf3ac2016-05-03 17:12:58515 spdy_headers_frame_length, offset);
xunjieli34291fe12016-03-02 13:58:38516 }
517
Ryan Hamilton8d9ee76e2018-05-29 23:52:52518 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientRstStreamPacket(
519 quic::QuicPacketNumber packet_number) {
alyssara72f5352016-10-20 12:45:16520 return client_maker_.MakeRstPacket(packet_number, true, stream_id_,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52521 quic::QUIC_RST_ACKNOWLEDGEMENT);
[email protected]06ff5152013-08-29 01:03:05522 }
523
Ryan Hamilton8d9ee76e2018-05-29 23:52:52524 std::unique_ptr<quic::QuicReceivedPacket>
525 ConstructClientRstStreamCancelledPacket(
526 quic::QuicPacketNumber packet_number) {
alyssar2adf3ac2016-05-03 17:12:58527 return client_maker_.MakeRstPacket(packet_number, !kIncludeVersion,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52528 stream_id_, quic::QUIC_STREAM_CANCELLED);
rtenneti6bd660b2015-07-18 00:19:53529 }
530
Ryan Hamilton8d9ee76e2018-05-29 23:52:52531 std::unique_ptr<quic::QuicReceivedPacket>
532 ConstructClientRstStreamVaryMismatchPacket(
533 quic::QuicPacketNumber packet_number) {
alyssar2adf3ac2016-05-03 17:12:58534 return client_maker_.MakeRstPacket(packet_number, !kIncludeVersion,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52535 promise_id_,
536 quic::QUIC_PROMISE_VARY_MISMATCH);
ckrasic3865ee0f2016-02-29 22:04:56537 }
538
Fan Yang550c6282018-06-22 18:53:25539 std::unique_ptr<quic::QuicReceivedPacket>
540 ConstructClientRstStreamVaryMismatchAndRequestHeadersPacket(
541 quic::QuicPacketNumber packet_number,
542 quic::QuicStreamId stream_id,
543 bool should_include_version,
544 bool fin,
545 RequestPriority request_priority,
546 quic::QuicStreamId parent_stream_id,
547 size_t* spdy_headers_frame_length,
548 quic::QuicStreamOffset* offset) {
549 spdy::SpdyPriority priority =
550 ConvertRequestPriorityToQuicPriority(request_priority);
551 return client_maker_.MakeRstAndRequestHeadersPacket(
552 packet_number, should_include_version, promise_id_,
553 quic::QUIC_PROMISE_VARY_MISMATCH, stream_id, fin, priority,
554 std::move(request_headers_), parent_stream_id,
555 spdy_headers_frame_length, offset);
556 }
557
Ryan Hamilton8d9ee76e2018-05-29 23:52:52558 std::unique_ptr<quic::QuicReceivedPacket> ConstructAckAndRstStreamPacket(
559 quic::QuicPacketNumber packet_number,
560 quic::QuicPacketNumber largest_received,
561 quic::QuicPacketNumber smallest_received,
562 quic::QuicPacketNumber least_unacked) {
alyssar2adf3ac2016-05-03 17:12:58563 return client_maker_.MakeAckAndRstPacket(
Ryan Hamilton8d9ee76e2018-05-29 23:52:52564 packet_number, !kIncludeVersion, stream_id_,
565 quic::QUIC_STREAM_CANCELLED, largest_received, smallest_received,
566 least_unacked, !kIncludeCongestionFeedback);
xunjieli34291fe12016-03-02 13:58:38567 }
568
Ryan Hamilton8d9ee76e2018-05-29 23:52:52569 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientRstStreamErrorPacket(
570 quic::QuicPacketNumber packet_number,
maksim.sisov84e20c92016-06-23 08:49:34571 bool include_version) {
572 return client_maker_.MakeRstPacket(packet_number, include_version,
573 stream_id_,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52574 quic::QUIC_ERROR_PROCESSING_STREAM);
maksim.sisov84e20c92016-06-23 08:49:34575 }
576
Ryan Hamilton8d9ee76e2018-05-29 23:52:52577 std::unique_ptr<quic::QuicReceivedPacket> ConstructAckAndRstStreamPacket(
578 quic::QuicPacketNumber packet_number) {
xunjieli34291fe12016-03-02 13:58:38579 return ConstructAckAndRstStreamPacket(packet_number, 2, 1, 1);
[email protected]c5e1aca2014-01-30 04:03:04580 }
581
Ryan Hamilton8d9ee76e2018-05-29 23:52:52582 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientAckPacket(
583 quic::QuicPacketNumber packet_number,
584 quic::QuicPacketNumber largest_received,
585 quic::QuicPacketNumber smallest_received,
586 quic::QuicPacketNumber least_unacked) {
alyssar2adf3ac2016-05-03 17:12:58587 return client_maker_.MakeAckPacket(packet_number, largest_received,
wangyix6444ffe2017-04-25 17:49:49588 smallest_received, least_unacked,
alyssar2adf3ac2016-05-03 17:12:58589 !kIncludeCongestionFeedback);
590 }
591
Ryan Hamilton8d9ee76e2018-05-29 23:52:52592 std::unique_ptr<quic::QuicReceivedPacket> ConstructServerAckPacket(
593 quic::QuicPacketNumber packet_number,
594 quic::QuicPacketNumber largest_received,
595 quic::QuicPacketNumber smallest_received,
596 quic::QuicPacketNumber least_unacked) {
alyssar2adf3ac2016-05-03 17:12:58597 return server_maker_.MakeAckPacket(packet_number, largest_received,
wangyix6444ffe2017-04-25 17:49:49598 smallest_received, least_unacked,
alyssar2adf3ac2016-05-03 17:12:58599 !kIncludeCongestionFeedback);
[email protected]63534512012-12-23 18:49:00600 }
601
Ryan Hamilton8d9ee76e2018-05-29 23:52:52602 std::unique_ptr<quic::QuicReceivedPacket> ConstructClientPriorityPacket(
603 quic::QuicPacketNumber packet_number,
Yixin Wangb470bc882018-02-15 18:43:57604 bool should_include_version,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52605 quic::QuicStreamId id,
606 quic::QuicStreamId parent_stream_id,
Yixin Wangb470bc882018-02-15 18:43:57607 RequestPriority request_priority,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52608 quic::QuicStreamOffset* header_stream_offset) {
Yixin Wangb470bc882018-02-15 18:43:57609 return client_maker_.MakePriorityPacket(
610 packet_number, should_include_version, id, parent_stream_id,
611 ConvertRequestPriorityToQuicPriority(request_priority),
612 header_stream_offset);
613 }
614
Ryan Hamilton8d9ee76e2018-05-29 23:52:52615 std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket(
616 quic::QuicStreamOffset* offset) {
rch5cb522462017-04-25 20:18:36617 return client_maker_.MakeInitialSettingsPacket(1, offset);
fayang3bcb8b502016-12-07 21:44:37618 }
619
Ryan Hamilton8d9ee76e2018-05-29 23:52:52620 void ReceivePromise(quic::QuicStreamId id) {
621 auto headers = quic::test::AsHeaderList(push_promise_);
rch08e198572017-05-09 16:56:55622 QuicChromiumClientStream::Handle* stream =
ckrasic3865ee0f2016-02-29 22:04:56623 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
ckrasic32b17dcd2016-10-31 06:15:35624 stream->OnPromiseHeaderList(id, headers.uncompressed_header_bytes(),
625 headers);
ckrasic3865ee0f2016-02-29 22:04:56626 }
627
xunjieli84adaab2016-09-20 01:12:28628 void ExpectLoadTimingValid(const LoadTimingInfo& load_timing_info,
xunjieli100937eb52016-09-15 20:09:37629 bool session_reused) {
630 EXPECT_EQ(session_reused, load_timing_info.socket_reused);
xunjieli84adaab2016-09-20 01:12:28631 if (session_reused) {
632 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
633 } else {
634 ExpectConnectTimingHasTimes(
635 load_timing_info.connect_timing,
636 CONNECT_TIMING_HAS_SSL_TIMES | CONNECT_TIMING_HAS_DNS_TIMES);
637 }
638 ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info);
xunjieli100937eb52016-09-15 20:09:37639 }
640
Ryan Hamilton8d9ee76e2018-05-29 23:52:52641 quic::QuicStreamId GetNthClientInitiatedStreamId(int n) {
642 return quic::test::GetNthClientInitiatedStreamId(version_, n);
ckrasicbf2f59c2017-05-04 23:54:36643 }
644
Ryan Hamilton8d9ee76e2018-05-29 23:52:52645 quic::QuicStreamId GetNthServerInitiatedStreamId(int n) {
646 return quic::test::GetNthServerInitiatedStreamId(version_, n);
ckrasicbf2f59c2017-05-04 23:54:36647 }
648
Ryan Hamilton8d9ee76e2018-05-29 23:52:52649 const quic::QuicTransportVersion version_;
Yixin Wang079ad542018-01-11 04:06:05650 const bool client_headers_include_h2_stream_dependency_;
651
xunjieli5fafe142016-03-23 23:32:54652 BoundTestNetLog net_log_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52653 quic::test::MockSendAlgorithm* send_algorithm_;
[email protected]f702d572012-12-04 15:56:20654 scoped_refptr<TestTaskRunner> runner_;
danakjad1777e2016-04-16 00:56:42655 std::unique_ptr<MockWrite[]> mock_writes_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52656 quic::MockClock clock_;
[email protected]f702d572012-12-04 15:56:20657 TestQuicConnection* connection_;
danakjad1777e2016-04-16 00:56:42658 std::unique_ptr<QuicChromiumConnectionHelper> helper_;
rch16c74d1d2016-04-22 06:14:07659 std::unique_ptr<QuicChromiumAlarmFactory> alarm_factory_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52660 testing::StrictMock<quic::test::MockQuicConnectionVisitor> visitor_;
rch97827ee2017-05-24 23:49:12661 std::unique_ptr<UploadDataStream> upload_data_stream_;
danakjad1777e2016-04-16 00:56:42662 std::unique_ptr<QuicHttpStream> stream_;
[email protected]5db452202014-08-19 05:22:15663 TransportSecurityState transport_security_state_;
danakjad1777e2016-04-16 00:56:42664 std::unique_ptr<QuicChromiumClientSession> session_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52665 quic::QuicCryptoClientConfig crypto_config_;
[email protected]f702d572012-12-04 15:56:20666 TestCompletionCallback callback_;
667 HttpRequestInfo request_;
668 HttpRequestHeaders headers_;
669 HttpResponseInfo response_;
670 scoped_refptr<IOBufferWithSize> read_buffer_;
Ryan Hamilton0239aac2018-05-19 00:03:13671 spdy::SpdyHeaderBlock request_headers_;
672 spdy::SpdyHeaderBlock response_headers_;
bnc614a92d32016-04-04 13:56:07673 string request_data_;
674 string response_data_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52675 quic::QuicClientPushPromiseIndex push_promise_index_;
[email protected]f702d572012-12-04 15:56:20676
ckrasic3865ee0f2016-02-29 22:04:56677 // For server push testing
danakjad1777e2016-04-16 00:56:42678 std::unique_ptr<QuicHttpStream> promised_stream_;
Ryan Hamilton0239aac2018-05-19 00:03:13679 spdy::SpdyHeaderBlock push_promise_;
680 spdy::SpdyHeaderBlock promised_response_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52681 const quic::QuicStreamId promise_id_;
ckrasic3865ee0f2016-02-29 22:04:56682 string promise_url_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52683 const quic::QuicStreamId stream_id_;
ckrasic3865ee0f2016-02-29 22:04:56684
Ryan Hamilton8d9ee76e2018-05-29 23:52:52685 const quic::QuicConnectionId connection_id_;
alyssar2adf3ac2016-05-03 17:12:58686 QuicTestPacketMaker client_maker_;
687 QuicTestPacketMaker server_maker_;
[email protected]f702d572012-12-04 15:56:20688 IPEndPoint self_addr_;
689 IPEndPoint peer_addr_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52690 quic::test::MockRandom random_generator_;
rch03b7a202016-02-05 00:54:20691 ProofVerifyDetailsChromium verify_details_;
[email protected]e8ff26842013-03-22 21:02:05692 MockCryptoClientStreamFactory crypto_client_stream_factory_;
danakjad1777e2016-04-16 00:56:42693 std::unique_ptr<StaticSocketDataProvider> socket_data_;
[email protected]f702d572012-12-04 15:56:20694 std::vector<PacketToWrite> writes_;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52695 quic::QuicStreamOffset response_offset_;
[email protected]f702d572012-12-04 15:56:20696};
697
Yixin Wang079ad542018-01-11 04:06:05698INSTANTIATE_TEST_CASE_P(
Bence Békyce380cb2018-04-26 23:39:55699 VersionIncludeStreamDependencySequence,
Yixin Wang079ad542018-01-11 04:06:05700 QuicHttpStreamTest,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52701 ::testing::Combine(
702 ::testing::ValuesIn(quic::AllSupportedTransportVersions()),
703 ::testing::Bool()));
[email protected]1e960032013-12-20 19:00:20704
705TEST_P(QuicHttpStreamTest, RenewStreamForAuth) {
[email protected]ed3fc15d2013-03-08 18:37:44706 Initialize();
rtennetibe635732014-10-02 22:51:42707 EXPECT_EQ(nullptr, stream_->RenewStreamForAuth());
[email protected]f702d572012-12-04 15:56:20708}
709
mmenkebd84c392015-09-02 14:12:34710TEST_P(QuicHttpStreamTest, CanReuseConnection) {
[email protected]ed3fc15d2013-03-08 18:37:44711 Initialize();
mmenkebd84c392015-09-02 14:12:34712 EXPECT_FALSE(stream_->CanReuseConnection());
[email protected]f702d572012-12-04 15:56:20713}
714
jri231c2972016-03-08 19:50:11715TEST_P(QuicHttpStreamTest, DisableConnectionMigrationForStream) {
Zhongyi Shibb28b1f2018-07-18 02:41:26716 request_.load_flags |= LOAD_DISABLE_CONNECTION_MIGRATION_TO_CELLULAR;
jri231c2972016-03-08 19:50:11717 Initialize();
xunjieli5fafe142016-03-23 23:32:54718 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27719 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:54720 net_log_.bound(), callback_.callback()));
rch08e198572017-05-09 16:56:55721 QuicChromiumClientStream::Handle* client_stream =
jri231c2972016-03-08 19:50:11722 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
Zhongyi Shibb28b1f2018-07-18 02:41:26723 EXPECT_FALSE(client_stream->can_migrate_to_cellular_network());
jri231c2972016-03-08 19:50:11724}
725
[email protected]1e960032013-12-20 19:00:20726TEST_P(QuicHttpStreamTest, GetRequest) {
727 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:45728 size_t spdy_request_header_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52729 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:36730 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:37731 AddWrite(InnerConstructRequestHeadersPacket(
ckrasicbf2f59c2017-05-04 23:54:36732 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, kFin,
733 DEFAULT_PRIORITY, &spdy_request_header_frame_length,
734 &header_stream_offset));
fayang3bcb8b502016-12-07 21:44:37735
[email protected]f702d572012-12-04 15:56:20736 Initialize();
737
738 request_.method = "GET";
rchcd379012017-04-12 21:53:32739 request_.url = GURL("https://www.example.org/");
[email protected]f702d572012-12-04 15:56:20740
xunjieli100937eb52016-09-15 20:09:37741 // Make sure getting load timing from the stream early does not crash.
742 LoadTimingInfo load_timing_info;
743 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
744
xunjieli5fafe142016-03-23 23:32:54745 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27746 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:54747 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:02748 EXPECT_EQ(OK,
749 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20750
751 // Ack the request.
wangyix6444ffe2017-04-25 17:49:49752 ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
[email protected]f702d572012-12-04 15:56:20753
robpercival214763f2016-07-01 23:27:01754 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
755 IsError(ERR_IO_PENDING));
[email protected]f702d572012-12-04 15:56:20756
bnc614a92d32016-04-04 13:56:07757 SetResponse("404 Not Found", string());
sclittlec4dc1a32015-09-24 00:15:45758 size_t spdy_response_header_frame_length;
759 ProcessPacket(ConstructResponseHeadersPacket(
760 2, kFin, &spdy_response_header_frame_length));
[email protected]f702d572012-12-04 15:56:20761
762 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:01763 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]cadac622013-06-11 16:46:36764 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:20765 EXPECT_EQ(404, response_.headers->response_code());
766 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
[email protected]6ed67432014-06-24 01:53:53767 EXPECT_FALSE(response_.response_time.is_null());
768 EXPECT_FALSE(response_.request_time.is_null());
[email protected]f702d572012-12-04 15:56:20769
770 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:02771 EXPECT_EQ(0,
772 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
773 callback_.callback()));
[email protected]f702d572012-12-04 15:56:20774 EXPECT_TRUE(stream_->IsResponseBodyComplete());
775 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:10776
xunjieli100937eb52016-09-15 20:09:37777 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
xunjieli84adaab2016-09-20 01:12:28778 ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
xunjieli100937eb52016-09-15 20:09:37779
sclittle1edeeb22015-09-02 20:46:10780 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:45781 // headers and payload.
782 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
783 stream_->GetTotalSentBytes());
784 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length),
785 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:20786}
787
xunjieli100937eb52016-09-15 20:09:37788TEST_P(QuicHttpStreamTest, LoadTimingTwoRequests) {
789 SetRequest("GET", "/", DEFAULT_PRIORITY);
790 size_t spdy_request_header_frame_length;
791
Ryan Hamilton8d9ee76e2018-05-29 23:52:52792 quic::QuicStreamOffset offset = 0;
rch5cb522462017-04-25 20:18:36793 AddWrite(ConstructInitialSettingsPacket(&offset));
xunjieli100937eb52016-09-15 20:09:37794 AddWrite(InnerConstructRequestHeadersPacket(
ckrasicbf2f59c2017-05-04 23:54:36795 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, kFin,
796 DEFAULT_PRIORITY, &spdy_request_header_frame_length, &offset));
xunjieli100937eb52016-09-15 20:09:37797
798 // SetRequest() again for second request as |request_headers_| was moved.
799 SetRequest("GET", "/", DEFAULT_PRIORITY);
800 AddWrite(InnerConstructRequestHeadersPacket(
ckrasicbf2f59c2017-05-04 23:54:36801 3, GetNthClientInitiatedStreamId(1), kIncludeVersion, kFin,
Yixin Wang7a3f1b8d2018-01-17 21:40:48802 DEFAULT_PRIORITY, GetNthClientInitiatedStreamId(0),
803 &spdy_request_header_frame_length, &offset));
wangyix6444ffe2017-04-25 17:49:49804 AddWrite(ConstructClientAckPacket(4, 3, 1, 1)); // Ack the responses.
xunjieli100937eb52016-09-15 20:09:37805
806 Initialize();
807
808 request_.method = "GET";
rchcd379012017-04-12 21:53:32809 request_.url = GURL("https://www.example.org/");
xunjieli100937eb52016-09-15 20:09:37810 // Start first request.
811 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27812 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli100937eb52016-09-15 20:09:37813 net_log_.bound(), callback_.callback()));
814 EXPECT_EQ(OK,
815 stream_->SendRequest(headers_, &response_, callback_.callback()));
816
817 // Start a second request.
Ryan Hamilton6c2a2a82017-12-15 02:06:28818 QuicHttpStream stream2(
819 session_->CreateHandle(HostPortPair("www.example.org", 443)));
xunjieli100937eb52016-09-15 20:09:37820 TestCompletionCallback callback2;
821 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27822 stream2.InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli100937eb52016-09-15 20:09:37823 net_log_.bound(), callback2.callback()));
824 EXPECT_EQ(OK,
825 stream2.SendRequest(headers_, &response_, callback2.callback()));
826
827 // Ack both requests.
wangyix6444ffe2017-04-25 17:49:49828 ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
xunjieli100937eb52016-09-15 20:09:37829
830 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
831 IsError(ERR_IO_PENDING));
832 size_t spdy_response_header_frame_length;
833 SetResponse("200 OK", string());
834 ProcessPacket(InnerConstructResponseHeadersPacket(
ckrasicbf2f59c2017-05-04 23:54:36835 2, GetNthClientInitiatedStreamId(0), kFin,
836 &spdy_response_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37837
838 // Now that the headers have been processed, the callback will return.
839 EXPECT_THAT(callback_.WaitForResult(), IsOk());
840 EXPECT_EQ(200, response_.headers->response_code());
841
842 // There is no body, so this should return immediately.
843 EXPECT_EQ(0,
844 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
845 callback_.callback()));
846 EXPECT_TRUE(stream_->IsResponseBodyComplete());
847
848 LoadTimingInfo load_timing_info;
849 EXPECT_TRUE(stream_->GetLoadTimingInfo(&load_timing_info));
xunjieli84adaab2016-09-20 01:12:28850 ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
xunjieli100937eb52016-09-15 20:09:37851
852 // SetResponse() again for second request as |response_headers_| was moved.
853 SetResponse("200 OK", string());
854 EXPECT_THAT(stream2.ReadResponseHeaders(callback2.callback()),
855 IsError(ERR_IO_PENDING));
856
857 ProcessPacket(InnerConstructResponseHeadersPacket(
ckrasicbf2f59c2017-05-04 23:54:36858 3, GetNthClientInitiatedStreamId(1), kFin,
859 &spdy_response_header_frame_length));
xunjieli100937eb52016-09-15 20:09:37860
861 EXPECT_THAT(callback2.WaitForResult(), IsOk());
862
863 // There is no body, so this should return immediately.
864 EXPECT_EQ(0,
865 stream2.ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
866 callback2.callback()));
867 EXPECT_TRUE(stream2.IsResponseBodyComplete());
868
869 LoadTimingInfo load_timing_info2;
870 EXPECT_TRUE(stream2.GetLoadTimingInfo(&load_timing_info2));
xunjieli84adaab2016-09-20 01:12:28871 ExpectLoadTimingValid(load_timing_info2, /*session_reused=*/true);
xunjieli100937eb52016-09-15 20:09:37872}
873
xunjieli34291fe12016-03-02 13:58:38874// QuicHttpStream does not currently support trailers. It should ignore
875// trailers upon receiving them.
876TEST_P(QuicHttpStreamTest, GetRequestWithTrailers) {
877 SetRequest("GET", "/", DEFAULT_PRIORITY);
878 size_t spdy_request_header_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52879 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:36880 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:37881 AddWrite(InnerConstructRequestHeadersPacket(
ckrasicbf2f59c2017-05-04 23:54:36882 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, kFin,
883 DEFAULT_PRIORITY, &spdy_request_header_frame_length,
884 &header_stream_offset));
wangyix6444ffe2017-04-25 17:49:49885 AddWrite(ConstructClientAckPacket(3, 3, 1, 1)); // Ack the data packet.
xunjieli34291fe12016-03-02 13:58:38886
887 Initialize();
888
889 request_.method = "GET";
rchcd379012017-04-12 21:53:32890 request_.url = GURL("https://www.example.org/");
xunjieli34291fe12016-03-02 13:58:38891
xunjieli5fafe142016-03-23 23:32:54892 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27893 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:54894 net_log_.bound(), callback_.callback()));
895
xunjieli34291fe12016-03-02 13:58:38896 EXPECT_EQ(OK,
897 stream_->SendRequest(headers_, &response_, callback_.callback()));
xunjieli34291fe12016-03-02 13:58:38898 // Ack the request.
wangyix6444ffe2017-04-25 17:49:49899 ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
xunjieli34291fe12016-03-02 13:58:38900
robpercival214763f2016-07-01 23:27:01901 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
902 IsError(ERR_IO_PENDING));
xunjieli34291fe12016-03-02 13:58:38903
bnc614a92d32016-04-04 13:56:07904 SetResponse("200 OK", string());
xunjieli34291fe12016-03-02 13:58:38905
906 // Send the response headers.
907 size_t spdy_response_header_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52908 quic::QuicStreamOffset offset = 0;
xunjieli34291fe12016-03-02 13:58:38909 ProcessPacket(ConstructResponseHeadersPacketWithOffset(
910 2, !kFin, &spdy_response_header_frame_length, &offset));
911 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:01912 EXPECT_THAT(callback_.WaitForResult(), IsOk());
xunjieli34291fe12016-03-02 13:58:38913 ASSERT_TRUE(response_.headers.get());
914 EXPECT_EQ(200, response_.headers->response_code());
915 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
916 EXPECT_FALSE(response_.response_time.is_null());
917 EXPECT_FALSE(response_.request_time.is_null());
918
919 // Send the response body.
920 const char kResponseBody[] = "Hello world!";
921 ProcessPacket(
alyssar2adf3ac2016-05-03 17:12:58922 ConstructServerDataPacket(3, false, !kFin, /*offset=*/0, kResponseBody));
Ryan Hamilton0239aac2018-05-19 00:03:13923 spdy::SpdyHeaderBlock trailers;
xunjieli34291fe12016-03-02 13:58:38924 size_t spdy_trailers_frame_length;
925 trailers["foo"] = "bar";
Ryan Hamilton8d9ee76e2018-05-29 23:52:52926 trailers[quic::kFinalOffsetHeaderKey] =
927 base::IntToString(strlen(kResponseBody));
xunjieli34291fe12016-03-02 13:58:38928 ProcessPacket(ConstructResponseTrailersPacket(
bnc086b39e12016-06-24 13:05:26929 4, kFin, std::move(trailers), &spdy_trailers_frame_length, &offset));
xunjieli34291fe12016-03-02 13:58:38930
931 // Make sure trailers are processed.
fdoray92e35a72016-06-10 15:54:55932 base::RunLoop().RunUntilIdle();
xunjieli34291fe12016-03-02 13:58:38933
934 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
935 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
936 callback_.callback()));
937 EXPECT_TRUE(stream_->IsResponseBodyComplete());
938
939 EXPECT_EQ(OK,
940 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
941 callback_.callback()));
942
943 EXPECT_TRUE(stream_->IsResponseBodyComplete());
944 EXPECT_TRUE(AtEof());
945
946 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
947 // headers and payload.
948 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
949 stream_->GetTotalSentBytes());
950 EXPECT_EQ(
951 static_cast<int64_t>(spdy_response_header_frame_length +
952 strlen(kResponseBody) + +spdy_trailers_frame_length),
953 stream_->GetTotalReceivedBytes());
xunjieli5fafe142016-03-23 23:32:54954 // Check that NetLog was filled as expected.
955 TestNetLogEntry::List entries;
956 net_log_.GetEntries(&entries);
957 size_t pos = ExpectLogContainsSomewhere(
958 entries, /*min_offset=*/0,
mikecirone8b85c432016-09-08 19:11:00959 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
960 NetLogEventPhase::NONE);
xunjieli5fafe142016-03-23 23:32:54961 pos = ExpectLogContainsSomewhere(
962 entries, /*min_offset=*/pos,
mikecirone8b85c432016-09-08 19:11:00963 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
964 NetLogEventPhase::NONE);
xunjieli5fafe142016-03-23 23:32:54965 ExpectLogContainsSomewhere(
966 entries, /*min_offset=*/pos,
mikecirone8b85c432016-09-08 19:11:00967 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
968 NetLogEventPhase::NONE);
xunjieli34291fe12016-03-02 13:58:38969}
970
[email protected]3e7dca62013-09-10 16:14:23971// Regression test for http://crbug.com/288128
[email protected]1e960032013-12-20 19:00:20972TEST_P(QuicHttpStreamTest, GetRequestLargeResponse) {
973 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:45974 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52975 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:36976 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:37977 AddWrite(InnerConstructRequestHeadersPacket(
ckrasicbf2f59c2017-05-04 23:54:36978 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, kFin,
979 DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
980 &header_stream_offset));
[email protected]3e7dca62013-09-10 16:14:23981 Initialize();
982
983 request_.method = "GET";
rchcd379012017-04-12 21:53:32984 request_.url = GURL("https://www.example.org/");
[email protected]3e7dca62013-09-10 16:14:23985
xunjieli5fafe142016-03-23 23:32:54986 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:27987 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:54988 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:02989 EXPECT_EQ(OK,
990 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:23991
992 // Ack the request.
wangyix6444ffe2017-04-25 17:49:49993 ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
[email protected]3e7dca62013-09-10 16:14:23994
robpercival214763f2016-07-01 23:27:01995 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
996 IsError(ERR_IO_PENDING));
[email protected]3e7dca62013-09-10 16:14:23997
bnc086b39e12016-06-24 13:05:26998 response_headers_[":status"] = "200 OK";
999 response_headers_[":version"] = "HTTP/1.1";
1000 response_headers_["content-type"] = "text/plain";
1001 response_headers_["big6"] = string(1000, 'x'); // Lots of x's.
[email protected]3e7dca62013-09-10 16:14:231002
sclittlec4dc1a32015-09-24 00:15:451003 size_t spdy_response_headers_frame_length;
1004 ProcessPacket(ConstructResponseHeadersPacket(
1005 2, kFin, &spdy_response_headers_frame_length));
[email protected]3e7dca62013-09-10 16:14:231006
1007 // Now that the headers have been processed, the callback will return.
robpercival214763f2016-07-01 23:27:011008 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]3e7dca62013-09-10 16:14:231009 ASSERT_TRUE(response_.headers.get());
1010 EXPECT_EQ(200, response_.headers->response_code());
1011 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1012
1013 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:021014 EXPECT_EQ(0,
1015 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1016 callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:231017 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1018 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101019
1020 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451021 // headers and payload.
1022 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1023 stream_->GetTotalSentBytes());
1024 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length),
1025 stream_->GetTotalReceivedBytes());
[email protected]3e7dca62013-09-10 16:14:231026}
1027
rchf9f103cbc2014-08-30 05:28:041028// Regression test for http://crbug.com/409101
1029TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendRequest) {
1030 SetRequest("GET", "/", DEFAULT_PRIORITY);
1031 Initialize();
1032
1033 request_.method = "GET";
rchcd379012017-04-12 21:53:321034 request_.url = GURL("https://www.example.org/");
rchf9f103cbc2014-08-30 05:28:041035
xunjieli5fafe142016-03-23 23:32:541036 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271037 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541038 net_log_.bound(), callback_.callback()));
rchf9f103cbc2014-08-30 05:28:041039
jri78ec06a2016-03-31 18:19:401040 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521041 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rchf9f103cbc2014-08-30 05:28:041042
1043 EXPECT_EQ(ERR_CONNECTION_CLOSED,
rjshaded5ced072015-12-18 19:26:021044 stream_->SendRequest(headers_, &response_, callback_.callback()));
sclittle1edeeb22015-09-02 20:46:101045
1046 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1047 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rchf9f103cbc2014-08-30 05:28:041048}
1049
rch03b7a202016-02-05 00:54:201050// Regression test for http://crbug.com/584441
1051TEST_P(QuicHttpStreamTest, GetSSLInfoAfterSessionClosed) {
1052 SetRequest("GET", "/", DEFAULT_PRIORITY);
1053 Initialize();
1054
1055 request_.method = "GET";
rchcd379012017-04-12 21:53:321056 request_.url = GURL("https://www.example.org/");
rch03b7a202016-02-05 00:54:201057
xunjieli5fafe142016-03-23 23:32:541058 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271059 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541060 net_log_.bound(), callback_.callback()));
rch03b7a202016-02-05 00:54:201061
1062 SSLInfo ssl_info;
rch11565e02016-02-09 20:13:471063 EXPECT_FALSE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:201064 stream_->GetSSLInfo(&ssl_info);
rch11565e02016-02-09 20:13:471065 EXPECT_TRUE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:201066
jri78ec06a2016-03-31 18:19:401067 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521068 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rch03b7a202016-02-05 00:54:201069
rch11565e02016-02-09 20:13:471070 SSLInfo ssl_info2;
1071 stream_->GetSSLInfo(&ssl_info2);
1072 EXPECT_TRUE(ssl_info2.is_valid());
rch03b7a202016-02-05 00:54:201073}
1074
rchcd379012017-04-12 21:53:321075TEST_P(QuicHttpStreamTest, GetAlternativeService) {
1076 SetRequest("GET", "/", DEFAULT_PRIORITY);
1077 Initialize();
1078
1079 request_.method = "GET";
1080 request_.url = GURL("https://www.example.org/");
1081
1082 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271083 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
rchcd379012017-04-12 21:53:321084 net_log_.bound(), callback_.callback()));
1085
1086 AlternativeService alternative_service;
1087 EXPECT_TRUE(stream_->GetAlternativeService(&alternative_service));
1088 EXPECT_EQ(AlternativeService(kProtoQUIC, "www.example.org", 443),
1089 alternative_service);
1090
1091 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521092 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rchcd379012017-04-12 21:53:321093
1094 AlternativeService alternative_service2;
1095 EXPECT_TRUE(stream_->GetAlternativeService(&alternative_service2));
1096 EXPECT_EQ(AlternativeService(kProtoQUIC, "www.example.org", 443),
1097 alternative_service2);
1098}
1099
zhongyica364fbb2015-12-12 03:39:121100TEST_P(QuicHttpStreamTest, LogGranularQuicConnectionError) {
1101 SetRequest("GET", "/", DEFAULT_PRIORITY);
1102 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521103 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361104 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:371105 AddWrite(InnerConstructRequestHeadersPacket(
ckrasicbf2f59c2017-05-04 23:54:361106 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, kFin,
1107 DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
1108 &header_stream_offset));
fayang3bcb8b502016-12-07 21:44:371109 AddWrite(ConstructAckAndRstStreamPacket(3));
zhongyica364fbb2015-12-12 03:39:121110 Initialize();
1111
1112 request_.method = "GET";
rchcd379012017-04-12 21:53:321113 request_.url = GURL("https://www.example.org/");
zhongyica364fbb2015-12-12 03:39:121114
xunjieli5fafe142016-03-23 23:32:541115 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271116 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541117 net_log_.bound(), callback_.callback()));
zhongyica364fbb2015-12-12 03:39:121118 EXPECT_EQ(OK,
1119 stream_->SendRequest(headers_, &response_, callback_.callback()));
1120
1121 // Ack the request.
wangyix6444ffe2017-04-25 17:49:491122 ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
robpercival214763f2016-07-01 23:27:011123 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1124 IsError(ERR_IO_PENDING));
zhongyica364fbb2015-12-12 03:39:121125
Ryan Hamilton8d9ee76e2018-05-29 23:52:521126 quic::QuicConnectionCloseFrame frame;
1127 frame.error_code = quic::QUIC_PEER_GOING_AWAY;
rch1c5b74a2016-06-23 22:10:551128 session_->connection()->OnConnectionCloseFrame(frame);
zhongyica364fbb2015-12-12 03:39:121129
1130 NetErrorDetails details;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521131 EXPECT_EQ(quic::QUIC_NO_ERROR, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121132 stream_->PopulateNetErrorDetails(&details);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521133 EXPECT_EQ(quic::QUIC_PEER_GOING_AWAY, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121134}
1135
Ryan Hamiltone316e482017-08-17 02:48:531136TEST_P(QuicHttpStreamTest, LogGranularQuicErrorIfHandshakeNotConfirmed) {
rch617e0652017-04-26 17:57:511137 // By default the test setup defaults handshake to be confirmed. Manually set
1138 // it to be not confirmed.
rch617e0652017-04-26 17:57:511139 crypto_client_stream_factory_.set_handshake_mode(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521140 quic::MockCryptoClientStream::ZERO_RTT);
rch617e0652017-04-26 17:57:511141
zhongyica364fbb2015-12-12 03:39:121142 SetRequest("GET", "/", DEFAULT_PRIORITY);
1143 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521144 quic::QuicStreamOffset header_stream_offset = 0;
1145 client_maker_.SetEncryptionLevel(quic::ENCRYPTION_INITIAL);
1146 client_maker_.SetLongHeaderType(quic::ZERO_RTT_PROTECTED);
fayang3bcb8b502016-12-07 21:44:371147 AddWrite(InnerConstructRequestHeadersPacket(
ckrasicbf2f59c2017-05-04 23:54:361148 1, GetNthClientInitiatedStreamId(0), kIncludeVersion, kFin,
1149 DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
1150 &header_stream_offset));
zhongyica364fbb2015-12-12 03:39:121151 Initialize();
1152
1153 request_.method = "GET";
rchcd379012017-04-12 21:53:321154 request_.url = GURL("https://www.example.org/");
zhongyica364fbb2015-12-12 03:39:121155
xunjieli5fafe142016-03-23 23:32:541156 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271157 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541158 net_log_.bound(), callback_.callback()));
zhongyica364fbb2015-12-12 03:39:121159 EXPECT_EQ(OK,
1160 stream_->SendRequest(headers_, &response_, callback_.callback()));
1161
1162 // Ack the request.
wangyix6444ffe2017-04-25 17:49:491163 ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
robpercival214763f2016-07-01 23:27:011164 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1165 IsError(ERR_IO_PENDING));
zhongyica364fbb2015-12-12 03:39:121166
Ryan Hamilton8d9ee76e2018-05-29 23:52:521167 quic::QuicConnectionCloseFrame frame;
1168 frame.error_code = quic::QUIC_PEER_GOING_AWAY;
rch1c5b74a2016-06-23 22:10:551169 session_->connection()->OnConnectionCloseFrame(frame);
zhongyica364fbb2015-12-12 03:39:121170
1171 NetErrorDetails details;
zhongyica364fbb2015-12-12 03:39:121172 stream_->PopulateNetErrorDetails(&details);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521173 EXPECT_EQ(quic::QUIC_PEER_GOING_AWAY, details.quic_connection_error);
zhongyica364fbb2015-12-12 03:39:121174}
1175
rch11a114a2014-09-04 23:41:591176// Regression test for http://crbug.com/409871
1177TEST_P(QuicHttpStreamTest, SessionClosedBeforeReadResponseHeaders) {
1178 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451179 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521180 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361181 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:371182 AddWrite(InnerConstructRequestHeadersPacket(
ckrasicbf2f59c2017-05-04 23:54:361183 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, kFin,
1184 DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
1185 &header_stream_offset));
rch11a114a2014-09-04 23:41:591186 Initialize();
1187
1188 request_.method = "GET";
rchcd379012017-04-12 21:53:321189 request_.url = GURL("https://www.example.org/");
rch11a114a2014-09-04 23:41:591190
xunjieli5fafe142016-03-23 23:32:541191 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271192 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541193 net_log_.bound(), callback_.callback()));
rch11a114a2014-09-04 23:41:591194
rjshaded5ced072015-12-18 19:26:021195 EXPECT_EQ(OK,
1196 stream_->SendRequest(headers_, &response_, callback_.callback()));
rch11a114a2014-09-04 23:41:591197
jri78ec06a2016-03-31 18:19:401198 session_->connection()->CloseConnection(
Ryan Hamilton8d9ee76e2018-05-29 23:52:521199 quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
rch11a114a2014-09-04 23:41:591200
1201 EXPECT_NE(OK, stream_->ReadResponseHeaders(callback_.callback()));
sclittle1edeeb22015-09-02 20:46:101202
1203 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451204 // headers and payload.
1205 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1206 stream_->GetTotalSentBytes());
sclittle1edeeb22015-09-02 20:46:101207 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rch11a114a2014-09-04 23:41:591208}
1209
[email protected]1e960032013-12-20 19:00:201210TEST_P(QuicHttpStreamTest, SendPostRequest) {
1211 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451212 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521213 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361214 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
Yixin Wange7ecc472018-03-06 19:00:251215
1216 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1217 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, kFin,
1218 DEFAULT_PRIORITY, 0, &header_stream_offset,
1219 &spdy_request_headers_frame_length, {kUploadData}));
1220
1221 AddWrite(ConstructClientAckPacket(3, 3, 1, 1));
[email protected]f702d572012-12-04 15:56:201222
1223 Initialize();
1224
danakjad1777e2016-04-16 00:56:421225 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:191226 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
ricea2deef682016-09-09 08:04:071227 kUploadData, strlen(kUploadData)));
rch97827ee2017-05-24 23:49:121228 upload_data_stream_ =
Jeremy Roman0579ed62017-08-29 15:56:191229 std::make_unique<ElementsUploadDataStream>(std::move(element_readers), 0);
[email protected]f702d572012-12-04 15:56:201230 request_.method = "POST";
rchcd379012017-04-12 21:53:321231 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121232 request_.upload_data_stream = upload_data_stream_.get();
Bence Békyd8a21fc32018-06-27 18:29:581233 ASSERT_THAT(request_.upload_data_stream->Init(CompletionOnceCallback(),
tfarina42834112016-09-22 13:38:201234 NetLogWithSource()),
1235 IsOk());
[email protected]f702d572012-12-04 15:56:201236
xunjieli5fafe142016-03-23 23:32:541237 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271238 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541239 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021240 EXPECT_EQ(OK,
1241 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:201242
1243 // Ack both packets in the request.
wangyix6444ffe2017-04-25 17:49:491244 ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
[email protected]f702d572012-12-04 15:56:201245
1246 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071247 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451248 size_t spdy_response_headers_frame_length;
1249 ProcessPacket(ConstructResponseHeadersPacket(
1250 2, !kFin, &spdy_response_headers_frame_length));
[email protected]f702d572012-12-04 15:56:201251
rchfb47f712017-05-21 03:24:001252 // The headers have already arrived.
1253 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]cadac622013-06-11 16:46:361254 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:201255 EXPECT_EQ(200, response_.headers->response_code());
1256 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1257
1258 // Send the response body.
1259 const char kResponseBody[] = "Hello world!";
alyssar2adf3ac2016-05-03 17:12:581260 ProcessPacket(ConstructServerDataPacket(3, false, kFin, 0, kResponseBody));
[email protected]f702d572012-12-04 15:56:201261 // Since the body has already arrived, this should return immediately.
1262 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
1263 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1264 callback_.callback()));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291265 EXPECT_EQ(0,
1266 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1267 callback_.callback()));
1268
1269 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1270 EXPECT_TRUE(AtEof());
1271
1272 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
1273 // headers and payload.
1274 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
1275 strlen(kUploadData)),
1276 stream_->GetTotalSentBytes());
1277 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1278 strlen(kResponseBody)),
1279 stream_->GetTotalReceivedBytes());
1280}
1281
1282TEST_P(QuicHttpStreamTest, SendPostRequestAndReceiveSoloFin) {
1283 SetRequest("POST", "/", DEFAULT_PRIORITY);
1284 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521285 quic::QuicStreamOffset header_stream_offset = 0;
Ryan Hamilton2ef0a9c2017-07-25 03:18:291286 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
Yixin Wange7ecc472018-03-06 19:00:251287 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1288 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, kFin,
1289 DEFAULT_PRIORITY, 0, &header_stream_offset,
1290 &spdy_request_headers_frame_length, {kUploadData}));
1291 AddWrite(ConstructClientAckPacket(3, 3, 1, 1));
Ryan Hamilton2ef0a9c2017-07-25 03:18:291292
1293 Initialize();
1294
1295 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:191296 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
Ryan Hamilton2ef0a9c2017-07-25 03:18:291297 kUploadData, strlen(kUploadData)));
1298 upload_data_stream_ =
Jeremy Roman0579ed62017-08-29 15:56:191299 std::make_unique<ElementsUploadDataStream>(std::move(element_readers), 0);
Ryan Hamilton2ef0a9c2017-07-25 03:18:291300 request_.method = "POST";
1301 request_.url = GURL("https://www.example.org/");
1302 request_.upload_data_stream = upload_data_stream_.get();
Bence Békyd8a21fc32018-06-27 18:29:581303 ASSERT_THAT(request_.upload_data_stream->Init(CompletionOnceCallback(),
Ryan Hamilton2ef0a9c2017-07-25 03:18:291304 NetLogWithSource()),
1305 IsOk());
1306
1307 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271308 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
Ryan Hamilton2ef0a9c2017-07-25 03:18:291309 net_log_.bound(), callback_.callback()));
1310 EXPECT_EQ(OK,
1311 stream_->SendRequest(headers_, &response_, callback_.callback()));
1312
1313 // Ack both packets in the request.
1314 ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
1315
1316 // Send the response headers (but not the body).
1317 SetResponse("200 OK", string());
1318 size_t spdy_response_headers_frame_length;
1319 ProcessPacket(ConstructResponseHeadersPacket(
1320 2, !kFin, &spdy_response_headers_frame_length));
1321
1322 // The headers have already arrived.
1323 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
1324 ASSERT_TRUE(response_.headers.get());
1325 EXPECT_EQ(200, response_.headers->response_code());
1326 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1327
1328 // Send the response body.
1329 const char kResponseBody[] = "Hello world!";
1330 ProcessPacket(ConstructServerDataPacket(3, false, !kFin, 0, kResponseBody));
1331 // Since the body has already arrived, this should return immediately.
1332 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
1333 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1334 callback_.callback()));
1335 ProcessPacket(ConstructServerDataPacket(4, false, kFin,
1336 arraysize(kResponseBody) - 1, ""));
1337 EXPECT_EQ(0,
1338 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1339 callback_.callback()));
[email protected]f702d572012-12-04 15:56:201340
1341 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1342 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101343
1344 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451345 // headers and payload.
1346 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
1347 strlen(kUploadData)),
sclittle1edeeb22015-09-02 20:46:101348 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451349 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1350 strlen(kResponseBody)),
sclittle1edeeb22015-09-02 20:46:101351 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:201352}
1353
[email protected]1e960032013-12-20 19:00:201354TEST_P(QuicHttpStreamTest, SendChunkedPostRequest) {
1355 SetRequest("POST", "/", DEFAULT_PRIORITY);
[email protected]c9e49a02013-02-26 05:56:471356 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:451357 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521358 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361359 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
Yixin Wange7ecc472018-03-06 19:00:251360 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
ckrasicbf2f59c2017-05-04 23:54:361361 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, !kFin,
Yixin Wange7ecc472018-03-06 19:00:251362 DEFAULT_PRIORITY, 0, &header_stream_offset,
1363 &spdy_request_headers_frame_length, {kUploadData}));
1364 AddWrite(ConstructClientDataPacket(3, kIncludeVersion, kFin, chunk_size,
alyssar2adf3ac2016-05-03 17:12:581365 kUploadData));
Yixin Wange7ecc472018-03-06 19:00:251366 AddWrite(ConstructClientAckPacket(4, 3, 1, 1));
[email protected]c9e49a02013-02-26 05:56:471367 Initialize();
1368
Jeremy Roman0579ed62017-08-29 15:56:191369 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121370 auto* chunked_upload_stream =
1371 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1372 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
[email protected]c9e49a02013-02-26 05:56:471373
1374 request_.method = "POST";
rchcd379012017-04-12 21:53:321375 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121376 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071377 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201378 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]c9e49a02013-02-26 05:56:471379
xunjieli5fafe142016-03-23 23:32:541380 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271381 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541382 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021383 ASSERT_EQ(ERR_IO_PENDING,
1384 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]c9e49a02013-02-26 05:56:471385
rch97827ee2017-05-24 23:49:121386 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
robpercival214763f2016-07-01 23:27:011387 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]c9e49a02013-02-26 05:56:471388
1389 // Ack both packets in the request.
wangyix6444ffe2017-04-25 17:49:491390 ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
[email protected]c9e49a02013-02-26 05:56:471391
1392 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071393 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451394 size_t spdy_response_headers_frame_length;
1395 ProcessPacket(ConstructResponseHeadersPacket(
1396 2, !kFin, &spdy_response_headers_frame_length));
[email protected]c9e49a02013-02-26 05:56:471397
rchfb47f712017-05-21 03:24:001398 // The headers have already arrived.
1399 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]cadac622013-06-11 16:46:361400 ASSERT_TRUE(response_.headers.get());
[email protected]c9e49a02013-02-26 05:56:471401 EXPECT_EQ(200, response_.headers->response_code());
1402 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1403
1404 // Send the response body.
1405 const char kResponseBody[] = "Hello world!";
alyssar2adf3ac2016-05-03 17:12:581406 ProcessPacket(ConstructServerDataPacket(
1407 3, false, kFin, response_data_.length(), kResponseBody));
[email protected]c9e49a02013-02-26 05:56:471408
1409 // Since the body has already arrived, this should return immediately.
1410 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1411 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1412 callback_.callback()));
1413
1414 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1415 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101416
1417 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451418 // headers and payload.
1419 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
1420 strlen(kUploadData) * 2),
sclittle1edeeb22015-09-02 20:46:101421 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451422 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1423 strlen(kResponseBody)),
sclittle1edeeb22015-09-02 20:46:101424 stream_->GetTotalReceivedBytes());
[email protected]c9e49a02013-02-26 05:56:471425}
1426
[email protected]16ba7742014-08-22 00:57:251427TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithFinalEmptyDataPacket) {
1428 SetRequest("POST", "/", DEFAULT_PRIORITY);
1429 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:451430 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521431 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361432 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
Yixin Wange7ecc472018-03-06 19:00:251433 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
ckrasicbf2f59c2017-05-04 23:54:361434 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, !kFin,
Yixin Wange7ecc472018-03-06 19:00:251435 DEFAULT_PRIORITY, 0, &header_stream_offset,
1436 &spdy_request_headers_frame_length, {kUploadData}));
1437 AddWrite(ConstructClientDataPacket(3, kIncludeVersion, kFin, chunk_size, ""));
1438 AddWrite(ConstructClientAckPacket(4, 3, 1, 1));
[email protected]16ba7742014-08-22 00:57:251439 Initialize();
1440
Jeremy Roman0579ed62017-08-29 15:56:191441 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121442 auto* chunked_upload_stream =
1443 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1444 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
[email protected]16ba7742014-08-22 00:57:251445
1446 request_.method = "POST";
rchcd379012017-04-12 21:53:321447 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121448 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071449 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201450 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]16ba7742014-08-22 00:57:251451
xunjieli5fafe142016-03-23 23:32:541452 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271453 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541454 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021455 ASSERT_EQ(ERR_IO_PENDING,
1456 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251457
rch97827ee2017-05-24 23:49:121458 chunked_upload_stream->AppendData(nullptr, 0, true);
robpercival214763f2016-07-01 23:27:011459 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]16ba7742014-08-22 00:57:251460
wangyix6444ffe2017-04-25 17:49:491461 ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
[email protected]16ba7742014-08-22 00:57:251462
1463 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071464 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451465 size_t spdy_response_headers_frame_length;
1466 ProcessPacket(ConstructResponseHeadersPacket(
1467 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251468
rchfb47f712017-05-21 03:24:001469 // The headers have already arrived.
1470 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]16ba7742014-08-22 00:57:251471 ASSERT_TRUE(response_.headers.get());
1472 EXPECT_EQ(200, response_.headers->response_code());
1473 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1474
1475 // Send the response body.
1476 const char kResponseBody[] = "Hello world!";
alyssar2adf3ac2016-05-03 17:12:581477 ProcessPacket(ConstructServerDataPacket(
1478 3, false, kFin, response_data_.length(), kResponseBody));
[email protected]16ba7742014-08-22 00:57:251479
rchb27683c2015-07-29 23:53:501480 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251481 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1482 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1483 callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251484 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1485 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101486
1487 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451488 // headers and payload.
1489 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
1490 strlen(kUploadData)),
sclittle1edeeb22015-09-02 20:46:101491 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451492 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1493 strlen(kResponseBody)),
sclittle1edeeb22015-09-02 20:46:101494 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251495}
1496
1497TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithOneEmptyDataPacket) {
1498 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451499 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521500 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361501 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:371502 AddWrite(InnerConstructRequestHeadersPacket(
ckrasicbf2f59c2017-05-04 23:54:361503 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, !kFin,
1504 DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
1505 &header_stream_offset));
fayang3bcb8b502016-12-07 21:44:371506 AddWrite(ConstructClientDataPacket(3, kIncludeVersion, kFin, 0, ""));
wangyix6444ffe2017-04-25 17:49:491507 AddWrite(ConstructClientAckPacket(4, 3, 1, 1));
[email protected]16ba7742014-08-22 00:57:251508 Initialize();
1509
Jeremy Roman0579ed62017-08-29 15:56:191510 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121511 auto* chunked_upload_stream =
1512 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
[email protected]16ba7742014-08-22 00:57:251513
1514 request_.method = "POST";
rchcd379012017-04-12 21:53:321515 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121516 request_.upload_data_stream = upload_data_stream_.get();
mmenkecbc2b712014-10-09 20:29:071517 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201518 TestCompletionCallback().callback(), NetLogWithSource()));
[email protected]16ba7742014-08-22 00:57:251519
xunjieli5fafe142016-03-23 23:32:541520 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271521 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541522 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021523 ASSERT_EQ(ERR_IO_PENDING,
1524 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251525
rch97827ee2017-05-24 23:49:121526 chunked_upload_stream->AppendData(nullptr, 0, true);
robpercival214763f2016-07-01 23:27:011527 EXPECT_THAT(callback_.WaitForResult(), IsOk());
[email protected]16ba7742014-08-22 00:57:251528
wangyix6444ffe2017-04-25 17:49:491529 ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
[email protected]16ba7742014-08-22 00:57:251530
1531 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071532 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451533 size_t spdy_response_headers_frame_length;
1534 ProcessPacket(ConstructResponseHeadersPacket(
1535 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251536
rchfb47f712017-05-21 03:24:001537 // The headers have already arrived.
1538 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk());
[email protected]16ba7742014-08-22 00:57:251539 ASSERT_TRUE(response_.headers.get());
1540 EXPECT_EQ(200, response_.headers->response_code());
1541 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1542
1543 // Send the response body.
1544 const char kResponseBody[] = "Hello world!";
alyssar2adf3ac2016-05-03 17:12:581545 ProcessPacket(ConstructServerDataPacket(
1546 3, false, kFin, response_data_.length(), kResponseBody));
[email protected]16ba7742014-08-22 00:57:251547
rchb27683c2015-07-29 23:53:501548 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251549 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1550 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1551 callback_.callback()));
1552
1553 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1554 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101555
1556 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451557 // headers and payload.
1558 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1559 stream_->GetTotalSentBytes());
1560 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1561 strlen(kResponseBody)),
sclittle1edeeb22015-09-02 20:46:101562 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251563}
1564
[email protected]1e960032013-12-20 19:00:201565TEST_P(QuicHttpStreamTest, DestroyedEarly) {
1566 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451567 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521568 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361569 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:371570 AddWrite(InnerConstructRequestHeadersPacket(
ckrasicbf2f59c2017-05-04 23:54:361571 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, kFin,
1572 DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
1573 &header_stream_offset));
fayang3bcb8b502016-12-07 21:44:371574 AddWrite(ConstructAckAndRstStreamPacket(3));
[email protected]63534512012-12-23 18:49:001575 Initialize();
1576
1577 request_.method = "GET";
rchcd379012017-04-12 21:53:321578 request_.url = GURL("https://www.example.org/");
[email protected]63534512012-12-23 18:49:001579
xunjieli5fafe142016-03-23 23:32:541580 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271581 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541582 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021583 EXPECT_EQ(OK,
1584 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]63534512012-12-23 18:49:001585
1586 // Ack the request.
wangyix6444ffe2017-04-25 17:49:491587 ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
rchfb47f712017-05-21 03:24:001588 EXPECT_THAT(stream_->ReadResponseHeaders(
1589 base::Bind(&QuicHttpStreamTest::CloseStream,
1590 base::Unretained(this), stream_.get())),
robpercival214763f2016-07-01 23:27:011591 IsError(ERR_IO_PENDING));
[email protected]63534512012-12-23 18:49:001592
1593 // Send the response with a body.
[email protected]1e960032013-12-20 19:00:201594 SetResponse("404 OK", "hello world!");
[email protected]63534512012-12-23 18:49:001595 // In the course of processing this packet, the QuicHttpStream close itself.
rchfb47f712017-05-21 03:24:001596 size_t response_size = 0;
rch1bcfddf22017-06-03 00:26:291597 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin, &response_size));
[email protected]63534512012-12-23 18:49:001598
fdoray92e35a72016-06-10 15:54:551599 base::RunLoop().RunUntilIdle();
rchb27683c2015-07-29 23:53:501600
[email protected]63534512012-12-23 18:49:001601 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101602
1603 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451604 // headers and payload.
1605 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1606 stream_->GetTotalSentBytes());
rchfb47f712017-05-21 03:24:001607 // The stream was closed after receiving the headers.
1608 EXPECT_EQ(static_cast<int64_t>(response_size),
1609 stream_->GetTotalReceivedBytes());
[email protected]63534512012-12-23 18:49:001610}
1611
[email protected]1e960032013-12-20 19:00:201612TEST_P(QuicHttpStreamTest, Priority) {
1613 SetRequest("GET", "/", MEDIUM);
sclittlec4dc1a32015-09-24 00:15:451614 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521615 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361616 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:371617 AddWrite(InnerConstructRequestHeadersPacket(
ckrasicbf2f59c2017-05-04 23:54:361618 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, kFin, MEDIUM,
fayang3bcb8b502016-12-07 21:44:371619 &spdy_request_headers_frame_length, &header_stream_offset));
[email protected]24e5bc52013-09-18 15:36:581620 Initialize();
1621
1622 request_.method = "GET";
rchcd379012017-04-12 21:53:321623 request_.url = GURL("https://www.example.org/");
[email protected]24e5bc52013-09-18 15:36:581624
Steven Valdezb4ff0412018-01-18 22:39:271625 EXPECT_EQ(OK,
1626 stream_->InitializeStream(&request_, true, MEDIUM, net_log_.bound(),
1627 callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581628
rjshaded5ced072015-12-18 19:26:021629 EXPECT_EQ(OK,
1630 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581631
[email protected]24e5bc52013-09-18 15:36:581632 // Ack the request.
wangyix6444ffe2017-04-25 17:49:491633 ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
robpercival214763f2016-07-01 23:27:011634 EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()),
1635 IsError(ERR_IO_PENDING));
[email protected]24e5bc52013-09-18 15:36:581636
1637 // Send the response with a body.
[email protected]1e960032013-12-20 19:00:201638 SetResponse("404 OK", "hello world!");
rchfb47f712017-05-21 03:24:001639 size_t response_size = 0;
1640 ProcessPacket(ConstructResponseHeadersPacket(2, kFin, &response_size));
[email protected]24e5bc52013-09-18 15:36:581641
rchfb47f712017-05-21 03:24:001642 EXPECT_EQ(OK, callback_.WaitForResult());
rchb27683c2015-07-29 23:53:501643
[email protected]24e5bc52013-09-18 15:36:581644 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101645
1646 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451647 // headers and payload.
1648 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1649 stream_->GetTotalSentBytes());
rchfb47f712017-05-21 03:24:001650 EXPECT_EQ(static_cast<int64_t>(response_size),
1651 stream_->GetTotalReceivedBytes());
[email protected]24e5bc52013-09-18 15:36:581652}
1653
xunjieli8dff50b2016-07-22 14:19:061654TEST_P(QuicHttpStreamTest, SessionClosedDuringDoLoop) {
1655 SetRequest("POST", "/", DEFAULT_PRIORITY);
1656 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521657 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361658 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
Yixin Wange7ecc472018-03-06 19:00:251659 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
ckrasicbf2f59c2017-05-04 23:54:361660 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, !kFin,
Yixin Wange7ecc472018-03-06 19:00:251661 DEFAULT_PRIORITY, 0, &header_stream_offset,
1662 &spdy_request_headers_frame_length, {kUploadData}));
xunjieli8dff50b2016-07-22 14:19:061663 // Second data write will result in a synchronous failure which will close
1664 // the session.
1665 AddWrite(SYNCHRONOUS, ERR_FAILED);
1666 Initialize();
1667
Jeremy Roman0579ed62017-08-29 15:56:191668 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121669 auto* chunked_upload_stream =
1670 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
xunjieli8dff50b2016-07-22 14:19:061671
1672 request_.method = "POST";
rchcd379012017-04-12 21:53:321673 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121674 request_.upload_data_stream = upload_data_stream_.get();
xunjieli8dff50b2016-07-22 14:19:061675 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201676 TestCompletionCallback().callback(), NetLogWithSource()));
xunjieli8dff50b2016-07-22 14:19:061677
1678 size_t chunk_size = strlen(kUploadData);
rch97827ee2017-05-24 23:49:121679 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
xunjieli8dff50b2016-07-22 14:19:061680 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271681 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli8dff50b2016-07-22 14:19:061682 net_log_.bound(), callback_.callback()));
1683 QuicHttpStream* stream = stream_.get();
1684 DeleteStreamCallback delete_stream_callback(std::move(stream_));
1685 // SendRequest() completes asynchronously after the final chunk is added.
Yixin Wange7ecc472018-03-06 19:00:251686 // Error does not surface yet since packet write is triggered by a packet
1687 // flusher that tries to bundle request body writes.
xunjieli8dff50b2016-07-22 14:19:061688 ASSERT_EQ(ERR_IO_PENDING,
1689 stream->SendRequest(headers_, &response_, callback_.callback()));
rch97827ee2017-05-24 23:49:121690 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
xunjieli8dff50b2016-07-22 14:19:061691 int rv = callback_.WaitForResult();
Yixin Wange7ecc472018-03-06 19:00:251692 EXPECT_EQ(OK, rv);
1693 // Error will be surfaced once an attempt to read the response occurs.
1694 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1695 stream->ReadResponseHeaders(callback_.callback()));
xunjieli8dff50b2016-07-22 14:19:061696}
1697
rtenneti15656ae2016-01-23 03:05:031698TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersComplete) {
1699 SetRequest("POST", "/", DEFAULT_PRIORITY);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521700 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361701 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
rtenneti15656ae2016-01-23 03:05:031702 AddWrite(SYNCHRONOUS, ERR_FAILED);
1703 Initialize();
1704
Jeremy Roman0579ed62017-08-29 15:56:191705 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
Yixin Wange7ecc472018-03-06 19:00:251706 auto* chunked_upload_stream =
1707 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
rtenneti15656ae2016-01-23 03:05:031708
1709 request_.method = "POST";
rchcd379012017-04-12 21:53:321710 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121711 request_.upload_data_stream = upload_data_stream_.get();
rtenneti15656ae2016-01-23 03:05:031712 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201713 TestCompletionCallback().callback(), NetLogWithSource()));
rtenneti15656ae2016-01-23 03:05:031714
xunjieli5fafe142016-03-23 23:32:541715 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271716 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541717 net_log_.bound(), callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:251718 ASSERT_EQ(ERR_IO_PENDING,
rtenneti15656ae2016-01-23 03:05:031719 stream_->SendRequest(headers_, &response_, callback_.callback()));
mmenkeffff3642017-06-15 17:37:241720
Yixin Wange7ecc472018-03-06 19:00:251721 // Error will be surfaced once |upload_data_stream| triggers the next write.
1722 size_t chunk_size = strlen(kUploadData);
1723 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1724 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR, callback_.WaitForResult());
1725
1726 EXPECT_LE(0, stream_->GetTotalSentBytes());
1727 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1728}
1729
1730TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersCompleteReadResponse) {
1731 SetRequest("POST", "/", DEFAULT_PRIORITY);
Ryan Hamilton8d9ee76e2018-05-29 23:52:521732 quic::QuicStreamOffset header_stream_offset = 0;
Yixin Wange7ecc472018-03-06 19:00:251733 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
1734 AddWrite(SYNCHRONOUS, ERR_FAILED);
1735 Initialize();
1736
1737 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
1738 auto* chunked_upload_stream =
1739 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1740
1741 request_.method = "POST";
1742 request_.url = GURL("https://www.example.org/");
1743 request_.upload_data_stream = upload_data_stream_.get();
1744
1745 size_t chunk_size = strlen(kUploadData);
1746 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1747
1748 ASSERT_EQ(OK, request_.upload_data_stream->Init(
1749 TestCompletionCallback().callback(), NetLogWithSource()));
1750
1751 ASSERT_EQ(OK,
1752 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1753 net_log_.bound(), callback_.callback()));
1754 ASSERT_EQ(OK,
1755 stream_->SendRequest(headers_, &response_, callback_.callback()));
1756
1757 // Error will be surfaced once an attempt to read the response occurs.
1758 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1759 stream_->ReadResponseHeaders(callback_.callback()));
1760
mmenkeffff3642017-06-15 17:37:241761 EXPECT_LE(0, stream_->GetTotalSentBytes());
1762 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rtenneti15656ae2016-01-23 03:05:031763}
1764
1765TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBodyComplete) {
1766 SetRequest("POST", "/", DEFAULT_PRIORITY);
1767 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521768 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:361769 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:371770 AddWrite(InnerConstructRequestHeadersPacket(
ckrasicbf2f59c2017-05-04 23:54:361771 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, !kFin,
1772 DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
1773 &header_stream_offset));
rtenneti15656ae2016-01-23 03:05:031774 AddWrite(SYNCHRONOUS, ERR_FAILED);
1775 Initialize();
1776
Jeremy Roman0579ed62017-08-29 15:56:191777 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
rch97827ee2017-05-24 23:49:121778 auto* chunked_upload_stream =
1779 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
rtenneti15656ae2016-01-23 03:05:031780
1781 request_.method = "POST";
rchcd379012017-04-12 21:53:321782 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:121783 request_.upload_data_stream = upload_data_stream_.get();
rtenneti15656ae2016-01-23 03:05:031784 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:201785 TestCompletionCallback().callback(), NetLogWithSource()));
rtenneti15656ae2016-01-23 03:05:031786
xunjieli5fafe142016-03-23 23:32:541787 ASSERT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271788 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541789 net_log_.bound(), callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:251790 ASSERT_EQ(ERR_IO_PENDING,
rtenneti15656ae2016-01-23 03:05:031791 stream_->SendRequest(headers_, &response_, callback_.callback()));
Yixin Wange7ecc472018-03-06 19:00:251792
1793 size_t chunk_size = strlen(kUploadData);
1794 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1795 // Error does not surface yet since packet write is triggered by a packet
1796 // flusher that tries to bundle request body writes.
1797 ASSERT_EQ(OK, callback_.WaitForResult());
1798 // Error will be surfaced once an attempt to read the response occurs.
1799 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1800 stream_->ReadResponseHeaders(callback_.callback()));
1801
1802 EXPECT_LE(0, stream_->GetTotalSentBytes());
1803 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1804}
1805
1806TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBundledBodyComplete) {
1807 SetRequest("POST", "/", DEFAULT_PRIORITY);
1808 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:521809 quic::QuicStreamOffset header_stream_offset = 0;
Yixin Wange7ecc472018-03-06 19:00:251810 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
1811 AddWrite(ConstructRequestHeadersAndDataFramesPacket(
1812 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, !kFin,
1813 DEFAULT_PRIORITY, 0, &header_stream_offset,
1814 &spdy_request_headers_frame_length, {kUploadData}));
1815 AddWrite(SYNCHRONOUS, ERR_FAILED);
1816 Initialize();
1817
1818 upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
1819 auto* chunked_upload_stream =
1820 static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
1821
1822 request_.method = "POST";
1823 request_.url = GURL("https://www.example.org/");
1824 request_.upload_data_stream = upload_data_stream_.get();
1825
1826 size_t chunk_size = strlen(kUploadData);
1827 chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
1828
1829 ASSERT_EQ(OK, request_.upload_data_stream->Init(
1830 TestCompletionCallback().callback(), NetLogWithSource()));
1831
1832 ASSERT_EQ(OK,
1833 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
1834 net_log_.bound(), callback_.callback()));
1835 ASSERT_EQ(ERR_IO_PENDING,
1836 stream_->SendRequest(headers_, &response_, callback_.callback()));
1837
1838 chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
1839
1840 // Error does not surface yet since packet write is triggered by a packet
1841 // flusher that tries to bundle request body writes.
1842 ASSERT_EQ(OK, callback_.WaitForResult());
1843 // Error will be surfaced once an attempt to read the response occurs.
1844 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1845 stream_->ReadResponseHeaders(callback_.callback()));
1846
1847 EXPECT_LE(0, stream_->GetTotalSentBytes());
1848 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rtenneti15656ae2016-01-23 03:05:031849}
1850
ckrasic3865ee0f2016-02-29 22:04:561851TEST_P(QuicHttpStreamTest, ServerPushGetRequest) {
1852 SetRequest("GET", "/", DEFAULT_PRIORITY);
1853 Initialize();
1854
1855 // Initialize the first stream, for receiving the promise on.
1856 request_.method = "GET";
rchcd379012017-04-12 21:53:321857 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:561858
xunjieli5fafe142016-03-23 23:32:541859 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271860 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541861 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561862
1863 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
1864 // packet, but does it matter?
1865 ReceivePromise(promise_id_);
1866 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
1867
1868 request_.url = GURL(promise_url_);
1869
1870 // Make the second stream that will exercise the first step of the
1871 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:271872 EXPECT_EQ(OK, promised_stream_->InitializeStream(
1873 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
1874 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561875
1876 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:251877 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:561878 size_t spdy_response_headers_frame_length;
1879 ProcessPacket(InnerConstructResponseHeadersPacket(
1880 1, promise_id_, false, &spdy_response_headers_frame_length));
1881
1882 // Receive the promised response body.
1883 const char kResponseBody[] = "Hello world!";
alyssar2adf3ac2016-05-03 17:12:581884 ProcessPacket(InnerConstructDataPacket(2, promise_id_, false, kFin, 0,
1885 kResponseBody, &server_maker_));
ckrasic3865ee0f2016-02-29 22:04:561886
1887 // Now sending a matching request will have successful rendezvous
1888 // with the promised stream.
1889 EXPECT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
1890 callback_.callback()));
1891
1892 EXPECT_EQ(
1893 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
1894 ->id(),
1895 promise_id_);
1896
1897 // The headers will be immediately available.
robpercival214763f2016-07-01 23:27:011898 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
1899 IsOk());
ckrasic3865ee0f2016-02-29 22:04:561900
1901 // As will be the body.
1902 EXPECT_EQ(
1903 static_cast<int>(strlen(kResponseBody)),
1904 promised_stream_->ReadResponseBody(
1905 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
1906 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
1907 EXPECT_TRUE(AtEof());
1908
1909 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1910 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1911 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
1912 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1913 strlen(kResponseBody)),
1914 promised_stream_->GetTotalReceivedBytes());
1915}
1916
1917TEST_P(QuicHttpStreamTest, ServerPushGetRequestSlowResponse) {
1918 SetRequest("GET", "/", DEFAULT_PRIORITY);
1919 Initialize();
1920
1921 // Initialize the first stream, for receiving the promise on.
1922 request_.method = "GET";
rchcd379012017-04-12 21:53:321923 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:561924
xunjieli5fafe142016-03-23 23:32:541925 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:271926 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:541927 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561928
1929 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
1930 // packet, but does it matter?
1931 ReceivePromise(promise_id_);
1932 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
1933
1934 request_.url = GURL(promise_url_);
1935
1936 // Make the second stream that will exercise the first step of the
1937 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:271938 EXPECT_EQ(OK, promised_stream_->InitializeStream(
1939 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
1940 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561941
1942 // Now sending a matching request will rendezvous with the promised
1943 // stream, but pending secondary validation.
1944 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
1945 headers_, &response_, callback_.callback()));
1946
1947 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:251948 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:561949 size_t spdy_response_headers_frame_length;
1950 ProcessPacket(InnerConstructResponseHeadersPacket(
1951 1, promise_id_, false, &spdy_response_headers_frame_length));
1952
1953 // Receive the promised response body.
1954 const char kResponseBody[] = "Hello world!";
alyssar2adf3ac2016-05-03 17:12:581955 ProcessPacket(InnerConstructDataPacket(2, promise_id_, false, kFin, 0,
1956 kResponseBody, &server_maker_));
ckrasic3865ee0f2016-02-29 22:04:561957
fdoray92e35a72016-06-10 15:54:551958 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:561959
1960 // Rendezvous should have succeeded now, so the promised stream
1961 // should point at our push stream, and we should be able read
1962 // headers and data from it.
robpercival214763f2016-07-01 23:27:011963 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:561964
1965 EXPECT_EQ(
1966 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
1967 ->id(),
1968 promise_id_);
1969
robpercival214763f2016-07-01 23:27:011970 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
1971 IsOk());
ckrasic3865ee0f2016-02-29 22:04:561972
1973 EXPECT_EQ(
1974 static_cast<int>(strlen(kResponseBody)),
1975 promised_stream_->ReadResponseBody(
1976 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
1977
1978 // Callback should return
1979 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
1980 EXPECT_TRUE(AtEof());
1981
1982 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1983 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1984 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
1985 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1986 strlen(kResponseBody)),
1987 promised_stream_->GetTotalReceivedBytes());
1988}
1989
ckrasic2c63f9b2016-08-16 23:54:071990// Verify fix for crbug.com/637349
1991TEST_P(QuicHttpStreamTest, ServerPushCancelHttpStreamBeforeResponse) {
1992 SetRequest("GET", "/", DEFAULT_PRIORITY);
1993 Initialize();
1994
1995 // Initialize the first stream, for receiving the promise on.
1996 request_.method = "GET";
rchcd379012017-04-12 21:53:321997 request_.url = GURL("https://www.example.org/");
ckrasic2c63f9b2016-08-16 23:54:071998
1999 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272000 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
ckrasic2c63f9b2016-08-16 23:54:072001 net_log_.bound(), callback_.callback()));
2002
2003 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2004 // packet, but does it matter?
2005 ReceivePromise(promise_id_);
2006 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2007
2008 request_.url = GURL(promise_url_);
2009
2010 // Make the second stream that will exercise the first step of the
2011 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272012 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2013 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2014 callback_.callback()));
ckrasic2c63f9b2016-08-16 23:54:072015
2016 // Now sending a matching request will rendezvous with the promised
2017 // stream, but pending secondary validation.
2018 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2019 headers_, &response_, callback_.callback()));
2020
2021 base::RunLoop().RunUntilIdle();
2022
2023 // Cause of FinalValidation() crash as per bug.
2024 promised_stream_.reset();
2025
2026 // Receive the promised response headers.
2027 response_headers_ = promised_response_.Clone();
2028 size_t spdy_response_headers_frame_length;
2029 ProcessPacket(InnerConstructResponseHeadersPacket(
2030 1, promise_id_, false, &spdy_response_headers_frame_length));
2031}
2032
ckrasic3865ee0f2016-02-29 22:04:562033TEST_P(QuicHttpStreamTest, ServerPushCrossOriginOK) {
2034 SetRequest("GET", "/", DEFAULT_PRIORITY);
2035 Initialize();
2036
2037 // Initialize the first stream, for receiving the promise on.
2038 request_.method = "GET";
rchcd379012017-04-12 21:53:322039 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562040
xunjieli5fafe142016-03-23 23:32:542041 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272042 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542043 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562044
2045 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2046 // packet, but does it matter?
2047
2048 push_promise_[":authority"] = "mail.example.org";
Ryan Hamilton8d9ee76e2018-05-29 23:52:522049 promise_url_ = quic::SpdyUtils::GetPromisedUrlFromHeaders(push_promise_);
ckrasic3865ee0f2016-02-29 22:04:562050
2051 ReceivePromise(promise_id_);
2052 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2053
2054 request_.url = GURL(promise_url_);
2055
2056 // Make the second stream that will exercise the first step of the
2057 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272058 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2059 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2060 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562061
2062 // Receive the promised response headers.
bnc94893a72016-06-30 13:45:252063 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562064 size_t spdy_response_headers_frame_length;
2065 ProcessPacket(InnerConstructResponseHeadersPacket(
2066 1, promise_id_, false, &spdy_response_headers_frame_length));
2067
2068 // Receive the promised response body.
2069 const char kResponseBody[] = "Hello world!";
alyssar2adf3ac2016-05-03 17:12:582070 ProcessPacket(InnerConstructDataPacket(2, promise_id_, false, kFin, 0,
2071 kResponseBody, &server_maker_));
ckrasic3865ee0f2016-02-29 22:04:562072
2073 // Now sending a matching request will have successful rendezvous
2074 // with the promised stream.
2075 EXPECT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
2076 callback_.callback()));
2077
2078 EXPECT_EQ(
2079 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2080 ->id(),
2081 promise_id_);
2082
2083 // The headers will be immediately available.
robpercival214763f2016-07-01 23:27:012084 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2085 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562086
2087 // As will be the body.
2088 EXPECT_EQ(
2089 static_cast<int>(strlen(kResponseBody)),
2090 promised_stream_->ReadResponseBody(
2091 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2092 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2093 EXPECT_TRUE(AtEof());
2094
2095 EXPECT_EQ(0, stream_->GetTotalSentBytes());
2096 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2097 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2098 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
2099 strlen(kResponseBody)),
2100 promised_stream_->GetTotalReceivedBytes());
2101}
2102
2103TEST_P(QuicHttpStreamTest, ServerPushCrossOriginFail) {
2104 SetRequest("GET", "/", DEFAULT_PRIORITY);
2105 Initialize();
2106
2107 // Initialize the first stream, for receiving the promise on.
2108 request_.method = "GET";
rchcd379012017-04-12 21:53:322109 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562110
xunjieli5fafe142016-03-23 23:32:542111 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272112 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542113 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562114
2115 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2116 // packet, but does it matter?
2117 push_promise_[":authority"] = "www.notexample.org";
Ryan Hamilton8d9ee76e2018-05-29 23:52:522118 promise_url_ = quic::SpdyUtils::GetPromisedUrlFromHeaders(push_promise_);
ckrasic3865ee0f2016-02-29 22:04:562119
2120 ReceivePromise(promise_id_);
2121 // The promise will have been rejected because the cert doesn't
2122 // match.
2123 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
2124}
2125
2126TEST_P(QuicHttpStreamTest, ServerPushVaryCheckOK) {
2127 SetRequest("GET", "/", DEFAULT_PRIORITY);
2128 Initialize();
2129
2130 // Initialize the first stream, for receiving the promise on.
2131 request_.method = "GET";
rchcd379012017-04-12 21:53:322132 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562133
xunjieli5fafe142016-03-23 23:32:542134 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272135 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542136 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562137
2138 push_promise_["accept-encoding"] = "gzip";
ckrasic3865ee0f2016-02-29 22:04:562139
2140 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2141 // packet, but does it matter?
2142 ReceivePromise(promise_id_);
2143 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2144
2145 request_.url = GURL(promise_url_);
2146
2147 // Make the second stream that will exercise the first step of the
2148 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272149 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2150 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2151 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562152
2153 headers_.SetHeader("accept-encoding", "gzip");
2154
2155 // Now sending a matching request will rendezvous with the promised
2156 // stream, but pending secondary validation.
2157 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2158 headers_, &response_, callback_.callback()));
2159
2160 // Receive the promised response headers.
2161 promised_response_["vary"] = "accept-encoding";
bnc94893a72016-06-30 13:45:252162 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562163 size_t spdy_response_headers_frame_length;
2164 ProcessPacket(InnerConstructResponseHeadersPacket(
2165 1, promise_id_, false, &spdy_response_headers_frame_length));
2166
2167 // Receive the promised response body.
2168 const char kResponseBody[] = "Hello world!";
alyssar2adf3ac2016-05-03 17:12:582169 ProcessPacket(InnerConstructDataPacket(2, promise_id_, false, kFin, 0,
2170 kResponseBody, &server_maker_));
ckrasic3865ee0f2016-02-29 22:04:562171
fdoray92e35a72016-06-10 15:54:552172 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562173
2174 // Rendezvous should have succeeded now, so the promised stream
2175 // should point at our push stream, and we should be able read
2176 // headers and data from it.
robpercival214763f2016-07-01 23:27:012177 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562178
2179 EXPECT_EQ(
2180 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2181 ->id(),
2182 promise_id_);
2183
robpercival214763f2016-07-01 23:27:012184 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2185 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562186
2187 EXPECT_EQ(
2188 static_cast<int>(strlen(kResponseBody)),
2189 promised_stream_->ReadResponseBody(
2190 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2191
2192 // Callback should return
2193 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2194 EXPECT_TRUE(AtEof());
2195
2196 EXPECT_EQ(0, stream_->GetTotalSentBytes());
2197 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2198 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
2199 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
2200 strlen(kResponseBody)),
2201 promised_stream_->GetTotalReceivedBytes());
2202}
2203
2204TEST_P(QuicHttpStreamTest, ServerPushVaryCheckFail) {
2205 SetRequest("GET", "/", DEFAULT_PRIORITY);
2206 request_headers_[":scheme"] = "https";
2207 request_headers_[":path"] = "/bar";
2208 request_headers_["accept-encoding"] = "sdch";
2209
2210 size_t spdy_request_header_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:522211 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:362212 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
Yixin Wangb470bc882018-02-15 18:43:572213
Ryan Hamilton8d9ee76e2018-05-29 23:52:522214 quic::QuicPacketNumber client_packet_number = 2;
Yixin Wangb470bc882018-02-15 18:43:572215 if (client_headers_include_h2_stream_dependency_ &&
Ryan Hamilton8d9ee76e2018-05-29 23:52:522216 version_ > quic::QUIC_VERSION_42) {
Yixin Wangb470bc882018-02-15 18:43:572217 AddWrite(ConstructClientPriorityPacket(
2218 client_packet_number++, kIncludeVersion, promise_id_, 0,
2219 DEFAULT_PRIORITY, &header_stream_offset));
2220 }
Michael Warresabba8b7d2018-07-20 22:50:272221 AddWrite(ConstructClientRstStreamVaryMismatchAndRequestHeadersPacket(
2222 client_packet_number++, stream_id_ + 2, !kIncludeVersion, kFin,
2223 DEFAULT_PRIORITY, promise_id_, &spdy_request_header_frame_length,
2224 &header_stream_offset));
Yixin Wangb470bc882018-02-15 18:43:572225 AddWrite(ConstructClientAckPacket(client_packet_number++, 3, 1, 1));
2226 AddWrite(ConstructClientRstStreamCancelledPacket(client_packet_number++));
2227
ckrasic3865ee0f2016-02-29 22:04:562228 Initialize();
2229
2230 // Initialize the first stream, for receiving the promise on.
2231 request_.method = "GET";
rchcd379012017-04-12 21:53:322232 request_.url = GURL("https://www.example.org/");
ckrasic3865ee0f2016-02-29 22:04:562233
xunjieli5fafe142016-03-23 23:32:542234 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272235 stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
xunjieli5fafe142016-03-23 23:32:542236 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562237
2238 push_promise_["accept-encoding"] = "gzip";
ckrasic3865ee0f2016-02-29 22:04:562239
2240 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
2241 // packet, but does it matter?
2242 ReceivePromise(promise_id_);
2243 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
2244
2245 request_.url = GURL(promise_url_);
2246
2247 // Make the second stream that will exercise the first step of the
2248 // server push rendezvous mechanism.
Steven Valdezb4ff0412018-01-18 22:39:272249 EXPECT_EQ(OK, promised_stream_->InitializeStream(
2250 &request_, true, DEFAULT_PRIORITY, net_log_.bound(),
2251 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:562252
2253 headers_.SetHeader("accept-encoding", "sdch");
2254
2255 // Now sending a matching request will rendezvous with the promised
2256 // stream, but pending secondary validation.
2257 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
2258 headers_, &response_, callback_.callback()));
2259
2260 // Receive the promised response headers.
2261 promised_response_["vary"] = "accept-encoding";
bnc94893a72016-06-30 13:45:252262 response_headers_ = promised_response_.Clone();
ckrasic3865ee0f2016-02-29 22:04:562263 size_t spdy_response_headers_frame_length;
2264 ProcessPacket(InnerConstructResponseHeadersPacket(
2265 1, promise_id_, false, &spdy_response_headers_frame_length));
2266
fdoray92e35a72016-06-10 15:54:552267 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562268
2269 // Rendezvous should have failed due to vary mismatch, so the
2270 // promised stream should have been aborted, and instead we have a
2271 // new, regular client initiated stream.
robpercival214763f2016-07-01 23:27:012272 EXPECT_THAT(callback_.WaitForResult(), IsOk());
ckrasic3865ee0f2016-02-29 22:04:562273
2274 // Not a server-initiated stream.
2275 EXPECT_NE(
2276 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2277 ->id(),
2278 promise_id_);
2279
2280 // Instead, a new client-initiated stream.
2281 EXPECT_EQ(
2282 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
2283 ->id(),
2284 stream_id_ + 2);
2285
2286 // After rendezvous failure, the push stream has been cancelled.
2287 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
2288
2289 // The rest of the test verifies that the retried as
2290 // client-initiated version of |promised_stream_| works as intended.
2291
2292 // Ack the request.
wangyix6444ffe2017-04-25 17:49:492293 ProcessPacket(ConstructServerAckPacket(2, 0, 0, 0));
ckrasic3865ee0f2016-02-29 22:04:562294
bnc614a92d32016-04-04 13:56:072295 SetResponse("404 Not Found", string());
ckrasic3865ee0f2016-02-29 22:04:562296 size_t spdy_response_header_frame_length;
2297 ProcessPacket(InnerConstructResponseHeadersPacket(
2298 3, stream_id_ + 2, kFin, &spdy_response_header_frame_length));
2299
fdoray92e35a72016-06-10 15:54:552300 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:562301
robpercival214763f2016-07-01 23:27:012302 EXPECT_THAT(promised_stream_->ReadResponseHeaders(callback_.callback()),
2303 IsOk());
ckrasic3865ee0f2016-02-29 22:04:562304 ASSERT_TRUE(response_.headers.get());
2305 EXPECT_EQ(404, response_.headers->response_code());
2306 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
2307 EXPECT_FALSE(response_.response_time.is_null());
2308 EXPECT_FALSE(response_.request_time.is_null());
2309
2310 // There is no body, so this should return immediately.
2311 EXPECT_EQ(
2312 0, promised_stream_->ReadResponseBody(
2313 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
2314 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
2315
2316 stream_->Close(true);
2317
2318 EXPECT_TRUE(AtEof());
2319
2320 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
2321 // headers and payload.
2322 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
2323 promised_stream_->GetTotalSentBytes());
2324 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length),
2325 promised_stream_->GetTotalReceivedBytes());
2326}
2327
maksim.sisov84e20c92016-06-23 08:49:342328TEST_P(QuicHttpStreamTest, DataReadErrorSynchronous) {
2329 SetRequest("POST", "/", DEFAULT_PRIORITY);
2330 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:522331 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:362332 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
Yixin Wange7ecc472018-03-06 19:00:252333 AddWrite(ConstructRequestAndRstPacket(
ckrasicbf2f59c2017-05-04 23:54:362334 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, !kFin,
Yixin Wange7ecc472018-03-06 19:00:252335 DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
Ryan Hamilton8d9ee76e2018-05-29 23:52:522336 &header_stream_offset, quic::QUIC_ERROR_PROCESSING_STREAM, 0));
maksim.sisov84e20c92016-06-23 08:49:342337
2338 Initialize();
2339
Jeremy Roman0579ed62017-08-29 15:56:192340 upload_data_stream_ = std::make_unique<ReadErrorUploadDataStream>(
maksim.sisov84e20c92016-06-23 08:49:342341 ReadErrorUploadDataStream::FailureMode::SYNC);
2342 request_.method = "POST";
rchcd379012017-04-12 21:53:322343 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122344 request_.upload_data_stream = upload_data_stream_.get();
maksim.sisov84e20c92016-06-23 08:49:342345 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202346 TestCompletionCallback().callback(), NetLogWithSource()));
maksim.sisov84e20c92016-06-23 08:49:342347
2348 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272349 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
maksim.sisov84e20c92016-06-23 08:49:342350 net_log_.bound(), callback_.callback()));
2351
2352 int result = stream_->SendRequest(headers_, &response_, callback_.callback());
robpercival214763f2016-07-01 23:27:012353 EXPECT_THAT(result, IsError(ERR_FAILED));
maksim.sisov84e20c92016-06-23 08:49:342354
2355 EXPECT_TRUE(AtEof());
2356
2357 // QuicHttpStream::GetTotalSent/ReceivedBytes includes only headers.
2358 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
2359 stream_->GetTotalSentBytes());
2360 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2361}
2362
2363TEST_P(QuicHttpStreamTest, DataReadErrorAsynchronous) {
2364 SetRequest("POST", "/", DEFAULT_PRIORITY);
2365 size_t spdy_request_headers_frame_length;
Ryan Hamilton8d9ee76e2018-05-29 23:52:522366 quic::QuicStreamOffset header_stream_offset = 0;
rch5cb522462017-04-25 20:18:362367 AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
fayang3bcb8b502016-12-07 21:44:372368 AddWrite(InnerConstructRequestHeadersPacket(
ckrasicbf2f59c2017-05-04 23:54:362369 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, !kFin,
2370 DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
2371 &header_stream_offset));
fayang3bcb8b502016-12-07 21:44:372372 AddWrite(ConstructClientRstStreamErrorPacket(3, !kIncludeVersion));
maksim.sisov84e20c92016-06-23 08:49:342373
2374 Initialize();
2375
Jeremy Roman0579ed62017-08-29 15:56:192376 upload_data_stream_ = std::make_unique<ReadErrorUploadDataStream>(
maksim.sisov84e20c92016-06-23 08:49:342377 ReadErrorUploadDataStream::FailureMode::ASYNC);
2378 request_.method = "POST";
rchcd379012017-04-12 21:53:322379 request_.url = GURL("https://www.example.org/");
rch97827ee2017-05-24 23:49:122380 request_.upload_data_stream = upload_data_stream_.get();
maksim.sisov84e20c92016-06-23 08:49:342381 ASSERT_EQ(OK, request_.upload_data_stream->Init(
tfarina42834112016-09-22 13:38:202382 TestCompletionCallback().callback(), NetLogWithSource()));
maksim.sisov84e20c92016-06-23 08:49:342383
2384 EXPECT_EQ(OK,
Steven Valdezb4ff0412018-01-18 22:39:272385 stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
maksim.sisov84e20c92016-06-23 08:49:342386 net_log_.bound(), callback_.callback()));
2387
2388 int result = stream_->SendRequest(headers_, &response_, callback_.callback());
2389
wangyix6444ffe2017-04-25 17:49:492390 ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
maksim.sisov84e20c92016-06-23 08:49:342391 SetResponse("200 OK", string());
2392
robpercival214763f2016-07-01 23:27:012393 EXPECT_THAT(result, IsError(ERR_IO_PENDING));
2394 EXPECT_THAT(callback_.GetResult(result), IsError(ERR_FAILED));
maksim.sisov84e20c92016-06-23 08:49:342395
2396 EXPECT_TRUE(AtEof());
2397
2398 // QuicHttpStream::GetTotalSent/ReceivedBytes includes only headers.
2399 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
2400 stream_->GetTotalSentBytes());
2401 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
2402}
2403
[email protected]f702d572012-12-04 15:56:202404} // namespace test
[email protected]f702d572012-12-04 15:56:202405} // namespace net