blob: 59ce8b7865351c72afe0889a5c27bc83124b0168 [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
5#include "net/quic/quic_http_stream.h"
6
sclittle1edeeb22015-09-02 20:46:107#include <stdint.h>
8
danakjad1777e2016-04-16 00:56:429#include <memory>
[email protected]f702d572012-12-04 15:56:2010
danakjad1777e2016-04-16 00:56:4211#include "base/memory/ptr_util.h"
fdoray92e35a72016-06-10 15:54:5512#include "base/run_loop.h"
xunjieli188bd402016-03-12 00:17:2513#include "base/strings/string_number_conversions.h"
gabf767595f2016-05-11 18:50:3514#include "base/threading/thread_task_runner_handle.h"
mmenkecbc2b712014-10-09 20:29:0715#include "net/base/chunked_upload_data_stream.h"
16#include "net/base/elements_upload_data_stream.h"
[email protected]f702d572012-12-04 15:56:2017#include "net/base/net_errors.h"
18#include "net/base/test_completion_callback.h"
[email protected]b2d26cfd2012-12-11 10:36:0619#include "net/base/upload_bytes_element_reader.h"
[email protected]f702d572012-12-04 15:56:2020#include "net/http/http_response_headers.h"
[email protected]5db452202014-08-19 05:22:1521#include "net/http/transport_security_state.h"
xunjieli5fafe142016-03-23 23:32:5422#include "net/log/test_net_log.h"
23#include "net/log/test_net_log_util.h"
[email protected]fee17f72013-02-03 07:47:4124#include "net/quic/congestion_control/send_algorithm_interface.h"
[email protected]e8ff26842013-03-22 21:02:0525#include "net/quic/crypto/crypto_protocol.h"
rch03b7a202016-02-05 00:54:2026#include "net/quic/crypto/proof_verifier_chromium.h"
[email protected]4df69842013-02-27 06:32:1627#include "net/quic/crypto/quic_decrypter.h"
28#include "net/quic/crypto/quic_encrypter.h"
[email protected]17bf15c2014-03-14 10:08:0429#include "net/quic/crypto/quic_server_info.h"
rch16c74d1d2016-04-22 06:14:0730#include "net/quic/quic_chromium_alarm_factory.h"
rch12fef552016-01-15 16:26:3131#include "net/quic/quic_chromium_connection_helper.h"
rcha02807b42016-01-29 21:56:1532#include "net/quic/quic_chromium_packet_reader.h"
33#include "net/quic/quic_chromium_packet_writer.h"
[email protected]f702d572012-12-04 15:56:2034#include "net/quic/quic_connection.h"
[email protected]24e5bc52013-09-18 15:36:5835#include "net/quic/quic_http_utils.h"
[email protected]9f0dcd4e2014-01-16 15:58:1436#include "net/quic/quic_write_blocked_list.h"
[email protected]3e7dca62013-09-10 16:14:2337#include "net/quic/spdy_utils.h"
rch1fe2eeb2015-10-26 14:45:5738#include "net/quic/test_tools/crypto_test_utils.h"
[email protected]f702d572012-12-04 15:56:2039#include "net/quic/test_tools/mock_clock.h"
[email protected]e8ff26842013-03-22 21:02:0540#include "net/quic/test_tools/mock_crypto_client_stream_factory.h"
[email protected]9db443912013-02-25 05:27:0341#include "net/quic/test_tools/mock_random.h"
[email protected]b1f287d2012-12-22 17:25:3942#include "net/quic/test_tools/quic_connection_peer.h"
[email protected]1e960032013-12-20 19:00:2043#include "net/quic/test_tools/quic_test_packet_maker.h"
[email protected]f702d572012-12-04 15:56:2044#include "net/quic/test_tools/quic_test_utils.h"
45#include "net/quic/test_tools/test_task_runner.h"
tbansalca83c002016-04-28 20:56:2846#include "net/socket/socket_performance_watcher.h"
[email protected]f702d572012-12-04 15:56:2047#include "net/socket/socket_test_util.h"
[email protected]6cca996b2013-01-25 07:43:3648#include "net/spdy/spdy_frame_builder.h"
49#include "net/spdy/spdy_framer.h"
50#include "net/spdy/spdy_http_utils.h"
51#include "net/spdy/spdy_protocol.h"
rch03b7a202016-02-05 00:54:2052#include "net/test/cert_test_util.h"
rsleevia69c79a2016-06-22 03:28:4353#include "net/test/test_data_directory.h"
[email protected]f702d572012-12-04 15:56:2054#include "testing/gmock/include/gmock/gmock.h"
55#include "testing/gtest/include/gtest/gtest.h"
56
bnc614a92d32016-04-04 13:56:0757using std::string;
[email protected]f702d572012-12-04 15:56:2058using testing::_;
[email protected]06ff5152013-08-29 01:03:0559using testing::AnyNumber;
60using testing::Return;
[email protected]f702d572012-12-04 15:56:2061
62namespace net {
[email protected]f702d572012-12-04 15:56:2063namespace test {
[email protected]f702d572012-12-04 15:56:2064namespace {
65
[email protected]16ba7742014-08-22 00:57:2566const char kUploadData[] = "Really nifty data!";
rch9ae5b3b2016-02-11 00:36:2967const char kDefaultServerHostName[] = "www.example.org";
Avi Drissman13fc8932015-12-20 04:40:4668const uint16_t kDefaultServerPort = 80;
[email protected]f702d572012-12-04 15:56:2069
70class TestQuicConnection : public QuicConnection {
71 public:
[email protected]1e960032013-12-20 19:00:2072 TestQuicConnection(const QuicVersionVector& versions,
[email protected]3aa9ca72014-02-27 19:39:4373 QuicConnectionId connection_id,
[email protected]f702d572012-12-04 15:56:2074 IPEndPoint address,
rch12fef552016-01-15 16:26:3175 QuicChromiumConnectionHelper* helper,
rch16c74d1d2016-04-22 06:14:0776 QuicChromiumAlarmFactory* alarm_factory,
jdorfman90d185f32016-01-15 13:22:4777 QuicPacketWriter* writer)
[email protected]66cd2d62014-08-01 18:42:3978 : QuicConnection(connection_id,
79 address,
80 helper,
rch16c74d1d2016-04-22 06:14:0781 alarm_factory,
jdorfman90d185f32016-01-15 13:22:4782 writer,
rtenneti6f48aa92015-03-16 02:18:4883 true /* owns_writer */,
84 Perspective::IS_CLIENT,
rtenneti6f48aa92015-03-16 02:18:4885 versions) {}
[email protected]f702d572012-12-04 15:56:2086
[email protected]fee17f72013-02-03 07:47:4187 void SetSendAlgorithm(SendAlgorithmInterface* send_algorithm) {
88 QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
[email protected]f702d572012-12-04 15:56:2089 }
90};
91
[email protected]63534512012-12-23 18:49:0092// Subclass of QuicHttpStream that closes itself when the first piece of data
93// is received.
94class AutoClosingStream : public QuicHttpStream {
95 public:
ckrasic4f9d88d2015-07-22 22:23:1696 explicit AutoClosingStream(
97 const base::WeakPtr<QuicChromiumClientSession>& session)
98 : QuicHttpStream(session) {}
[email protected]63534512012-12-23 18:49:0099
sclittlec4dc1a32015-09-24 00:15:45100 void OnHeadersAvailable(const SpdyHeaderBlock& headers,
101 size_t frame_len) override {
[email protected]63534512012-12-23 18:49:00102 Close(false);
[email protected]63534512012-12-23 18:49:00103 }
rchb27683c2015-07-29 23:53:50104
105 void OnDataAvailable() override { Close(false); }
[email protected]63534512012-12-23 18:49:00106};
107
[email protected]f702d572012-12-04 15:56:20108} // namespace
109
[email protected]24e5bc52013-09-18 15:36:58110class QuicHttpStreamPeer {
111 public:
rch12fef552016-01-15 16:26:31112 static QuicChromiumClientStream* GetQuicChromiumClientStream(
[email protected]24e5bc52013-09-18 15:36:58113 QuicHttpStream* stream) {
114 return stream->stream_;
115 }
zhongyica364fbb2015-12-12 03:39:12116
117 static bool WasHandshakeConfirmed(QuicHttpStream* stream) {
118 return stream->was_handshake_confirmed_;
119 }
120
121 static void SetHandshakeConfirmed(QuicHttpStream* stream, bool confirmed) {
122 stream->was_handshake_confirmed_ = confirmed;
123 }
[email protected]24e5bc52013-09-18 15:36:58124};
125
[email protected]1e960032013-12-20 19:00:20126class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
[email protected]f702d572012-12-04 15:56:20127 protected:
[email protected]1e960032013-12-20 19:00:20128 static const bool kFin = true;
129 static const bool kIncludeVersion = true;
130 static const bool kIncludeCongestionFeedback = true;
131
[email protected]f702d572012-12-04 15:56:20132 // Holds a packet to be written to the wire, and the IO mode that should
133 // be used by the mock socket when performing the write.
134 struct PacketToWrite {
jokulikf2bd55c52016-03-24 22:35:30135 PacketToWrite(IoMode mode, QuicReceivedPacket* packet)
rjshaded5ced072015-12-18 19:26:02136 : mode(mode), packet(packet) {}
rtenneti15656ae2016-01-23 03:05:03137 PacketToWrite(IoMode mode, int rv) : mode(mode), packet(nullptr), rv(rv) {}
[email protected]f702d572012-12-04 15:56:20138 IoMode mode;
jokulikf2bd55c52016-03-24 22:35:30139 QuicReceivedPacket* packet;
rtenneti15656ae2016-01-23 03:05:03140 int rv;
[email protected]f702d572012-12-04 15:56:20141 };
142
143 QuicHttpStreamTest()
xunjieli5fafe142016-03-23 23:32:54144 : use_closing_stream_(false),
rch1fe2eeb2015-10-26 14:45:57145 crypto_config_(CryptoTestUtils::ProofVerifierForTesting()),
[email protected]f702d572012-12-04 15:56:20146 read_buffer_(new IOBufferWithSize(4096)),
ckrasic3865ee0f2016-02-29 22:04:56147 promise_id_(kServerDataStreamId1),
[email protected]66ae5962014-05-22 11:13:05148 stream_id_(kClientDataStreamId1),
ckrasic3865ee0f2016-02-29 22:04:56149 connection_id_(2),
alyssar2adf3ac2016-05-03 17:12:58150 client_maker_(GetParam(),
151 connection_id_,
152 &clock_,
153 kDefaultServerHostName,
154 Perspective::IS_CLIENT),
155 server_maker_(GetParam(),
156 connection_id_,
157 &clock_,
158 kDefaultServerHostName,
159 Perspective::IS_SERVER),
ckrasic3865ee0f2016-02-29 22:04:56160 random_generator_(0),
161 response_offset_(0) {
martijn21968ea2016-02-24 18:46:20162 IPAddress ip(192, 0, 2, 33);
[email protected]f702d572012-12-04 15:56:20163 peer_addr_ = IPEndPoint(ip, 443);
164 self_addr_ = IPEndPoint(ip, 8435);
rtenneti4b06ae72014-08-26 03:43:43165 clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(20));
[email protected]f702d572012-12-04 15:56:20166 }
167
168 ~QuicHttpStreamTest() {
rtenneti85dcfac22015-03-27 20:22:19169 session_->CloseSessionOnError(ERR_ABORTED, QUIC_INTERNAL_ERROR);
[email protected]f702d572012-12-04 15:56:20170 for (size_t i = 0; i < writes_.size(); i++) {
171 delete writes_[i].packet;
172 }
173 }
174
175 // Adds a packet to the list of expected writes.
danakjad1777e2016-04-16 00:56:42176 void AddWrite(std::unique_ptr<QuicReceivedPacket> packet) {
[email protected]1e960032013-12-20 19:00:20177 writes_.push_back(PacketToWrite(SYNCHRONOUS, packet.release()));
[email protected]f702d572012-12-04 15:56:20178 }
179
rtenneti15656ae2016-01-23 03:05:03180 void AddWrite(IoMode mode, int rv) {
181 writes_.push_back(PacketToWrite(mode, rv));
182 }
183
[email protected]f702d572012-12-04 15:56:20184 // Returns the packet to be written at position |pos|.
jokulikf2bd55c52016-03-24 22:35:30185 QuicReceivedPacket* GetWrite(size_t pos) { return writes_[pos].packet; }
[email protected]f702d572012-12-04 15:56:20186
187 bool AtEof() {
rch37de576c2015-05-17 20:28:17188 return socket_data_->AllReadDataConsumed() &&
189 socket_data_->AllWriteDataConsumed();
[email protected]f702d572012-12-04 15:56:20190 }
191
danakjad1777e2016-04-16 00:56:42192 void ProcessPacket(std::unique_ptr<QuicReceivedPacket> packet) {
[email protected]1e960032013-12-20 19:00:20193 connection_->ProcessUdpPacket(self_addr_, peer_addr_, *packet);
[email protected]f702d572012-12-04 15:56:20194 }
195
196 // Configures the test fixture to use the list of expected writes.
197 void Initialize() {
198 mock_writes_.reset(new MockWrite[writes_.size()]);
199 for (size_t i = 0; i < writes_.size(); i++) {
rtenneti15656ae2016-01-23 03:05:03200 if (writes_[i].packet == nullptr) {
201 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].rv, i);
202 } else {
203 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].packet->data(),
204 writes_[i].packet->length());
205 }
bnc614a92d32016-04-04 13:56:07206 }
[email protected]f702d572012-12-04 15:56:20207
rtennetibe635732014-10-02 22:51:42208 socket_data_.reset(new StaticSocketDataProvider(
209 nullptr, 0, mock_writes_.get(), writes_.size()));
[email protected]f702d572012-12-04 15:56:20210
danakjad1777e2016-04-16 00:56:42211 std::unique_ptr<MockUDPClientSocket> socket(new MockUDPClientSocket(
xunjielib53b38c2016-03-24 15:54:36212 socket_data_.get(), net_log_.bound().net_log()));
[email protected]e13201d82012-12-12 05:00:32213 socket->Connect(peer_addr_);
[email protected]f702d572012-12-04 15:56:20214 runner_ = new TestTaskRunner(&clock_);
[email protected]fee17f72013-02-03 07:47:41215 send_algorithm_ = new MockSendAlgorithm();
rch7dd15702015-07-01 18:57:57216 EXPECT_CALL(*send_algorithm_, InRecovery()).WillRepeatedly(Return(false));
217 EXPECT_CALL(*send_algorithm_, InSlowStart()).WillRepeatedly(Return(false));
rjshaded5ced072015-12-18 19:26:02218 EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
219 .WillRepeatedly(Return(true));
rtenneti44f4a2e2015-08-07 14:00:07220 EXPECT_CALL(*send_algorithm_, RetransmissionDelay())
221 .WillRepeatedly(Return(QuicTime::Delta::Zero()));
222 EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
223 .WillRepeatedly(Return(kMaxPacketSize));
jokulik0e0a00c32016-06-13 21:51:58224 EXPECT_CALL(*send_algorithm_, PacingRate(_))
rtenneti44f4a2e2015-08-07 14:00:07225 .WillRepeatedly(Return(QuicBandwidth::Zero()));
fnkf57804c2016-03-17 20:57:07226 EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
rtenneti44f4a2e2015-08-07 14:00:07227 .WillRepeatedly(Return(QuicTime::Delta::Zero()));
228 EXPECT_CALL(*send_algorithm_, BandwidthEstimate())
229 .WillRepeatedly(Return(QuicBandwidth::Zero()));
rch1e543ec2015-03-29 07:04:40230 EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(AnyNumber());
rch16c74d1d2016-04-22 06:14:07231 helper_.reset(
232 new QuicChromiumConnectionHelper(&clock_, &random_generator_));
233 alarm_factory_.reset(new QuicChromiumAlarmFactory(runner_.get(), &clock_));
234
235 connection_ =
236 new TestQuicConnection(SupportedVersions(GetParam()), connection_id_,
237 peer_addr_, helper_.get(), alarm_factory_.get(),
238 new QuicChromiumPacketWriter(socket.get()));
[email protected]f702d572012-12-04 15:56:20239 connection_->set_visitor(&visitor_);
[email protected]fee17f72013-02-03 07:47:41240 connection_->SetSendAlgorithm(send_algorithm_);
rch03b7a202016-02-05 00:54:20241
242 // Load a certificate that is valid for *.example.org
243 scoped_refptr<X509Certificate> test_cert(
244 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
245 EXPECT_TRUE(test_cert.get());
246
247 verify_details_.cert_verify_result.verified_cert = test_cert;
248 verify_details_.cert_verify_result.is_issued_by_known_root = true;
249 crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details_);
250
ckrasic4f9d88d2015-07-22 22:23:16251 session_.reset(new QuicChromiumClientSession(
xunjielib53b38c2016-03-24 15:54:36252 connection_, std::move(socket),
rtenneti1cd3b162015-09-29 02:58:28253 /*stream_factory=*/nullptr, &crypto_client_stream_factory_, &clock_,
bnc614a92d32016-04-04 13:56:07254 &transport_security_state_,
danakjad1777e2016-04-16 00:56:42255 base::WrapUnique(static_cast<QuicServerInfo*>(nullptr)),
bncb07c05532015-05-14 19:07:20256 QuicServerId(kDefaultServerHostName, kDefaultServerPort,
rch1fe2eeb2015-10-26 14:45:57257 PRIVACY_MODE_DISABLED),
rtenneti1cd3b162015-09-29 02:58:28258 kQuicYieldAfterPacketsRead,
259 QuicTime::Delta::FromMilliseconds(kQuicYieldAfterDurationMilliseconds),
rtennetia75df622015-06-21 23:59:50260 /*cert_verify_flags=*/0, DefaultQuicConfig(), &crypto_config_,
ckrasic244375a32016-02-04 21:21:22261 "CONNECTION_UNKNOWN", base::TimeTicks::Now(), &push_promise_index_,
tbansalfdf5665b2015-09-21 22:46:40262 base::ThreadTaskRunnerHandle::Get().get(),
xunjieli5fafe142016-03-23 23:32:54263 /*socket_performance_watcher=*/nullptr, net_log_.bound().net_log()));
rtennetid39bd762015-06-12 01:05:52264 session_->Initialize();
[email protected]ed3fc15d2013-03-08 18:37:44265 session_->GetCryptoStream()->CryptoConnect();
[email protected]8ba81212013-05-03 13:11:48266 EXPECT_TRUE(session_->IsCryptoHandshakeConfirmed());
rjshaded5ced072015-12-18 19:26:02267 stream_.reset(use_closing_stream_
268 ? new AutoClosingStream(session_->GetWeakPtr())
269 : new QuicHttpStream(session_->GetWeakPtr()));
ckrasic3865ee0f2016-02-29 22:04:56270
271 promised_stream_.reset(use_closing_stream_
272 ? new AutoClosingStream(session_->GetWeakPtr())
273 : new QuicHttpStream(session_->GetWeakPtr()));
274
275 push_promise_[":path"] = "/bar";
276 push_promise_[":authority"] = "www.example.org";
277 push_promise_[":version"] = "HTTP/1.1";
278 push_promise_[":method"] = "GET";
279 push_promise_[":scheme"] = "https";
280
281 promised_response_[":status"] = "200 OK";
282 promised_response_[":version"] = "HTTP/1.1";
283 promised_response_["content-type"] = "text/plain";
284
285 promise_url_ = SpdyUtils::GetUrlFromHeaderBlock(push_promise_);
286
287 serialized_push_promise_ =
288 SpdyUtils::SerializeUncompressedHeaders(push_promise_);
[email protected]6cca996b2013-01-25 07:43:36289 }
290
bnc614a92d32016-04-04 13:56:07291 void SetRequest(const string& method,
292 const string& path,
[email protected]1e960032013-12-20 19:00:20293 RequestPriority priority) {
alyssar2adf3ac2016-05-03 17:12:58294 request_headers_ = client_maker_.GetRequestHeaders(method, "http", path);
[email protected]6cca996b2013-01-25 07:43:36295 }
296
bnc614a92d32016-04-04 13:56:07297 void SetResponse(const string& status, const string& body) {
alyssar2adf3ac2016-05-03 17:12:58298 response_headers_ = server_maker_.GetResponseHeaders(status);
[email protected]92bf17c2014-03-03 21:14:03299 response_data_ = body;
[email protected]6cca996b2013-01-25 07:43:36300 }
[email protected]f702d572012-12-04 15:56:20301
danakjad1777e2016-04-16 00:56:42302 std::unique_ptr<QuicReceivedPacket> InnerConstructDataPacket(
ckrasic3865ee0f2016-02-29 22:04:56303 QuicPacketNumber packet_number,
304 QuicStreamId stream_id,
305 bool should_include_version,
306 bool fin,
307 QuicStreamOffset offset,
alyssar2adf3ac2016-05-03 17:12:58308 base::StringPiece data,
309 QuicTestPacketMaker* maker) {
310 return maker->MakeDataPacket(packet_number, stream_id,
ckrasic3865ee0f2016-02-29 22:04:56311 should_include_version, fin, offset, data);
312 }
313
alyssar2adf3ac2016-05-03 17:12:58314 std::unique_ptr<QuicReceivedPacket> ConstructClientDataPacket(
rtennetia004d332015-08-28 06:44:57315 QuicPacketNumber packet_number,
[email protected]e8ff26842013-03-22 21:02:05316 bool should_include_version,
[email protected]f702d572012-12-04 15:56:20317 bool fin,
318 QuicStreamOffset offset,
319 base::StringPiece data) {
ckrasic3865ee0f2016-02-29 22:04:56320 return InnerConstructDataPacket(packet_number, stream_id_,
alyssar2adf3ac2016-05-03 17:12:58321 should_include_version, fin, offset, data,
322 &client_maker_);
323 }
324
325 std::unique_ptr<QuicReceivedPacket> ConstructServerDataPacket(
326 QuicPacketNumber packet_number,
327 bool should_include_version,
328 bool fin,
329 QuicStreamOffset offset,
330 base::StringPiece data) {
331 return InnerConstructDataPacket(packet_number, stream_id_,
332 should_include_version, fin, offset, data,
333 &server_maker_);
ckrasic3865ee0f2016-02-29 22:04:56334 }
335
danakjad1777e2016-04-16 00:56:42336 std::unique_ptr<QuicReceivedPacket> InnerConstructRequestHeadersPacket(
ckrasic3865ee0f2016-02-29 22:04:56337 QuicPacketNumber packet_number,
338 QuicStreamId stream_id,
339 bool should_include_version,
340 bool fin,
341 RequestPriority request_priority,
342 size_t* spdy_headers_frame_length) {
343 SpdyPriority priority =
344 ConvertRequestPriorityToQuicPriority(request_priority);
alyssar2adf3ac2016-05-03 17:12:58345 return client_maker_.MakeRequestHeadersPacket(
ckrasic3865ee0f2016-02-29 22:04:56346 packet_number, stream_id, should_include_version, fin, priority,
347 request_headers_, spdy_headers_frame_length);
[email protected]f702d572012-12-04 15:56:20348 }
349
danakjad1777e2016-04-16 00:56:42350 std::unique_ptr<QuicReceivedPacket> ConstructRequestHeadersPacket(
rtennetia004d332015-08-28 06:44:57351 QuicPacketNumber packet_number,
rtennetif4bdb542015-01-21 14:33:05352 bool fin,
sclittlec4dc1a32015-09-24 00:15:45353 RequestPriority request_priority,
354 size_t* spdy_headers_frame_length) {
ckrasic3865ee0f2016-02-29 22:04:56355 return InnerConstructRequestHeadersPacket(
356 packet_number, stream_id_, kIncludeVersion, fin, request_priority,
357 spdy_headers_frame_length);
358 }
359
danakjad1777e2016-04-16 00:56:42360 std::unique_ptr<QuicReceivedPacket> InnerConstructResponseHeadersPacket(
ckrasic3865ee0f2016-02-29 22:04:56361 QuicPacketNumber packet_number,
362 QuicStreamId stream_id,
363 bool fin,
364 size_t* spdy_headers_frame_length) {
alyssar2adf3ac2016-05-03 17:12:58365 return server_maker_.MakeResponseHeadersPacket(
ckrasic3865ee0f2016-02-29 22:04:56366 packet_number, stream_id, !kIncludeVersion, fin, response_headers_,
367 spdy_headers_frame_length, &response_offset_);
[email protected]1e960032013-12-20 19:00:20368 }
369
danakjad1777e2016-04-16 00:56:42370 std::unique_ptr<QuicReceivedPacket> ConstructResponseHeadersPacket(
rtennetia004d332015-08-28 06:44:57371 QuicPacketNumber packet_number,
sclittlec4dc1a32015-09-24 00:15:45372 bool fin,
373 size_t* spdy_headers_frame_length) {
ckrasic3865ee0f2016-02-29 22:04:56374 return InnerConstructResponseHeadersPacket(packet_number, stream_id_, fin,
375 spdy_headers_frame_length);
[email protected]1e960032013-12-20 19:00:20376 }
377
danakjad1777e2016-04-16 00:56:42378 std::unique_ptr<QuicReceivedPacket> ConstructResponseHeadersPacketWithOffset(
xunjieli34291fe12016-03-02 13:58:38379 QuicPacketNumber packet_number,
380 bool fin,
381 size_t* spdy_headers_frame_length,
382 QuicStreamOffset* offset) {
alyssar2adf3ac2016-05-03 17:12:58383 return server_maker_.MakeResponseHeadersPacket(
xunjieli34291fe12016-03-02 13:58:38384 packet_number, stream_id_, !kIncludeVersion, fin, response_headers_,
385 spdy_headers_frame_length, offset);
386 }
387
danakjad1777e2016-04-16 00:56:42388 std::unique_ptr<QuicReceivedPacket> ConstructResponseTrailersPacket(
xunjieli34291fe12016-03-02 13:58:38389 QuicPacketNumber packet_number,
390 bool fin,
391 const SpdyHeaderBlock& trailers,
392 size_t* spdy_headers_frame_length,
393 QuicStreamOffset* offset) {
alyssar2adf3ac2016-05-03 17:12:58394 return server_maker_.MakeResponseHeadersPacket(
395 packet_number, stream_id_, !kIncludeVersion, fin, trailers,
396 spdy_headers_frame_length, offset);
xunjieli34291fe12016-03-02 13:58:38397 }
398
alyssar2adf3ac2016-05-03 17:12:58399 std::unique_ptr<QuicReceivedPacket> ConstructClientRstStreamPacket(
rtennetia004d332015-08-28 06:44:57400 QuicPacketNumber packet_number) {
alyssar2adf3ac2016-05-03 17:12:58401 return client_maker_.MakeRstPacket(
rtennetia004d332015-08-28 06:44:57402 packet_number, true, stream_id_,
rtenneti4a5df262014-11-07 00:43:58403 AdjustErrorForVersion(QUIC_RST_ACKNOWLEDGEMENT, GetParam()));
[email protected]06ff5152013-08-29 01:03:05404 }
405
alyssar2adf3ac2016-05-03 17:12:58406 std::unique_ptr<QuicReceivedPacket> ConstructClientRstStreamCancelledPacket(
rtennetia004d332015-08-28 06:44:57407 QuicPacketNumber packet_number) {
alyssar2adf3ac2016-05-03 17:12:58408 return client_maker_.MakeRstPacket(packet_number, !kIncludeVersion,
409 stream_id_, QUIC_STREAM_CANCELLED);
rtenneti6bd660b2015-07-18 00:19:53410 }
411
alyssar2adf3ac2016-05-03 17:12:58412 std::unique_ptr<QuicReceivedPacket>
413 ConstructClientRstStreamVaryMismatchPacket(QuicPacketNumber packet_number) {
414 return client_maker_.MakeRstPacket(packet_number, !kIncludeVersion,
415 promise_id_, QUIC_PROMISE_VARY_MISMATCH);
ckrasic3865ee0f2016-02-29 22:04:56416 }
417
danakjad1777e2016-04-16 00:56:42418 std::unique_ptr<QuicReceivedPacket> ConstructAckAndRstStreamPacket(
xunjieli34291fe12016-03-02 13:58:38419 QuicPacketNumber packet_number,
420 QuicPacketNumber largest_received,
421 QuicPacketNumber ack_least_unacked,
422 QuicPacketNumber stop_least_unacked) {
alyssar2adf3ac2016-05-03 17:12:58423 return client_maker_.MakeAckAndRstPacket(
xunjieli34291fe12016-03-02 13:58:38424 packet_number, !kIncludeVersion, stream_id_, QUIC_STREAM_CANCELLED,
425 largest_received, ack_least_unacked, stop_least_unacked,
426 !kIncludeCongestionFeedback);
427 }
428
danakjad1777e2016-04-16 00:56:42429 std::unique_ptr<QuicReceivedPacket> ConstructAckAndRstStreamPacket(
rtennetia004d332015-08-28 06:44:57430 QuicPacketNumber packet_number) {
xunjieli34291fe12016-03-02 13:58:38431 return ConstructAckAndRstStreamPacket(packet_number, 2, 1, 1);
[email protected]c5e1aca2014-01-30 04:03:04432 }
433
alyssar2adf3ac2016-05-03 17:12:58434 std::unique_ptr<QuicReceivedPacket> ConstructClientAckPacket(
rtennetia004d332015-08-28 06:44:57435 QuicPacketNumber packet_number,
436 QuicPacketNumber largest_received,
437 QuicPacketNumber least_unacked) {
alyssar2adf3ac2016-05-03 17:12:58438 return client_maker_.MakeAckPacket(packet_number, largest_received,
439 least_unacked,
440 !kIncludeCongestionFeedback);
441 }
442
443 std::unique_ptr<QuicReceivedPacket> ConstructServerAckPacket(
444 QuicPacketNumber packet_number,
445 QuicPacketNumber largest_received,
446 QuicPacketNumber least_unacked) {
447 return server_maker_.MakeAckPacket(packet_number, largest_received,
448 least_unacked,
449 !kIncludeCongestionFeedback);
[email protected]63534512012-12-23 18:49:00450 }
451
ckrasic3865ee0f2016-02-29 22:04:56452 void ReceivePromise(QuicStreamId id) {
453 QuicChromiumClientStream* stream =
454 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
455 stream->OnStreamHeaders(serialized_push_promise_);
456
457 stream->OnPromiseHeadersComplete(id, serialized_push_promise_.size());
458 }
459
xunjieli5fafe142016-03-23 23:32:54460 BoundTestNetLog net_log_;
[email protected]63534512012-12-23 18:49:00461 bool use_closing_stream_;
[email protected]fee17f72013-02-03 07:47:41462 MockSendAlgorithm* send_algorithm_;
[email protected]f702d572012-12-04 15:56:20463 scoped_refptr<TestTaskRunner> runner_;
danakjad1777e2016-04-16 00:56:42464 std::unique_ptr<MockWrite[]> mock_writes_;
[email protected]f702d572012-12-04 15:56:20465 MockClock clock_;
466 TestQuicConnection* connection_;
danakjad1777e2016-04-16 00:56:42467 std::unique_ptr<QuicChromiumConnectionHelper> helper_;
rch16c74d1d2016-04-22 06:14:07468 std::unique_ptr<QuicChromiumAlarmFactory> alarm_factory_;
ckrasica7fd1242016-05-14 20:36:01469 testing::StrictMock<MockQuicConnectionVisitor> visitor_;
danakjad1777e2016-04-16 00:56:42470 std::unique_ptr<QuicHttpStream> stream_;
[email protected]5db452202014-08-19 05:22:15471 TransportSecurityState transport_security_state_;
danakjad1777e2016-04-16 00:56:42472 std::unique_ptr<QuicChromiumClientSession> session_;
[email protected]ef95114d2013-04-17 17:57:01473 QuicCryptoClientConfig crypto_config_;
[email protected]f702d572012-12-04 15:56:20474 TestCompletionCallback callback_;
475 HttpRequestInfo request_;
476 HttpRequestHeaders headers_;
477 HttpResponseInfo response_;
478 scoped_refptr<IOBufferWithSize> read_buffer_;
[email protected]1e960032013-12-20 19:00:20479 SpdyHeaderBlock request_headers_;
480 SpdyHeaderBlock response_headers_;
bnc614a92d32016-04-04 13:56:07481 string request_data_;
482 string response_data_;
ckrasic244375a32016-02-04 21:21:22483 QuicClientPushPromiseIndex push_promise_index_;
[email protected]f702d572012-12-04 15:56:20484
ckrasic3865ee0f2016-02-29 22:04:56485 // For server push testing
danakjad1777e2016-04-16 00:56:42486 std::unique_ptr<QuicHttpStream> promised_stream_;
ckrasic3865ee0f2016-02-29 22:04:56487 SpdyHeaderBlock push_promise_;
488 SpdyHeaderBlock promised_response_;
489 const QuicStreamId promise_id_;
490 string promise_url_;
491 string serialized_push_promise_;
492 const QuicStreamId stream_id_;
493
[email protected]3aa9ca72014-02-27 19:39:43494 const QuicConnectionId connection_id_;
alyssar2adf3ac2016-05-03 17:12:58495 QuicTestPacketMaker client_maker_;
496 QuicTestPacketMaker server_maker_;
[email protected]f702d572012-12-04 15:56:20497 IPEndPoint self_addr_;
498 IPEndPoint peer_addr_;
[email protected]457d6952013-12-13 09:24:58499 MockRandom random_generator_;
rch03b7a202016-02-05 00:54:20500 ProofVerifyDetailsChromium verify_details_;
[email protected]e8ff26842013-03-22 21:02:05501 MockCryptoClientStreamFactory crypto_client_stream_factory_;
danakjad1777e2016-04-16 00:56:42502 std::unique_ptr<StaticSocketDataProvider> socket_data_;
[email protected]f702d572012-12-04 15:56:20503 std::vector<PacketToWrite> writes_;
ckrasic3865ee0f2016-02-29 22:04:56504 QuicStreamOffset response_offset_;
[email protected]f702d572012-12-04 15:56:20505};
506
rjshaded5ced072015-12-18 19:26:02507INSTANTIATE_TEST_CASE_P(Version,
508 QuicHttpStreamTest,
[email protected]1e960032013-12-20 19:00:20509 ::testing::ValuesIn(QuicSupportedVersions()));
510
511TEST_P(QuicHttpStreamTest, RenewStreamForAuth) {
[email protected]ed3fc15d2013-03-08 18:37:44512 Initialize();
rtennetibe635732014-10-02 22:51:42513 EXPECT_EQ(nullptr, stream_->RenewStreamForAuth());
[email protected]f702d572012-12-04 15:56:20514}
515
mmenkebd84c392015-09-02 14:12:34516TEST_P(QuicHttpStreamTest, CanReuseConnection) {
[email protected]ed3fc15d2013-03-08 18:37:44517 Initialize();
mmenkebd84c392015-09-02 14:12:34518 EXPECT_FALSE(stream_->CanReuseConnection());
[email protected]f702d572012-12-04 15:56:20519}
520
jri231c2972016-03-08 19:50:11521TEST_P(QuicHttpStreamTest, DisableConnectionMigrationForStream) {
522 request_.load_flags |= LOAD_DISABLE_CONNECTION_MIGRATION;
523 Initialize();
xunjieli5fafe142016-03-23 23:32:54524 EXPECT_EQ(OK,
525 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
526 net_log_.bound(), callback_.callback()));
jri231c2972016-03-08 19:50:11527 QuicChromiumClientStream* client_stream =
528 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
529 EXPECT_FALSE(client_stream->can_migrate());
530}
531
[email protected]1e960032013-12-20 19:00:20532TEST_P(QuicHttpStreamTest, GetRequest) {
533 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:45534 size_t spdy_request_header_frame_length;
535 AddWrite(ConstructRequestHeadersPacket(1, kFin, DEFAULT_PRIORITY,
536 &spdy_request_header_frame_length));
[email protected]f702d572012-12-04 15:56:20537 Initialize();
538
539 request_.method = "GET";
rch9ae5b3b2016-02-11 00:36:29540 request_.url = GURL("http://www.example.org/");
[email protected]f702d572012-12-04 15:56:20541
xunjieli5fafe142016-03-23 23:32:54542 EXPECT_EQ(OK,
543 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
544 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:02545 EXPECT_EQ(OK,
546 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20547
548 // Ack the request.
alyssar2adf3ac2016-05-03 17:12:58549 ProcessPacket(ConstructServerAckPacket(1, 0, 0));
[email protected]f702d572012-12-04 15:56:20550
rjshaded5ced072015-12-18 19:26:02551 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadResponseHeaders(callback_.callback()));
[email protected]f702d572012-12-04 15:56:20552
bnc614a92d32016-04-04 13:56:07553 SetResponse("404 Not Found", string());
sclittlec4dc1a32015-09-24 00:15:45554 size_t spdy_response_header_frame_length;
555 ProcessPacket(ConstructResponseHeadersPacket(
556 2, kFin, &spdy_response_header_frame_length));
[email protected]f702d572012-12-04 15:56:20557
558 // Now that the headers have been processed, the callback will return.
559 EXPECT_EQ(OK, callback_.WaitForResult());
[email protected]cadac622013-06-11 16:46:36560 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:20561 EXPECT_EQ(404, response_.headers->response_code());
562 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
[email protected]6ed67432014-06-24 01:53:53563 EXPECT_FALSE(response_.response_time.is_null());
564 EXPECT_FALSE(response_.request_time.is_null());
[email protected]f702d572012-12-04 15:56:20565
566 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:02567 EXPECT_EQ(0,
568 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
569 callback_.callback()));
[email protected]f702d572012-12-04 15:56:20570 EXPECT_TRUE(stream_->IsResponseBodyComplete());
571 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:10572
573 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:45574 // headers and payload.
575 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
576 stream_->GetTotalSentBytes());
577 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length),
578 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:20579}
580
xunjieli34291fe12016-03-02 13:58:38581// QuicHttpStream does not currently support trailers. It should ignore
582// trailers upon receiving them.
583TEST_P(QuicHttpStreamTest, GetRequestWithTrailers) {
584 SetRequest("GET", "/", DEFAULT_PRIORITY);
585 size_t spdy_request_header_frame_length;
586 AddWrite(ConstructRequestHeadersPacket(1, kFin, DEFAULT_PRIORITY,
587 &spdy_request_header_frame_length));
alyssar2adf3ac2016-05-03 17:12:58588 AddWrite(ConstructClientAckPacket(2, 3, 1)); // Ack the data packet.
xunjieli34291fe12016-03-02 13:58:38589
590 Initialize();
591
592 request_.method = "GET";
593 request_.url = GURL("http://www.example.org/");
594
xunjieli5fafe142016-03-23 23:32:54595 EXPECT_EQ(OK,
596 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
597 net_log_.bound(), callback_.callback()));
598
xunjieli34291fe12016-03-02 13:58:38599 EXPECT_EQ(OK,
600 stream_->SendRequest(headers_, &response_, callback_.callback()));
xunjieli34291fe12016-03-02 13:58:38601 // Ack the request.
alyssar2adf3ac2016-05-03 17:12:58602 ProcessPacket(ConstructServerAckPacket(1, 0, 0));
xunjieli34291fe12016-03-02 13:58:38603
604 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadResponseHeaders(callback_.callback()));
605
bnc614a92d32016-04-04 13:56:07606 SetResponse("200 OK", string());
xunjieli34291fe12016-03-02 13:58:38607
608 // Send the response headers.
609 size_t spdy_response_header_frame_length;
610 QuicStreamOffset offset = 0;
611 ProcessPacket(ConstructResponseHeadersPacketWithOffset(
612 2, !kFin, &spdy_response_header_frame_length, &offset));
613 // Now that the headers have been processed, the callback will return.
614 EXPECT_EQ(OK, callback_.WaitForResult());
615 ASSERT_TRUE(response_.headers.get());
616 EXPECT_EQ(200, response_.headers->response_code());
617 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
618 EXPECT_FALSE(response_.response_time.is_null());
619 EXPECT_FALSE(response_.request_time.is_null());
620
621 // Send the response body.
622 const char kResponseBody[] = "Hello world!";
623 ProcessPacket(
alyssar2adf3ac2016-05-03 17:12:58624 ConstructServerDataPacket(3, false, !kFin, /*offset=*/0, kResponseBody));
xunjieli34291fe12016-03-02 13:58:38625 SpdyHeaderBlock trailers;
626 size_t spdy_trailers_frame_length;
627 trailers["foo"] = "bar";
xunjieli188bd402016-03-12 00:17:25628 trailers[kFinalOffsetHeaderKey] = base::IntToString(strlen(kResponseBody));
xunjieli34291fe12016-03-02 13:58:38629 ProcessPacket(ConstructResponseTrailersPacket(
630 4, kFin, trailers, &spdy_trailers_frame_length, &offset));
631
632 // Make sure trailers are processed.
fdoray92e35a72016-06-10 15:54:55633 base::RunLoop().RunUntilIdle();
xunjieli34291fe12016-03-02 13:58:38634
635 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
636 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
637 callback_.callback()));
638 EXPECT_TRUE(stream_->IsResponseBodyComplete());
639
640 EXPECT_EQ(OK,
641 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
642 callback_.callback()));
643
644 EXPECT_TRUE(stream_->IsResponseBodyComplete());
645 EXPECT_TRUE(AtEof());
646
647 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
648 // headers and payload.
649 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
650 stream_->GetTotalSentBytes());
651 EXPECT_EQ(
652 static_cast<int64_t>(spdy_response_header_frame_length +
653 strlen(kResponseBody) + +spdy_trailers_frame_length),
654 stream_->GetTotalReceivedBytes());
xunjieli5fafe142016-03-23 23:32:54655 // Check that NetLog was filled as expected.
656 TestNetLogEntry::List entries;
657 net_log_.GetEntries(&entries);
658 size_t pos = ExpectLogContainsSomewhere(
659 entries, /*min_offset=*/0,
660 NetLog::TYPE_QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
661 NetLog::PHASE_NONE);
662 pos = ExpectLogContainsSomewhere(
663 entries, /*min_offset=*/pos,
664 NetLog::TYPE_QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
665 NetLog::PHASE_NONE);
666 ExpectLogContainsSomewhere(
667 entries, /*min_offset=*/pos,
668 NetLog::TYPE_QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
669 NetLog::PHASE_NONE);
xunjieli34291fe12016-03-02 13:58:38670}
671
[email protected]3e7dca62013-09-10 16:14:23672// Regression test for http://crbug.com/288128
[email protected]1e960032013-12-20 19:00:20673TEST_P(QuicHttpStreamTest, GetRequestLargeResponse) {
674 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:45675 size_t spdy_request_headers_frame_length;
676 AddWrite(ConstructRequestHeadersPacket(1, kFin, DEFAULT_PRIORITY,
677 &spdy_request_headers_frame_length));
[email protected]3e7dca62013-09-10 16:14:23678 Initialize();
679
680 request_.method = "GET";
rch9ae5b3b2016-02-11 00:36:29681 request_.url = GURL("http://www.example.org/");
[email protected]3e7dca62013-09-10 16:14:23682
xunjieli5fafe142016-03-23 23:32:54683 EXPECT_EQ(OK,
684 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
685 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:02686 EXPECT_EQ(OK,
687 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:23688
689 // Ack the request.
alyssar2adf3ac2016-05-03 17:12:58690 ProcessPacket(ConstructServerAckPacket(1, 0, 0));
[email protected]3e7dca62013-09-10 16:14:23691
rjshaded5ced072015-12-18 19:26:02692 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadResponseHeaders(callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:23693
694 SpdyHeaderBlock headers;
695 headers[":status"] = "200 OK";
696 headers[":version"] = "HTTP/1.1";
697 headers["content-type"] = "text/plain";
bnc614a92d32016-04-04 13:56:07698 headers["big6"] = string(1000, 'x'); // Lots of x's.
[email protected]3e7dca62013-09-10 16:14:23699
rch7dd15702015-07-01 18:57:57700 response_headers_ = headers;
sclittlec4dc1a32015-09-24 00:15:45701 size_t spdy_response_headers_frame_length;
702 ProcessPacket(ConstructResponseHeadersPacket(
703 2, kFin, &spdy_response_headers_frame_length));
[email protected]3e7dca62013-09-10 16:14:23704
705 // Now that the headers have been processed, the callback will return.
706 EXPECT_EQ(OK, callback_.WaitForResult());
707 ASSERT_TRUE(response_.headers.get());
708 EXPECT_EQ(200, response_.headers->response_code());
709 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
710
711 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:02712 EXPECT_EQ(0,
713 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
714 callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:23715 EXPECT_TRUE(stream_->IsResponseBodyComplete());
716 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:10717
718 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:45719 // headers and payload.
720 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
721 stream_->GetTotalSentBytes());
722 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length),
723 stream_->GetTotalReceivedBytes());
[email protected]3e7dca62013-09-10 16:14:23724}
725
rchf9f103cbc2014-08-30 05:28:04726// Regression test for http://crbug.com/409101
727TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendRequest) {
728 SetRequest("GET", "/", DEFAULT_PRIORITY);
729 Initialize();
730
731 request_.method = "GET";
rch9ae5b3b2016-02-11 00:36:29732 request_.url = GURL("http://www.example.org/");
rchf9f103cbc2014-08-30 05:28:04733
xunjieli5fafe142016-03-23 23:32:54734 EXPECT_EQ(OK,
735 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
736 net_log_.bound(), callback_.callback()));
rchf9f103cbc2014-08-30 05:28:04737
jri78ec06a2016-03-31 18:19:40738 session_->connection()->CloseConnection(
739 QUIC_NO_ERROR, "test", ConnectionCloseBehavior::SILENT_CLOSE);
rchf9f103cbc2014-08-30 05:28:04740
741 EXPECT_EQ(ERR_CONNECTION_CLOSED,
rjshaded5ced072015-12-18 19:26:02742 stream_->SendRequest(headers_, &response_, callback_.callback()));
sclittle1edeeb22015-09-02 20:46:10743
744 EXPECT_EQ(0, stream_->GetTotalSentBytes());
745 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rchf9f103cbc2014-08-30 05:28:04746}
747
rch03b7a202016-02-05 00:54:20748// Regression test for http://crbug.com/584441
749TEST_P(QuicHttpStreamTest, GetSSLInfoAfterSessionClosed) {
750 SetRequest("GET", "/", DEFAULT_PRIORITY);
751 Initialize();
752
753 request_.method = "GET";
rch9ae5b3b2016-02-11 00:36:29754 request_.url = GURL("http://www.example.org/");
rch03b7a202016-02-05 00:54:20755
xunjieli5fafe142016-03-23 23:32:54756 EXPECT_EQ(OK,
757 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
758 net_log_.bound(), callback_.callback()));
rch03b7a202016-02-05 00:54:20759
760 SSLInfo ssl_info;
rch11565e02016-02-09 20:13:47761 EXPECT_FALSE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:20762 stream_->GetSSLInfo(&ssl_info);
rch11565e02016-02-09 20:13:47763 EXPECT_TRUE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:20764
jri78ec06a2016-03-31 18:19:40765 session_->connection()->CloseConnection(
766 QUIC_NO_ERROR, "test", ConnectionCloseBehavior::SILENT_CLOSE);
rch03b7a202016-02-05 00:54:20767
rch11565e02016-02-09 20:13:47768 SSLInfo ssl_info2;
769 stream_->GetSSLInfo(&ssl_info2);
770 EXPECT_TRUE(ssl_info2.is_valid());
rch03b7a202016-02-05 00:54:20771}
772
zhongyica364fbb2015-12-12 03:39:12773TEST_P(QuicHttpStreamTest, LogGranularQuicConnectionError) {
774 SetRequest("GET", "/", DEFAULT_PRIORITY);
775 size_t spdy_request_headers_frame_length;
776 AddWrite(ConstructRequestHeadersPacket(1, kFin, DEFAULT_PRIORITY,
777 &spdy_request_headers_frame_length));
778 AddWrite(ConstructAckAndRstStreamPacket(2));
779 use_closing_stream_ = true;
780 Initialize();
781
782 request_.method = "GET";
rch9ae5b3b2016-02-11 00:36:29783 request_.url = GURL("http://www.example.org/");
zhongyica364fbb2015-12-12 03:39:12784
xunjieli5fafe142016-03-23 23:32:54785 EXPECT_EQ(OK,
786 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
787 net_log_.bound(), callback_.callback()));
zhongyica364fbb2015-12-12 03:39:12788 EXPECT_EQ(OK,
789 stream_->SendRequest(headers_, &response_, callback_.callback()));
790
791 // Ack the request.
alyssar2adf3ac2016-05-03 17:12:58792 ProcessPacket(ConstructServerAckPacket(1, 0, 0));
zhongyica364fbb2015-12-12 03:39:12793 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadResponseHeaders(callback_.callback()));
794
795 EXPECT_TRUE(QuicHttpStreamPeer::WasHandshakeConfirmed(stream_.get()));
796 stream_->OnClose(QUIC_PEER_GOING_AWAY);
797
798 NetErrorDetails details;
799 EXPECT_EQ(QUIC_NO_ERROR, details.quic_connection_error);
800 stream_->PopulateNetErrorDetails(&details);
801 EXPECT_EQ(QUIC_PEER_GOING_AWAY, details.quic_connection_error);
802}
803
804TEST_P(QuicHttpStreamTest, DoNotLogGranularQuicErrorIfHandshakeNotConfirmed) {
805 SetRequest("GET", "/", DEFAULT_PRIORITY);
806 size_t spdy_request_headers_frame_length;
807 AddWrite(ConstructRequestHeadersPacket(1, kFin, DEFAULT_PRIORITY,
808 &spdy_request_headers_frame_length));
809 AddWrite(ConstructAckAndRstStreamPacket(2));
810 use_closing_stream_ = true;
811 Initialize();
812
813 request_.method = "GET";
rch9ae5b3b2016-02-11 00:36:29814 request_.url = GURL("http://www.example.org/");
zhongyica364fbb2015-12-12 03:39:12815
xunjieli5fafe142016-03-23 23:32:54816 EXPECT_EQ(OK,
817 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
818 net_log_.bound(), callback_.callback()));
zhongyica364fbb2015-12-12 03:39:12819 EXPECT_EQ(OK,
820 stream_->SendRequest(headers_, &response_, callback_.callback()));
821
822 // Ack the request.
alyssar2adf3ac2016-05-03 17:12:58823 ProcessPacket(ConstructServerAckPacket(1, 0, 0));
zhongyica364fbb2015-12-12 03:39:12824 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadResponseHeaders(callback_.callback()));
825
826 // The test setup defaults handshake to be confirmed. Manually set
827 // it to be not confirmed.
828 // Granular errors shouldn't be reported if handshake not confirmed.
829 QuicHttpStreamPeer::SetHandshakeConfirmed(stream_.get(), false);
830
831 EXPECT_FALSE(QuicHttpStreamPeer::WasHandshakeConfirmed(stream_.get()));
832 stream_->OnClose(QUIC_PEER_GOING_AWAY);
833
834 NetErrorDetails details;
835 EXPECT_EQ(QUIC_NO_ERROR, details.quic_connection_error);
836 stream_->PopulateNetErrorDetails(&details);
837 EXPECT_EQ(QUIC_NO_ERROR, details.quic_connection_error);
838}
839
rch11a114a2014-09-04 23:41:59840// Regression test for http://crbug.com/409871
841TEST_P(QuicHttpStreamTest, SessionClosedBeforeReadResponseHeaders) {
842 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:45843 size_t spdy_request_headers_frame_length;
844 AddWrite(ConstructRequestHeadersPacket(1, kFin, DEFAULT_PRIORITY,
845 &spdy_request_headers_frame_length));
rch11a114a2014-09-04 23:41:59846 Initialize();
847
848 request_.method = "GET";
rch9ae5b3b2016-02-11 00:36:29849 request_.url = GURL("http://www.example.org/");
rch11a114a2014-09-04 23:41:59850
xunjieli5fafe142016-03-23 23:32:54851 EXPECT_EQ(OK,
852 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
853 net_log_.bound(), callback_.callback()));
rch11a114a2014-09-04 23:41:59854
rjshaded5ced072015-12-18 19:26:02855 EXPECT_EQ(OK,
856 stream_->SendRequest(headers_, &response_, callback_.callback()));
rch11a114a2014-09-04 23:41:59857
jri78ec06a2016-03-31 18:19:40858 session_->connection()->CloseConnection(
859 QUIC_NO_ERROR, "test", ConnectionCloseBehavior::SILENT_CLOSE);
rch11a114a2014-09-04 23:41:59860
861 EXPECT_NE(OK, stream_->ReadResponseHeaders(callback_.callback()));
sclittle1edeeb22015-09-02 20:46:10862
863 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:45864 // headers and payload.
865 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
866 stream_->GetTotalSentBytes());
sclittle1edeeb22015-09-02 20:46:10867 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rch11a114a2014-09-04 23:41:59868}
869
[email protected]1e960032013-12-20 19:00:20870TEST_P(QuicHttpStreamTest, SendPostRequest) {
871 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:45872 size_t spdy_request_headers_frame_length;
873 AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY,
874 &spdy_request_headers_frame_length));
alyssar2adf3ac2016-05-03 17:12:58875 AddWrite(ConstructClientDataPacket(2, kIncludeVersion, kFin, 0, kUploadData));
876 AddWrite(ConstructClientAckPacket(3, 3, 1));
[email protected]f702d572012-12-04 15:56:20877
878 Initialize();
879
danakjad1777e2016-04-16 00:56:42880 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
881 element_readers.push_back(base::WrapUnique(
olli.raula6df48b2a2015-11-26 07:40:22882 new UploadBytesElementReader(kUploadData, strlen(kUploadData))));
883 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]f702d572012-12-04 15:56:20884 request_.method = "POST";
rch9ae5b3b2016-02-11 00:36:29885 request_.url = GURL("http://www.example.org/");
[email protected]f702d572012-12-04 15:56:20886 request_.upload_data_stream = &upload_data_stream;
[email protected]4db27d82012-12-20 11:50:24887 ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback()));
[email protected]f702d572012-12-04 15:56:20888
xunjieli5fafe142016-03-23 23:32:54889 EXPECT_EQ(OK,
890 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
891 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:02892 EXPECT_EQ(OK,
893 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20894
895 // Ack both packets in the request.
alyssar2adf3ac2016-05-03 17:12:58896 ProcessPacket(ConstructServerAckPacket(1, 0, 0));
[email protected]f702d572012-12-04 15:56:20897
898 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:07899 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:45900 size_t spdy_response_headers_frame_length;
901 ProcessPacket(ConstructResponseHeadersPacket(
902 2, !kFin, &spdy_response_headers_frame_length));
[email protected]f702d572012-12-04 15:56:20903
rchb27683c2015-07-29 23:53:50904 // The headers have arrived, but they are delivered asynchronously.
905 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadResponseHeaders(callback_.callback()));
906 EXPECT_EQ(OK, callback_.WaitForResult());
[email protected]cadac622013-06-11 16:46:36907 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:20908 EXPECT_EQ(200, response_.headers->response_code());
909 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
910
911 // Send the response body.
912 const char kResponseBody[] = "Hello world!";
alyssar2adf3ac2016-05-03 17:12:58913 ProcessPacket(ConstructServerDataPacket(3, false, kFin, 0, kResponseBody));
[email protected]f702d572012-12-04 15:56:20914 // Since the body has already arrived, this should return immediately.
915 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
916 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
917 callback_.callback()));
918
919 EXPECT_TRUE(stream_->IsResponseBodyComplete());
920 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:10921
922 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:45923 // headers and payload.
924 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
925 strlen(kUploadData)),
sclittle1edeeb22015-09-02 20:46:10926 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:45927 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
928 strlen(kResponseBody)),
sclittle1edeeb22015-09-02 20:46:10929 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:20930}
931
[email protected]1e960032013-12-20 19:00:20932TEST_P(QuicHttpStreamTest, SendChunkedPostRequest) {
933 SetRequest("POST", "/", DEFAULT_PRIORITY);
[email protected]c9e49a02013-02-26 05:56:47934 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:45935 size_t spdy_request_headers_frame_length;
936 AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY,
937 &spdy_request_headers_frame_length));
rjshaded5ced072015-12-18 19:26:02938 AddWrite(
alyssar2adf3ac2016-05-03 17:12:58939 ConstructClientDataPacket(2, kIncludeVersion, !kFin, 0, kUploadData));
940 AddWrite(ConstructClientDataPacket(3, kIncludeVersion, kFin, chunk_size,
941 kUploadData));
942 AddWrite(ConstructClientAckPacket(4, 3, 1));
[email protected]c9e49a02013-02-26 05:56:47943 Initialize();
944
mmenkecbc2b712014-10-09 20:29:07945 ChunkedUploadDataStream upload_data_stream(0);
946 upload_data_stream.AppendData(kUploadData, chunk_size, false);
[email protected]c9e49a02013-02-26 05:56:47947
948 request_.method = "POST";
rch9ae5b3b2016-02-11 00:36:29949 request_.url = GURL("http://www.example.org/");
[email protected]c9e49a02013-02-26 05:56:47950 request_.upload_data_stream = &upload_data_stream;
mmenkecbc2b712014-10-09 20:29:07951 ASSERT_EQ(OK, request_.upload_data_stream->Init(
rjshaded5ced072015-12-18 19:26:02952 TestCompletionCallback().callback()));
[email protected]c9e49a02013-02-26 05:56:47953
xunjieli5fafe142016-03-23 23:32:54954 ASSERT_EQ(OK,
955 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
956 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:02957 ASSERT_EQ(ERR_IO_PENDING,
958 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]c9e49a02013-02-26 05:56:47959
mmenkecbc2b712014-10-09 20:29:07960 upload_data_stream.AppendData(kUploadData, chunk_size, true);
rchb27683c2015-07-29 23:53:50961 EXPECT_EQ(OK, callback_.WaitForResult());
[email protected]c9e49a02013-02-26 05:56:47962
963 // Ack both packets in the request.
alyssar2adf3ac2016-05-03 17:12:58964 ProcessPacket(ConstructServerAckPacket(1, 0, 0));
[email protected]c9e49a02013-02-26 05:56:47965
966 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:07967 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:45968 size_t spdy_response_headers_frame_length;
969 ProcessPacket(ConstructResponseHeadersPacket(
970 2, !kFin, &spdy_response_headers_frame_length));
[email protected]c9e49a02013-02-26 05:56:47971
rchb27683c2015-07-29 23:53:50972 // The headers have arrived, but they are delivered asynchronously
973 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadResponseHeaders(callback_.callback()));
974 EXPECT_EQ(OK, callback_.WaitForResult());
[email protected]cadac622013-06-11 16:46:36975 ASSERT_TRUE(response_.headers.get());
[email protected]c9e49a02013-02-26 05:56:47976 EXPECT_EQ(200, response_.headers->response_code());
977 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
978
979 // Send the response body.
980 const char kResponseBody[] = "Hello world!";
alyssar2adf3ac2016-05-03 17:12:58981 ProcessPacket(ConstructServerDataPacket(
982 3, false, kFin, response_data_.length(), kResponseBody));
[email protected]c9e49a02013-02-26 05:56:47983
984 // Since the body has already arrived, this should return immediately.
985 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
986 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
987 callback_.callback()));
988
989 EXPECT_TRUE(stream_->IsResponseBodyComplete());
990 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:10991
992 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:45993 // headers and payload.
994 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
995 strlen(kUploadData) * 2),
sclittle1edeeb22015-09-02 20:46:10996 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:45997 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
998 strlen(kResponseBody)),
sclittle1edeeb22015-09-02 20:46:10999 stream_->GetTotalReceivedBytes());
[email protected]c9e49a02013-02-26 05:56:471000}
1001
[email protected]16ba7742014-08-22 00:57:251002TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithFinalEmptyDataPacket) {
1003 SetRequest("POST", "/", DEFAULT_PRIORITY);
1004 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:451005 size_t spdy_request_headers_frame_length;
1006 AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY,
1007 &spdy_request_headers_frame_length));
alyssar2adf3ac2016-05-03 17:12:581008 AddWrite(
1009 ConstructClientDataPacket(2, kIncludeVersion, !kFin, 0, kUploadData));
1010 AddWrite(ConstructClientDataPacket(3, kIncludeVersion, kFin, chunk_size, ""));
1011 AddWrite(ConstructClientAckPacket(4, 3, 1));
[email protected]16ba7742014-08-22 00:57:251012 Initialize();
1013
mmenkecbc2b712014-10-09 20:29:071014 ChunkedUploadDataStream upload_data_stream(0);
1015 upload_data_stream.AppendData(kUploadData, chunk_size, false);
[email protected]16ba7742014-08-22 00:57:251016
1017 request_.method = "POST";
rch9ae5b3b2016-02-11 00:36:291018 request_.url = GURL("http://www.example.org/");
[email protected]16ba7742014-08-22 00:57:251019 request_.upload_data_stream = &upload_data_stream;
mmenkecbc2b712014-10-09 20:29:071020 ASSERT_EQ(OK, request_.upload_data_stream->Init(
rjshaded5ced072015-12-18 19:26:021021 TestCompletionCallback().callback()));
[email protected]16ba7742014-08-22 00:57:251022
xunjieli5fafe142016-03-23 23:32:541023 ASSERT_EQ(OK,
1024 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1025 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021026 ASSERT_EQ(ERR_IO_PENDING,
1027 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251028
mmenkecbc2b712014-10-09 20:29:071029 upload_data_stream.AppendData(nullptr, 0, true);
rchb27683c2015-07-29 23:53:501030 EXPECT_EQ(OK, callback_.WaitForResult());
[email protected]16ba7742014-08-22 00:57:251031
alyssar2adf3ac2016-05-03 17:12:581032 ProcessPacket(ConstructServerAckPacket(1, 0, 0));
[email protected]16ba7742014-08-22 00:57:251033
1034 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071035 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451036 size_t spdy_response_headers_frame_length;
1037 ProcessPacket(ConstructResponseHeadersPacket(
1038 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251039
rchb27683c2015-07-29 23:53:501040 // The headers have arrived, but they are delivered asynchronously
1041 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadResponseHeaders(callback_.callback()));
1042 EXPECT_EQ(OK, callback_.WaitForResult());
[email protected]16ba7742014-08-22 00:57:251043 ASSERT_TRUE(response_.headers.get());
1044 EXPECT_EQ(200, response_.headers->response_code());
1045 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1046
1047 // Send the response body.
1048 const char kResponseBody[] = "Hello world!";
alyssar2adf3ac2016-05-03 17:12:581049 ProcessPacket(ConstructServerDataPacket(
1050 3, false, kFin, response_data_.length(), kResponseBody));
[email protected]16ba7742014-08-22 00:57:251051
rchb27683c2015-07-29 23:53:501052 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251053 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1054 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1055 callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251056 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1057 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101058
1059 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451060 // headers and payload.
1061 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
1062 strlen(kUploadData)),
sclittle1edeeb22015-09-02 20:46:101063 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451064 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1065 strlen(kResponseBody)),
sclittle1edeeb22015-09-02 20:46:101066 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251067}
1068
1069TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithOneEmptyDataPacket) {
1070 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451071 size_t spdy_request_headers_frame_length;
1072 AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY,
1073 &spdy_request_headers_frame_length));
alyssar2adf3ac2016-05-03 17:12:581074 AddWrite(ConstructClientDataPacket(2, kIncludeVersion, kFin, 0, ""));
1075 AddWrite(ConstructClientAckPacket(3, 3, 1));
[email protected]16ba7742014-08-22 00:57:251076 Initialize();
1077
mmenkecbc2b712014-10-09 20:29:071078 ChunkedUploadDataStream upload_data_stream(0);
[email protected]16ba7742014-08-22 00:57:251079
1080 request_.method = "POST";
rch9ae5b3b2016-02-11 00:36:291081 request_.url = GURL("http://www.example.org/");
[email protected]16ba7742014-08-22 00:57:251082 request_.upload_data_stream = &upload_data_stream;
mmenkecbc2b712014-10-09 20:29:071083 ASSERT_EQ(OK, request_.upload_data_stream->Init(
rjshaded5ced072015-12-18 19:26:021084 TestCompletionCallback().callback()));
[email protected]16ba7742014-08-22 00:57:251085
xunjieli5fafe142016-03-23 23:32:541086 ASSERT_EQ(OK,
1087 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1088 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021089 ASSERT_EQ(ERR_IO_PENDING,
1090 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251091
mmenkecbc2b712014-10-09 20:29:071092 upload_data_stream.AppendData(nullptr, 0, true);
rchb27683c2015-07-29 23:53:501093 EXPECT_EQ(OK, callback_.WaitForResult());
[email protected]16ba7742014-08-22 00:57:251094
alyssar2adf3ac2016-05-03 17:12:581095 ProcessPacket(ConstructServerAckPacket(1, 0, 0));
[email protected]16ba7742014-08-22 00:57:251096
1097 // Send the response headers (but not the body).
bnc614a92d32016-04-04 13:56:071098 SetResponse("200 OK", string());
sclittlec4dc1a32015-09-24 00:15:451099 size_t spdy_response_headers_frame_length;
1100 ProcessPacket(ConstructResponseHeadersPacket(
1101 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251102
rchb27683c2015-07-29 23:53:501103 // The headers have arrived, but they are delivered asynchronously
1104 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadResponseHeaders(callback_.callback()));
1105 EXPECT_EQ(OK, callback_.WaitForResult());
[email protected]16ba7742014-08-22 00:57:251106 ASSERT_TRUE(response_.headers.get());
1107 EXPECT_EQ(200, response_.headers->response_code());
1108 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1109
1110 // Send the response body.
1111 const char kResponseBody[] = "Hello world!";
alyssar2adf3ac2016-05-03 17:12:581112 ProcessPacket(ConstructServerDataPacket(
1113 3, false, kFin, response_data_.length(), kResponseBody));
[email protected]16ba7742014-08-22 00:57:251114
rchb27683c2015-07-29 23:53:501115 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251116 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1117 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1118 callback_.callback()));
1119
1120 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1121 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101122
1123 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451124 // headers and payload.
1125 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1126 stream_->GetTotalSentBytes());
1127 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1128 strlen(kResponseBody)),
sclittle1edeeb22015-09-02 20:46:101129 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251130}
1131
[email protected]1e960032013-12-20 19:00:201132TEST_P(QuicHttpStreamTest, DestroyedEarly) {
1133 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451134 size_t spdy_request_headers_frame_length;
1135 AddWrite(ConstructRequestHeadersPacket(1, kFin, DEFAULT_PRIORITY,
1136 &spdy_request_headers_frame_length));
rtenneti4efd55dd2015-09-18 01:12:041137 AddWrite(ConstructAckAndRstStreamPacket(2));
[email protected]63534512012-12-23 18:49:001138 use_closing_stream_ = true;
1139 Initialize();
1140
1141 request_.method = "GET";
rch9ae5b3b2016-02-11 00:36:291142 request_.url = GURL("http://www.example.org/");
[email protected]63534512012-12-23 18:49:001143
xunjieli5fafe142016-03-23 23:32:541144 EXPECT_EQ(OK,
1145 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1146 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021147 EXPECT_EQ(OK,
1148 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]63534512012-12-23 18:49:001149
1150 // Ack the request.
alyssar2adf3ac2016-05-03 17:12:581151 ProcessPacket(ConstructServerAckPacket(1, 0, 0));
rjshaded5ced072015-12-18 19:26:021152 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadResponseHeaders(callback_.callback()));
[email protected]63534512012-12-23 18:49:001153
1154 // Send the response with a body.
[email protected]1e960032013-12-20 19:00:201155 SetResponse("404 OK", "hello world!");
[email protected]63534512012-12-23 18:49:001156 // In the course of processing this packet, the QuicHttpStream close itself.
sclittlec4dc1a32015-09-24 00:15:451157 ProcessPacket(ConstructResponseHeadersPacket(2, kFin, nullptr));
[email protected]63534512012-12-23 18:49:001158
fdoray92e35a72016-06-10 15:54:551159 base::RunLoop().RunUntilIdle();
rchb27683c2015-07-29 23:53:501160
[email protected]63534512012-12-23 18:49:001161 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101162
1163 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451164 // headers and payload.
1165 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1166 stream_->GetTotalSentBytes());
1167 // Zero since the stream is closed before processing the headers.
sclittle1edeeb22015-09-02 20:46:101168 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
[email protected]63534512012-12-23 18:49:001169}
1170
[email protected]1e960032013-12-20 19:00:201171TEST_P(QuicHttpStreamTest, Priority) {
1172 SetRequest("GET", "/", MEDIUM);
sclittlec4dc1a32015-09-24 00:15:451173 size_t spdy_request_headers_frame_length;
1174 AddWrite(ConstructRequestHeadersPacket(1, kFin, MEDIUM,
1175 &spdy_request_headers_frame_length));
rtenneti4efd55dd2015-09-18 01:12:041176 AddWrite(ConstructAckAndRstStreamPacket(2));
[email protected]24e5bc52013-09-18 15:36:581177 use_closing_stream_ = true;
1178 Initialize();
1179
1180 request_.method = "GET";
rch9ae5b3b2016-02-11 00:36:291181 request_.url = GURL("http://www.example.org/");
[email protected]24e5bc52013-09-18 15:36:581182
xunjieli5fafe142016-03-23 23:32:541183 EXPECT_EQ(OK, stream_->InitializeStream(&request_, MEDIUM, net_log_.bound(),
rjshaded5ced072015-12-18 19:26:021184 callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581185
1186 // Check that priority is highest.
rch12fef552016-01-15 16:26:311187 QuicChromiumClientStream* reliable_stream =
1188 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
[email protected]24e5bc52013-09-18 15:36:581189 DCHECK(reliable_stream);
fayanga64c1a92016-02-13 01:55:581190 DCHECK_EQ(kV3HighestPriority, reliable_stream->priority());
[email protected]24e5bc52013-09-18 15:36:581191
rjshaded5ced072015-12-18 19:26:021192 EXPECT_EQ(OK,
1193 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581194
1195 // Check that priority has now dropped back to MEDIUM.
ianswett0888cff2015-11-24 17:42:161196 DCHECK_EQ(MEDIUM,
fayanga64c1a92016-02-13 01:55:581197 ConvertQuicPriorityToRequestPriority(reliable_stream->priority()));
[email protected]24e5bc52013-09-18 15:36:581198
1199 // Ack the request.
alyssar2adf3ac2016-05-03 17:12:581200 ProcessPacket(ConstructServerAckPacket(1, 0, 0));
rjshaded5ced072015-12-18 19:26:021201 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadResponseHeaders(callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581202
1203 // Send the response with a body.
[email protected]1e960032013-12-20 19:00:201204 SetResponse("404 OK", "hello world!");
[email protected]24e5bc52013-09-18 15:36:581205 // In the course of processing this packet, the QuicHttpStream close itself.
sclittlec4dc1a32015-09-24 00:15:451206 ProcessPacket(ConstructResponseHeadersPacket(2, kFin, nullptr));
[email protected]24e5bc52013-09-18 15:36:581207
fdoray92e35a72016-06-10 15:54:551208 base::RunLoop().RunUntilIdle();
rchb27683c2015-07-29 23:53:501209
[email protected]24e5bc52013-09-18 15:36:581210 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101211
1212 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451213 // headers and payload.
1214 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1215 stream_->GetTotalSentBytes());
1216 // Zero since the stream is closed before processing the headers.
sclittle1edeeb22015-09-02 20:46:101217 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
[email protected]24e5bc52013-09-18 15:36:581218}
1219
[email protected]e1cca9a2013-09-20 17:14:441220// Regression test for http://crbug.com/294870
[email protected]1e960032013-12-20 19:00:201221TEST_P(QuicHttpStreamTest, CheckPriorityWithNoDelegate) {
1222 SetRequest("GET", "/", MEDIUM);
[email protected]e1cca9a2013-09-20 17:14:441223 use_closing_stream_ = true;
[email protected]459a7402014-02-10 12:58:521224
alyssar2adf3ac2016-05-03 17:12:581225 AddWrite(ConstructClientRstStreamPacket(1));
[email protected]459a7402014-02-10 12:58:521226
[email protected]e1cca9a2013-09-20 17:14:441227 Initialize();
1228
1229 request_.method = "GET";
rch9ae5b3b2016-02-11 00:36:291230 request_.url = GURL("http://www.example.org/");
[email protected]e1cca9a2013-09-20 17:14:441231
xunjieli5fafe142016-03-23 23:32:541232 EXPECT_EQ(OK, stream_->InitializeStream(&request_, MEDIUM, net_log_.bound(),
rjshaded5ced072015-12-18 19:26:021233 callback_.callback()));
[email protected]e1cca9a2013-09-20 17:14:441234
1235 // Check that priority is highest.
rch12fef552016-01-15 16:26:311236 QuicChromiumClientStream* reliable_stream =
1237 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
[email protected]e1cca9a2013-09-20 17:14:441238 DCHECK(reliable_stream);
rch12fef552016-01-15 16:26:311239 QuicChromiumClientStream::Delegate* delegate = reliable_stream->GetDelegate();
[email protected]e1cca9a2013-09-20 17:14:441240 DCHECK(delegate);
fayanga64c1a92016-02-13 01:55:581241 DCHECK_EQ(kV3HighestPriority, reliable_stream->priority());
[email protected]e1cca9a2013-09-20 17:14:441242
ianswett0888cff2015-11-24 17:42:161243 // Set Delegate to nullptr and make sure Priority returns highest
[email protected]e1cca9a2013-09-20 17:14:441244 // priority.
rtennetibe635732014-10-02 22:51:421245 reliable_stream->SetDelegate(nullptr);
fayanga64c1a92016-02-13 01:55:581246 DCHECK_EQ(kV3HighestPriority, reliable_stream->priority());
[email protected]e1cca9a2013-09-20 17:14:441247 reliable_stream->SetDelegate(delegate);
sclittle1edeeb22015-09-02 20:46:101248
sclittle1edeeb22015-09-02 20:46:101249 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1250 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
[email protected]e1cca9a2013-09-20 17:14:441251}
1252
rtenneti15656ae2016-01-23 03:05:031253TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersComplete) {
1254 SetRequest("POST", "/", DEFAULT_PRIORITY);
1255 AddWrite(SYNCHRONOUS, ERR_FAILED);
1256 Initialize();
1257
1258 ChunkedUploadDataStream upload_data_stream(0);
1259
1260 request_.method = "POST";
rch9ae5b3b2016-02-11 00:36:291261 request_.url = GURL("http://www.example.org/");
rtenneti15656ae2016-01-23 03:05:031262 request_.upload_data_stream = &upload_data_stream;
1263 ASSERT_EQ(OK, request_.upload_data_stream->Init(
1264 TestCompletionCallback().callback()));
1265
xunjieli5fafe142016-03-23 23:32:541266 ASSERT_EQ(OK,
1267 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1268 net_log_.bound(), callback_.callback()));
rtenneti15656ae2016-01-23 03:05:031269 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1270 stream_->SendRequest(headers_, &response_, callback_.callback()));
1271}
1272
1273TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBodyComplete) {
1274 SetRequest("POST", "/", DEFAULT_PRIORITY);
1275 size_t spdy_request_headers_frame_length;
1276 AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY,
1277 &spdy_request_headers_frame_length));
1278 AddWrite(SYNCHRONOUS, ERR_FAILED);
1279 Initialize();
1280
1281 ChunkedUploadDataStream upload_data_stream(0);
1282 size_t chunk_size = strlen(kUploadData);
1283 upload_data_stream.AppendData(kUploadData, chunk_size, false);
1284
1285 request_.method = "POST";
rch9ae5b3b2016-02-11 00:36:291286 request_.url = GURL("http://www.example.org/");
rtenneti15656ae2016-01-23 03:05:031287 request_.upload_data_stream = &upload_data_stream;
1288 ASSERT_EQ(OK, request_.upload_data_stream->Init(
1289 TestCompletionCallback().callback()));
1290
xunjieli5fafe142016-03-23 23:32:541291 ASSERT_EQ(OK,
1292 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1293 net_log_.bound(), callback_.callback()));
rtenneti15656ae2016-01-23 03:05:031294 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1295 stream_->SendRequest(headers_, &response_, callback_.callback()));
1296}
1297
ckrasic3865ee0f2016-02-29 22:04:561298TEST_P(QuicHttpStreamTest, ServerPushGetRequest) {
1299 SetRequest("GET", "/", DEFAULT_PRIORITY);
1300 Initialize();
1301
1302 // Initialize the first stream, for receiving the promise on.
1303 request_.method = "GET";
1304 request_.url = GURL("http://www.example.org/");
1305
xunjieli5fafe142016-03-23 23:32:541306 EXPECT_EQ(OK,
1307 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1308 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561309
1310 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
1311 // packet, but does it matter?
1312 ReceivePromise(promise_id_);
1313 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
1314
1315 request_.url = GURL(promise_url_);
1316
1317 // Make the second stream that will exercise the first step of the
1318 // server push rendezvous mechanism.
xunjieli5fafe142016-03-23 23:32:541319 EXPECT_EQ(OK, promised_stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1320 net_log_.bound(),
1321 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561322
1323 // Receive the promised response headers.
1324 response_headers_ = promised_response_;
1325 size_t spdy_response_headers_frame_length;
1326 ProcessPacket(InnerConstructResponseHeadersPacket(
1327 1, promise_id_, false, &spdy_response_headers_frame_length));
1328
1329 // Receive the promised response body.
1330 const char kResponseBody[] = "Hello world!";
alyssar2adf3ac2016-05-03 17:12:581331 ProcessPacket(InnerConstructDataPacket(2, promise_id_, false, kFin, 0,
1332 kResponseBody, &server_maker_));
ckrasic3865ee0f2016-02-29 22:04:561333
1334 // Now sending a matching request will have successful rendezvous
1335 // with the promised stream.
1336 EXPECT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
1337 callback_.callback()));
1338
1339 EXPECT_EQ(
1340 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
1341 ->id(),
1342 promise_id_);
1343
1344 // The headers will be immediately available.
1345 EXPECT_EQ(OK, promised_stream_->ReadResponseHeaders(callback_.callback()));
1346
1347 // As will be the body.
1348 EXPECT_EQ(
1349 static_cast<int>(strlen(kResponseBody)),
1350 promised_stream_->ReadResponseBody(
1351 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
1352 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
1353 EXPECT_TRUE(AtEof());
1354
1355 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1356 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1357 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
1358 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1359 strlen(kResponseBody)),
1360 promised_stream_->GetTotalReceivedBytes());
1361}
1362
1363TEST_P(QuicHttpStreamTest, ServerPushGetRequestSlowResponse) {
1364 SetRequest("GET", "/", DEFAULT_PRIORITY);
1365 Initialize();
1366
1367 // Initialize the first stream, for receiving the promise on.
1368 request_.method = "GET";
1369 request_.url = GURL("http://www.example.org/");
1370
xunjieli5fafe142016-03-23 23:32:541371 EXPECT_EQ(OK,
1372 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1373 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561374
1375 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
1376 // packet, but does it matter?
1377 ReceivePromise(promise_id_);
1378 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
1379
1380 request_.url = GURL(promise_url_);
1381
1382 // Make the second stream that will exercise the first step of the
1383 // server push rendezvous mechanism.
xunjieli5fafe142016-03-23 23:32:541384 EXPECT_EQ(OK, promised_stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1385 net_log_.bound(),
1386 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561387
1388 // Now sending a matching request will rendezvous with the promised
1389 // stream, but pending secondary validation.
1390 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
1391 headers_, &response_, callback_.callback()));
1392
1393 // Receive the promised response headers.
1394 response_headers_ = promised_response_;
1395 size_t spdy_response_headers_frame_length;
1396 ProcessPacket(InnerConstructResponseHeadersPacket(
1397 1, promise_id_, false, &spdy_response_headers_frame_length));
1398
1399 // Receive the promised response body.
1400 const char kResponseBody[] = "Hello world!";
alyssar2adf3ac2016-05-03 17:12:581401 ProcessPacket(InnerConstructDataPacket(2, promise_id_, false, kFin, 0,
1402 kResponseBody, &server_maker_));
ckrasic3865ee0f2016-02-29 22:04:561403
fdoray92e35a72016-06-10 15:54:551404 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:561405
1406 // Rendezvous should have succeeded now, so the promised stream
1407 // should point at our push stream, and we should be able read
1408 // headers and data from it.
1409 EXPECT_EQ(OK, callback_.WaitForResult());
1410
1411 EXPECT_EQ(
1412 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
1413 ->id(),
1414 promise_id_);
1415
1416 EXPECT_EQ(OK, promised_stream_->ReadResponseHeaders(callback_.callback()));
1417
1418 EXPECT_EQ(
1419 static_cast<int>(strlen(kResponseBody)),
1420 promised_stream_->ReadResponseBody(
1421 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
1422
1423 // Callback should return
1424 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
1425 EXPECT_TRUE(AtEof());
1426
1427 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1428 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1429 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
1430 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1431 strlen(kResponseBody)),
1432 promised_stream_->GetTotalReceivedBytes());
1433}
1434
1435TEST_P(QuicHttpStreamTest, ServerPushCrossOriginOK) {
1436 SetRequest("GET", "/", DEFAULT_PRIORITY);
1437 Initialize();
1438
1439 // Initialize the first stream, for receiving the promise on.
1440 request_.method = "GET";
1441 request_.url = GURL("http://www.example.org/");
1442
xunjieli5fafe142016-03-23 23:32:541443 EXPECT_EQ(OK,
1444 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1445 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561446
1447 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
1448 // packet, but does it matter?
1449
1450 push_promise_[":authority"] = "mail.example.org";
1451 promise_url_ = SpdyUtils::GetUrlFromHeaderBlock(push_promise_);
1452 serialized_push_promise_ =
1453 SpdyUtils::SerializeUncompressedHeaders(push_promise_);
1454
1455 ReceivePromise(promise_id_);
1456 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
1457
1458 request_.url = GURL(promise_url_);
1459
1460 // Make the second stream that will exercise the first step of the
1461 // server push rendezvous mechanism.
xunjieli5fafe142016-03-23 23:32:541462 EXPECT_EQ(OK, promised_stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1463 net_log_.bound(),
1464 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561465
1466 // Receive the promised response headers.
1467 response_headers_ = promised_response_;
1468 size_t spdy_response_headers_frame_length;
1469 ProcessPacket(InnerConstructResponseHeadersPacket(
1470 1, promise_id_, false, &spdy_response_headers_frame_length));
1471
1472 // Receive the promised response body.
1473 const char kResponseBody[] = "Hello world!";
alyssar2adf3ac2016-05-03 17:12:581474 ProcessPacket(InnerConstructDataPacket(2, promise_id_, false, kFin, 0,
1475 kResponseBody, &server_maker_));
ckrasic3865ee0f2016-02-29 22:04:561476
1477 // Now sending a matching request will have successful rendezvous
1478 // with the promised stream.
1479 EXPECT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
1480 callback_.callback()));
1481
1482 EXPECT_EQ(
1483 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
1484 ->id(),
1485 promise_id_);
1486
1487 // The headers will be immediately available.
1488 EXPECT_EQ(OK, promised_stream_->ReadResponseHeaders(callback_.callback()));
1489
1490 // As will be the body.
1491 EXPECT_EQ(
1492 static_cast<int>(strlen(kResponseBody)),
1493 promised_stream_->ReadResponseBody(
1494 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
1495 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
1496 EXPECT_TRUE(AtEof());
1497
1498 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1499 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1500 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
1501 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1502 strlen(kResponseBody)),
1503 promised_stream_->GetTotalReceivedBytes());
1504}
1505
1506TEST_P(QuicHttpStreamTest, ServerPushCrossOriginFail) {
1507 SetRequest("GET", "/", DEFAULT_PRIORITY);
1508 Initialize();
1509
1510 // Initialize the first stream, for receiving the promise on.
1511 request_.method = "GET";
1512 request_.url = GURL("http://www.example.org/");
1513
xunjieli5fafe142016-03-23 23:32:541514 EXPECT_EQ(OK,
1515 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1516 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561517
1518 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
1519 // packet, but does it matter?
1520 push_promise_[":authority"] = "www.notexample.org";
1521 promise_url_ = SpdyUtils::GetUrlFromHeaderBlock(push_promise_);
1522 serialized_push_promise_ =
1523 SpdyUtils::SerializeUncompressedHeaders(push_promise_);
1524
1525 ReceivePromise(promise_id_);
1526 // The promise will have been rejected because the cert doesn't
1527 // match.
1528 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
1529}
1530
1531TEST_P(QuicHttpStreamTest, ServerPushVaryCheckOK) {
1532 SetRequest("GET", "/", DEFAULT_PRIORITY);
1533 Initialize();
1534
1535 // Initialize the first stream, for receiving the promise on.
1536 request_.method = "GET";
1537 request_.url = GURL("http://www.example.org/");
1538
xunjieli5fafe142016-03-23 23:32:541539 EXPECT_EQ(OK,
1540 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1541 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561542
1543 push_promise_["accept-encoding"] = "gzip";
1544 serialized_push_promise_ =
1545 SpdyUtils::SerializeUncompressedHeaders(push_promise_);
1546
1547 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
1548 // packet, but does it matter?
1549 ReceivePromise(promise_id_);
1550 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
1551
1552 request_.url = GURL(promise_url_);
1553
1554 // Make the second stream that will exercise the first step of the
1555 // server push rendezvous mechanism.
xunjieli5fafe142016-03-23 23:32:541556 EXPECT_EQ(OK, promised_stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1557 net_log_.bound(),
1558 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561559
1560 headers_.SetHeader("accept-encoding", "gzip");
1561
1562 // Now sending a matching request will rendezvous with the promised
1563 // stream, but pending secondary validation.
1564 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
1565 headers_, &response_, callback_.callback()));
1566
1567 // Receive the promised response headers.
1568 promised_response_["vary"] = "accept-encoding";
1569 response_headers_ = promised_response_;
1570 size_t spdy_response_headers_frame_length;
1571 ProcessPacket(InnerConstructResponseHeadersPacket(
1572 1, promise_id_, false, &spdy_response_headers_frame_length));
1573
1574 // Receive the promised response body.
1575 const char kResponseBody[] = "Hello world!";
alyssar2adf3ac2016-05-03 17:12:581576 ProcessPacket(InnerConstructDataPacket(2, promise_id_, false, kFin, 0,
1577 kResponseBody, &server_maker_));
ckrasic3865ee0f2016-02-29 22:04:561578
fdoray92e35a72016-06-10 15:54:551579 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:561580
1581 // Rendezvous should have succeeded now, so the promised stream
1582 // should point at our push stream, and we should be able read
1583 // headers and data from it.
1584 EXPECT_EQ(OK, callback_.WaitForResult());
1585
1586 EXPECT_EQ(
1587 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
1588 ->id(),
1589 promise_id_);
1590
1591 EXPECT_EQ(OK, promised_stream_->ReadResponseHeaders(callback_.callback()));
1592
1593 EXPECT_EQ(
1594 static_cast<int>(strlen(kResponseBody)),
1595 promised_stream_->ReadResponseBody(
1596 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
1597
1598 // Callback should return
1599 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
1600 EXPECT_TRUE(AtEof());
1601
1602 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1603 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1604 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
1605 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1606 strlen(kResponseBody)),
1607 promised_stream_->GetTotalReceivedBytes());
1608}
1609
1610TEST_P(QuicHttpStreamTest, ServerPushVaryCheckFail) {
1611 SetRequest("GET", "/", DEFAULT_PRIORITY);
1612 request_headers_[":scheme"] = "https";
1613 request_headers_[":path"] = "/bar";
1614 request_headers_["accept-encoding"] = "sdch";
1615
1616 size_t spdy_request_header_frame_length;
alyssar2adf3ac2016-05-03 17:12:581617 AddWrite(ConstructClientRstStreamVaryMismatchPacket(1));
ckrasic3865ee0f2016-02-29 22:04:561618 AddWrite(InnerConstructRequestHeadersPacket(
1619 2, stream_id_ + 2, !kIncludeVersion, kFin, DEFAULT_PRIORITY,
1620 &spdy_request_header_frame_length));
alyssar2adf3ac2016-05-03 17:12:581621 AddWrite(ConstructClientAckPacket(3, 3, 1));
1622 AddWrite(ConstructClientRstStreamCancelledPacket(4));
ckrasic3865ee0f2016-02-29 22:04:561623 Initialize();
1624
1625 // Initialize the first stream, for receiving the promise on.
1626 request_.method = "GET";
1627 request_.url = GURL("http://www.example.org/");
1628
xunjieli5fafe142016-03-23 23:32:541629 EXPECT_EQ(OK,
1630 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1631 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561632
1633 push_promise_["accept-encoding"] = "gzip";
1634 serialized_push_promise_ =
1635 SpdyUtils::SerializeUncompressedHeaders(push_promise_);
1636
1637 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
1638 // packet, but does it matter?
1639 ReceivePromise(promise_id_);
1640 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
1641
1642 request_.url = GURL(promise_url_);
1643
1644 // Make the second stream that will exercise the first step of the
1645 // server push rendezvous mechanism.
xunjieli5fafe142016-03-23 23:32:541646 EXPECT_EQ(OK, promised_stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1647 net_log_.bound(),
1648 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561649
1650 headers_.SetHeader("accept-encoding", "sdch");
1651
1652 // Now sending a matching request will rendezvous with the promised
1653 // stream, but pending secondary validation.
1654 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
1655 headers_, &response_, callback_.callback()));
1656
1657 // Receive the promised response headers.
1658 promised_response_["vary"] = "accept-encoding";
1659 response_headers_ = promised_response_;
1660 size_t spdy_response_headers_frame_length;
1661 ProcessPacket(InnerConstructResponseHeadersPacket(
1662 1, promise_id_, false, &spdy_response_headers_frame_length));
1663
fdoray92e35a72016-06-10 15:54:551664 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:561665
1666 // Rendezvous should have failed due to vary mismatch, so the
1667 // promised stream should have been aborted, and instead we have a
1668 // new, regular client initiated stream.
1669 EXPECT_EQ(OK, callback_.WaitForResult());
1670
1671 // Not a server-initiated stream.
1672 EXPECT_NE(
1673 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
1674 ->id(),
1675 promise_id_);
1676
1677 // Instead, a new client-initiated stream.
1678 EXPECT_EQ(
1679 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
1680 ->id(),
1681 stream_id_ + 2);
1682
1683 // After rendezvous failure, the push stream has been cancelled.
1684 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
1685
1686 // The rest of the test verifies that the retried as
1687 // client-initiated version of |promised_stream_| works as intended.
1688
1689 // Ack the request.
alyssar2adf3ac2016-05-03 17:12:581690 ProcessPacket(ConstructServerAckPacket(2, 0, 0));
ckrasic3865ee0f2016-02-29 22:04:561691
bnc614a92d32016-04-04 13:56:071692 SetResponse("404 Not Found", string());
ckrasic3865ee0f2016-02-29 22:04:561693 size_t spdy_response_header_frame_length;
1694 ProcessPacket(InnerConstructResponseHeadersPacket(
1695 3, stream_id_ + 2, kFin, &spdy_response_header_frame_length));
1696
fdoray92e35a72016-06-10 15:54:551697 base::RunLoop().RunUntilIdle();
ckrasic3865ee0f2016-02-29 22:04:561698
1699 EXPECT_EQ(OK, promised_stream_->ReadResponseHeaders(callback_.callback()));
1700 ASSERT_TRUE(response_.headers.get());
1701 EXPECT_EQ(404, response_.headers->response_code());
1702 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1703 EXPECT_FALSE(response_.response_time.is_null());
1704 EXPECT_FALSE(response_.request_time.is_null());
1705
1706 // There is no body, so this should return immediately.
1707 EXPECT_EQ(
1708 0, promised_stream_->ReadResponseBody(
1709 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
1710 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
1711
1712 stream_->Close(true);
1713
1714 EXPECT_TRUE(AtEof());
1715
1716 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
1717 // headers and payload.
1718 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
1719 promised_stream_->GetTotalSentBytes());
1720 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length),
1721 promised_stream_->GetTotalReceivedBytes());
1722}
1723
[email protected]f702d572012-12-04 15:56:201724} // namespace test
[email protected]f702d572012-12-04 15:56:201725} // namespace net