blob: cafeb0cd128b5f3f4834c5a8463eb301228c113a [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
[email protected]f702d572012-12-04 15:56:209#include <vector>
10
olli.raula6df48b2a2015-11-26 07:40:2211#include "base/memory/scoped_ptr.h"
xunjieli188bd402016-03-12 00:17:2512#include "base/strings/string_number_conversions.h"
skyostil4891b25b2015-06-11 11:43:4513#include "base/thread_task_runner_handle.h"
mmenkecbc2b712014-10-09 20:29:0714#include "net/base/chunked_upload_data_stream.h"
15#include "net/base/elements_upload_data_stream.h"
[email protected]f702d572012-12-04 15:56:2016#include "net/base/net_errors.h"
tbansalfdf5665b2015-09-21 22:46:4017#include "net/base/socket_performance_watcher.h"
[email protected]f702d572012-12-04 15:56:2018#include "net/base/test_completion_callback.h"
rch03b7a202016-02-05 00:54:2019#include "net/base/test_data_directory.h"
[email protected]b2d26cfd2012-12-11 10:36:0620#include "net/base/upload_bytes_element_reader.h"
[email protected]f702d572012-12-04 15:56:2021#include "net/http/http_response_headers.h"
[email protected]5db452202014-08-19 05:22:1522#include "net/http/transport_security_state.h"
xunjieli5fafe142016-03-23 23:32:5423#include "net/log/test_net_log.h"
24#include "net/log/test_net_log_util.h"
[email protected]fee17f72013-02-03 07:47:4125#include "net/quic/congestion_control/send_algorithm_interface.h"
[email protected]e8ff26842013-03-22 21:02:0526#include "net/quic/crypto/crypto_protocol.h"
rch03b7a202016-02-05 00:54:2027#include "net/quic/crypto/proof_verifier_chromium.h"
[email protected]4df69842013-02-27 06:32:1628#include "net/quic/crypto/quic_decrypter.h"
29#include "net/quic/crypto/quic_encrypter.h"
[email protected]17bf15c2014-03-14 10:08:0430#include "net/quic/crypto/quic_server_info.h"
ckrasic4f9d88d2015-07-22 22:23:1631#include "net/quic/quic_chromium_client_session.h"
rch12fef552016-01-15 16:26:3132#include "net/quic/quic_chromium_client_stream.h"
33#include "net/quic/quic_chromium_connection_helper.h"
rcha02807b42016-01-29 21:56:1534#include "net/quic/quic_chromium_packet_reader.h"
35#include "net/quic/quic_chromium_packet_writer.h"
[email protected]f702d572012-12-04 15:56:2036#include "net/quic/quic_connection.h"
[email protected]24e5bc52013-09-18 15:36:5837#include "net/quic/quic_http_utils.h"
[email protected]9f0dcd4e2014-01-16 15:58:1438#include "net/quic/quic_write_blocked_list.h"
[email protected]3e7dca62013-09-10 16:14:2339#include "net/quic/spdy_utils.h"
rch1fe2eeb2015-10-26 14:45:5740#include "net/quic/test_tools/crypto_test_utils.h"
[email protected]f702d572012-12-04 15:56:2041#include "net/quic/test_tools/mock_clock.h"
[email protected]e8ff26842013-03-22 21:02:0542#include "net/quic/test_tools/mock_crypto_client_stream_factory.h"
[email protected]9db443912013-02-25 05:27:0343#include "net/quic/test_tools/mock_random.h"
[email protected]b1f287d2012-12-22 17:25:3944#include "net/quic/test_tools/quic_connection_peer.h"
[email protected]1e960032013-12-20 19:00:2045#include "net/quic/test_tools/quic_test_packet_maker.h"
[email protected]f702d572012-12-04 15:56:2046#include "net/quic/test_tools/quic_test_utils.h"
47#include "net/quic/test_tools/test_task_runner.h"
48#include "net/socket/socket_test_util.h"
[email protected]6cca996b2013-01-25 07:43:3649#include "net/spdy/spdy_frame_builder.h"
50#include "net/spdy/spdy_framer.h"
51#include "net/spdy/spdy_http_utils.h"
52#include "net/spdy/spdy_protocol.h"
rch03b7a202016-02-05 00:54:2053#include "net/test/cert_test_util.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
57using testing::_;
[email protected]06ff5152013-08-29 01:03:0558using testing::AnyNumber;
59using testing::Return;
[email protected]f702d572012-12-04 15:56:2060
61namespace net {
[email protected]f702d572012-12-04 15:56:2062namespace test {
[email protected]f702d572012-12-04 15:56:2063namespace {
64
[email protected]16ba7742014-08-22 00:57:2565const char kUploadData[] = "Really nifty data!";
rch9ae5b3b2016-02-11 00:36:2966const char kDefaultServerHostName[] = "www.example.org";
Avi Drissman13fc8932015-12-20 04:40:4667const uint16_t kDefaultServerPort = 80;
[email protected]f702d572012-12-04 15:56:2068
69class TestQuicConnection : public QuicConnection {
70 public:
[email protected]1e960032013-12-20 19:00:2071 TestQuicConnection(const QuicVersionVector& versions,
[email protected]3aa9ca72014-02-27 19:39:4372 QuicConnectionId connection_id,
[email protected]f702d572012-12-04 15:56:2073 IPEndPoint address,
rch12fef552016-01-15 16:26:3174 QuicChromiumConnectionHelper* helper,
jdorfman90d185f32016-01-15 13:22:4775 QuicPacketWriter* writer)
[email protected]66cd2d62014-08-01 18:42:3976 : QuicConnection(connection_id,
77 address,
78 helper,
jdorfman90d185f32016-01-15 13:22:4779 writer,
rtenneti6f48aa92015-03-16 02:18:4880 true /* owns_writer */,
81 Perspective::IS_CLIENT,
rtenneti6f48aa92015-03-16 02:18:4882 versions) {}
[email protected]f702d572012-12-04 15:56:2083
[email protected]fee17f72013-02-03 07:47:4184 void SetSendAlgorithm(SendAlgorithmInterface* send_algorithm) {
85 QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
[email protected]f702d572012-12-04 15:56:2086 }
87};
88
[email protected]63534512012-12-23 18:49:0089// Subclass of QuicHttpStream that closes itself when the first piece of data
90// is received.
91class AutoClosingStream : public QuicHttpStream {
92 public:
ckrasic4f9d88d2015-07-22 22:23:1693 explicit AutoClosingStream(
94 const base::WeakPtr<QuicChromiumClientSession>& session)
95 : QuicHttpStream(session) {}
[email protected]63534512012-12-23 18:49:0096
sclittlec4dc1a32015-09-24 00:15:4597 void OnHeadersAvailable(const SpdyHeaderBlock& headers,
98 size_t frame_len) override {
[email protected]63534512012-12-23 18:49:0099 Close(false);
[email protected]63534512012-12-23 18:49:00100 }
rchb27683c2015-07-29 23:53:50101
102 void OnDataAvailable() override { Close(false); }
[email protected]63534512012-12-23 18:49:00103};
104
[email protected]f702d572012-12-04 15:56:20105} // namespace
106
[email protected]24e5bc52013-09-18 15:36:58107class QuicHttpStreamPeer {
108 public:
rch12fef552016-01-15 16:26:31109 static QuicChromiumClientStream* GetQuicChromiumClientStream(
[email protected]24e5bc52013-09-18 15:36:58110 QuicHttpStream* stream) {
111 return stream->stream_;
112 }
zhongyica364fbb2015-12-12 03:39:12113
114 static bool WasHandshakeConfirmed(QuicHttpStream* stream) {
115 return stream->was_handshake_confirmed_;
116 }
117
118 static void SetHandshakeConfirmed(QuicHttpStream* stream, bool confirmed) {
119 stream->was_handshake_confirmed_ = confirmed;
120 }
[email protected]24e5bc52013-09-18 15:36:58121};
122
[email protected]1e960032013-12-20 19:00:20123class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
[email protected]f702d572012-12-04 15:56:20124 protected:
[email protected]1e960032013-12-20 19:00:20125 static const bool kFin = true;
126 static const bool kIncludeVersion = true;
127 static const bool kIncludeCongestionFeedback = true;
128
[email protected]f702d572012-12-04 15:56:20129 // Holds a packet to be written to the wire, and the IO mode that should
130 // be used by the mock socket when performing the write.
131 struct PacketToWrite {
132 PacketToWrite(IoMode mode, QuicEncryptedPacket* packet)
rjshaded5ced072015-12-18 19:26:02133 : mode(mode), packet(packet) {}
rtenneti15656ae2016-01-23 03:05:03134 PacketToWrite(IoMode mode, int rv) : mode(mode), packet(nullptr), rv(rv) {}
[email protected]f702d572012-12-04 15:56:20135 IoMode mode;
136 QuicEncryptedPacket* packet;
rtenneti15656ae2016-01-23 03:05:03137 int rv;
[email protected]f702d572012-12-04 15:56:20138 };
139
140 QuicHttpStreamTest()
xunjieli5fafe142016-03-23 23:32:54141 : use_closing_stream_(false),
rch1fe2eeb2015-10-26 14:45:57142 crypto_config_(CryptoTestUtils::ProofVerifierForTesting()),
[email protected]f702d572012-12-04 15:56:20143 read_buffer_(new IOBufferWithSize(4096)),
ckrasic3865ee0f2016-02-29 22:04:56144 promise_id_(kServerDataStreamId1),
[email protected]66ae5962014-05-22 11:13:05145 stream_id_(kClientDataStreamId1),
ckrasic3865ee0f2016-02-29 22:04:56146 connection_id_(2),
bncb07c05532015-05-14 19:07:20147 maker_(GetParam(), connection_id_, &clock_, kDefaultServerHostName),
ckrasic3865ee0f2016-02-29 22:04:56148 random_generator_(0),
149 response_offset_(0) {
martijn21968ea2016-02-24 18:46:20150 IPAddress ip(192, 0, 2, 33);
[email protected]f702d572012-12-04 15:56:20151 peer_addr_ = IPEndPoint(ip, 443);
152 self_addr_ = IPEndPoint(ip, 8435);
rtenneti4b06ae72014-08-26 03:43:43153 clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(20));
[email protected]f702d572012-12-04 15:56:20154 }
155
156 ~QuicHttpStreamTest() {
rtenneti85dcfac22015-03-27 20:22:19157 session_->CloseSessionOnError(ERR_ABORTED, QUIC_INTERNAL_ERROR);
[email protected]f702d572012-12-04 15:56:20158 for (size_t i = 0; i < writes_.size(); i++) {
159 delete writes_[i].packet;
160 }
161 }
162
163 // Adds a packet to the list of expected writes.
[email protected]1e960032013-12-20 19:00:20164 void AddWrite(scoped_ptr<QuicEncryptedPacket> packet) {
165 writes_.push_back(PacketToWrite(SYNCHRONOUS, packet.release()));
[email protected]f702d572012-12-04 15:56:20166 }
167
rtenneti15656ae2016-01-23 03:05:03168 void AddWrite(IoMode mode, int rv) {
169 writes_.push_back(PacketToWrite(mode, rv));
170 }
171
[email protected]f702d572012-12-04 15:56:20172 // Returns the packet to be written at position |pos|.
rjshaded5ced072015-12-18 19:26:02173 QuicEncryptedPacket* GetWrite(size_t pos) { return writes_[pos].packet; }
[email protected]f702d572012-12-04 15:56:20174
175 bool AtEof() {
rch37de576c2015-05-17 20:28:17176 return socket_data_->AllReadDataConsumed() &&
177 socket_data_->AllWriteDataConsumed();
[email protected]f702d572012-12-04 15:56:20178 }
179
[email protected]1e960032013-12-20 19:00:20180 void ProcessPacket(scoped_ptr<QuicEncryptedPacket> packet) {
181 connection_->ProcessUdpPacket(self_addr_, peer_addr_, *packet);
[email protected]f702d572012-12-04 15:56:20182 }
183
184 // Configures the test fixture to use the list of expected writes.
185 void Initialize() {
186 mock_writes_.reset(new MockWrite[writes_.size()]);
187 for (size_t i = 0; i < writes_.size(); i++) {
rtenneti15656ae2016-01-23 03:05:03188 if (writes_[i].packet == nullptr) {
189 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].rv, i);
190 } else {
191 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].packet->data(),
192 writes_[i].packet->length());
193 }
[email protected]f702d572012-12-04 15:56:20194 };
195
rtennetibe635732014-10-02 22:51:42196 socket_data_.reset(new StaticSocketDataProvider(
197 nullptr, 0, mock_writes_.get(), writes_.size()));
[email protected]f702d572012-12-04 15:56:20198
rjshaded5ced072015-12-18 19:26:02199 MockUDPClientSocket* socket =
xunjieli5fafe142016-03-23 23:32:54200 new MockUDPClientSocket(socket_data_.get(), net_log_.bound().net_log());
[email protected]e13201d82012-12-12 05:00:32201 socket->Connect(peer_addr_);
[email protected]f702d572012-12-04 15:56:20202 runner_ = new TestTaskRunner(&clock_);
[email protected]fee17f72013-02-03 07:47:41203 send_algorithm_ = new MockSendAlgorithm();
rch7dd15702015-07-01 18:57:57204 EXPECT_CALL(*send_algorithm_, InRecovery()).WillRepeatedly(Return(false));
205 EXPECT_CALL(*send_algorithm_, InSlowStart()).WillRepeatedly(Return(false));
rjshaded5ced072015-12-18 19:26:02206 EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
207 .WillRepeatedly(Return(true));
rtenneti44f4a2e2015-08-07 14:00:07208 EXPECT_CALL(*send_algorithm_, RetransmissionDelay())
209 .WillRepeatedly(Return(QuicTime::Delta::Zero()));
210 EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
211 .WillRepeatedly(Return(kMaxPacketSize));
212 EXPECT_CALL(*send_algorithm_, PacingRate())
213 .WillRepeatedly(Return(QuicBandwidth::Zero()));
fnkf57804c2016-03-17 20:57:07214 EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
rtenneti44f4a2e2015-08-07 14:00:07215 .WillRepeatedly(Return(QuicTime::Delta::Zero()));
216 EXPECT_CALL(*send_algorithm_, BandwidthEstimate())
217 .WillRepeatedly(Return(QuicBandwidth::Zero()));
rch1e543ec2015-03-29 07:04:40218 EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(AnyNumber());
rch12fef552016-01-15 16:26:31219 helper_.reset(new QuicChromiumConnectionHelper(runner_.get(), &clock_,
220 &random_generator_));
jdorfman90d185f32016-01-15 13:22:47221 connection_ = new TestQuicConnection(
222 SupportedVersions(GetParam()), connection_id_, peer_addr_,
rcha02807b42016-01-29 21:56:15223 helper_.get(), new QuicChromiumPacketWriter(socket));
[email protected]f702d572012-12-04 15:56:20224 connection_->set_visitor(&visitor_);
[email protected]fee17f72013-02-03 07:47:41225 connection_->SetSendAlgorithm(send_algorithm_);
rch03b7a202016-02-05 00:54:20226
227 // Load a certificate that is valid for *.example.org
228 scoped_refptr<X509Certificate> test_cert(
229 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
230 EXPECT_TRUE(test_cert.get());
231
232 verify_details_.cert_verify_result.verified_cert = test_cert;
233 verify_details_.cert_verify_result.is_issued_by_known_root = true;
234 crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details_);
235
ckrasic4f9d88d2015-07-22 22:23:16236 session_.reset(new QuicChromiumClientSession(
rtennetid39bd762015-06-12 01:05:52237 connection_, scoped_ptr<DatagramClientSocket>(socket),
rtenneti1cd3b162015-09-29 02:58:28238 /*stream_factory=*/nullptr, &crypto_client_stream_factory_, &clock_,
rch68b32a82016-02-09 22:12:21239 &transport_security_state_, make_scoped_ptr((QuicServerInfo*)nullptr),
bncb07c05532015-05-14 19:07:20240 QuicServerId(kDefaultServerHostName, kDefaultServerPort,
rch1fe2eeb2015-10-26 14:45:57241 PRIVACY_MODE_DISABLED),
rtenneti1cd3b162015-09-29 02:58:28242 kQuicYieldAfterPacketsRead,
243 QuicTime::Delta::FromMilliseconds(kQuicYieldAfterDurationMilliseconds),
rtennetia75df622015-06-21 23:59:50244 /*cert_verify_flags=*/0, DefaultQuicConfig(), &crypto_config_,
ckrasic244375a32016-02-04 21:21:22245 "CONNECTION_UNKNOWN", base::TimeTicks::Now(), &push_promise_index_,
tbansalfdf5665b2015-09-21 22:46:40246 base::ThreadTaskRunnerHandle::Get().get(),
xunjieli5fafe142016-03-23 23:32:54247 /*socket_performance_watcher=*/nullptr, net_log_.bound().net_log()));
rtennetid39bd762015-06-12 01:05:52248 session_->Initialize();
[email protected]ed3fc15d2013-03-08 18:37:44249 session_->GetCryptoStream()->CryptoConnect();
[email protected]8ba81212013-05-03 13:11:48250 EXPECT_TRUE(session_->IsCryptoHandshakeConfirmed());
rjshaded5ced072015-12-18 19:26:02251 stream_.reset(use_closing_stream_
252 ? new AutoClosingStream(session_->GetWeakPtr())
253 : new QuicHttpStream(session_->GetWeakPtr()));
ckrasic3865ee0f2016-02-29 22:04:56254
255 promised_stream_.reset(use_closing_stream_
256 ? new AutoClosingStream(session_->GetWeakPtr())
257 : new QuicHttpStream(session_->GetWeakPtr()));
258
259 push_promise_[":path"] = "/bar";
260 push_promise_[":authority"] = "www.example.org";
261 push_promise_[":version"] = "HTTP/1.1";
262 push_promise_[":method"] = "GET";
263 push_promise_[":scheme"] = "https";
264
265 promised_response_[":status"] = "200 OK";
266 promised_response_[":version"] = "HTTP/1.1";
267 promised_response_["content-type"] = "text/plain";
268
269 promise_url_ = SpdyUtils::GetUrlFromHeaderBlock(push_promise_);
270
271 serialized_push_promise_ =
272 SpdyUtils::SerializeUncompressedHeaders(push_promise_);
[email protected]6cca996b2013-01-25 07:43:36273 }
274
[email protected]1e960032013-12-20 19:00:20275 void SetRequest(const std::string& method,
276 const std::string& path,
277 RequestPriority priority) {
278 request_headers_ = maker_.GetRequestHeaders(method, "http", path);
[email protected]6cca996b2013-01-25 07:43:36279 }
280
[email protected]1e960032013-12-20 19:00:20281 void SetResponse(const std::string& status, const std::string& body) {
282 response_headers_ = maker_.GetResponseHeaders(status);
[email protected]92bf17c2014-03-03 21:14:03283 response_data_ = body;
[email protected]6cca996b2013-01-25 07:43:36284 }
[email protected]f702d572012-12-04 15:56:20285
ckrasic3865ee0f2016-02-29 22:04:56286 scoped_ptr<QuicEncryptedPacket> InnerConstructDataPacket(
287 QuicPacketNumber packet_number,
288 QuicStreamId stream_id,
289 bool should_include_version,
290 bool fin,
291 QuicStreamOffset offset,
292 base::StringPiece data) {
293 return maker_.MakeDataPacket(packet_number, stream_id,
294 should_include_version, fin, offset, data);
295 }
296
[email protected]1e960032013-12-20 19:00:20297 scoped_ptr<QuicEncryptedPacket> ConstructDataPacket(
rtennetia004d332015-08-28 06:44:57298 QuicPacketNumber packet_number,
[email protected]e8ff26842013-03-22 21:02:05299 bool should_include_version,
[email protected]f702d572012-12-04 15:56:20300 bool fin,
301 QuicStreamOffset offset,
302 base::StringPiece data) {
ckrasic3865ee0f2016-02-29 22:04:56303 return InnerConstructDataPacket(packet_number, stream_id_,
304 should_include_version, fin, offset, data);
305 }
306
307 scoped_ptr<QuicEncryptedPacket> InnerConstructRequestHeadersPacket(
308 QuicPacketNumber packet_number,
309 QuicStreamId stream_id,
310 bool should_include_version,
311 bool fin,
312 RequestPriority request_priority,
313 size_t* spdy_headers_frame_length) {
314 SpdyPriority priority =
315 ConvertRequestPriorityToQuicPriority(request_priority);
316 return maker_.MakeRequestHeadersPacket(
317 packet_number, stream_id, should_include_version, fin, priority,
318 request_headers_, spdy_headers_frame_length);
[email protected]f702d572012-12-04 15:56:20319 }
320
[email protected]1e960032013-12-20 19:00:20321 scoped_ptr<QuicEncryptedPacket> ConstructRequestHeadersPacket(
rtennetia004d332015-08-28 06:44:57322 QuicPacketNumber packet_number,
rtennetif4bdb542015-01-21 14:33:05323 bool fin,
sclittlec4dc1a32015-09-24 00:15:45324 RequestPriority request_priority,
325 size_t* spdy_headers_frame_length) {
ckrasic3865ee0f2016-02-29 22:04:56326 return InnerConstructRequestHeadersPacket(
327 packet_number, stream_id_, kIncludeVersion, fin, request_priority,
328 spdy_headers_frame_length);
329 }
330
331 scoped_ptr<QuicEncryptedPacket> InnerConstructResponseHeadersPacket(
332 QuicPacketNumber packet_number,
333 QuicStreamId stream_id,
334 bool fin,
335 size_t* spdy_headers_frame_length) {
336 return maker_.MakeResponseHeadersPacket(
337 packet_number, stream_id, !kIncludeVersion, fin, response_headers_,
338 spdy_headers_frame_length, &response_offset_);
[email protected]1e960032013-12-20 19:00:20339 }
340
341 scoped_ptr<QuicEncryptedPacket> ConstructResponseHeadersPacket(
rtennetia004d332015-08-28 06:44:57342 QuicPacketNumber packet_number,
sclittlec4dc1a32015-09-24 00:15:45343 bool fin,
344 size_t* spdy_headers_frame_length) {
ckrasic3865ee0f2016-02-29 22:04:56345 return InnerConstructResponseHeadersPacket(packet_number, stream_id_, fin,
346 spdy_headers_frame_length);
[email protected]1e960032013-12-20 19:00:20347 }
348
xunjieli34291fe12016-03-02 13:58:38349 scoped_ptr<QuicEncryptedPacket> ConstructResponseHeadersPacketWithOffset(
350 QuicPacketNumber packet_number,
351 bool fin,
352 size_t* spdy_headers_frame_length,
353 QuicStreamOffset* offset) {
354 return maker_.MakeResponseHeadersPacket(
355 packet_number, stream_id_, !kIncludeVersion, fin, response_headers_,
356 spdy_headers_frame_length, offset);
357 }
358
359 scoped_ptr<QuicEncryptedPacket> ConstructResponseTrailersPacket(
360 QuicPacketNumber packet_number,
361 bool fin,
362 const SpdyHeaderBlock& trailers,
363 size_t* spdy_headers_frame_length,
364 QuicStreamOffset* offset) {
365 return maker_.MakeResponseHeadersPacket(packet_number, stream_id_,
366 !kIncludeVersion, fin, trailers,
367 spdy_headers_frame_length, offset);
368 }
369
[email protected]1e960032013-12-20 19:00:20370 scoped_ptr<QuicEncryptedPacket> ConstructRstStreamPacket(
rtennetia004d332015-08-28 06:44:57371 QuicPacketNumber packet_number) {
[email protected]1e960032013-12-20 19:00:20372 return maker_.MakeRstPacket(
rtennetia004d332015-08-28 06:44:57373 packet_number, true, stream_id_,
rtenneti4a5df262014-11-07 00:43:58374 AdjustErrorForVersion(QUIC_RST_ACKNOWLEDGEMENT, GetParam()));
[email protected]06ff5152013-08-29 01:03:05375 }
376
rtenneti6bd660b2015-07-18 00:19:53377 scoped_ptr<QuicEncryptedPacket> ConstructRstStreamCancelledPacket(
rtennetia004d332015-08-28 06:44:57378 QuicPacketNumber packet_number) {
379 return maker_.MakeRstPacket(packet_number, !kIncludeVersion, stream_id_,
rtenneti6bd660b2015-07-18 00:19:53380 QUIC_STREAM_CANCELLED);
381 }
382
ckrasic3865ee0f2016-02-29 22:04:56383 scoped_ptr<QuicEncryptedPacket> ConstructRstStreamVaryMismatchPacket(
384 QuicPacketNumber packet_number) {
385 return maker_.MakeRstPacket(packet_number, !kIncludeVersion, promise_id_,
386 QUIC_PROMISE_VARY_MISMATCH);
387 }
388
[email protected]c5e1aca2014-01-30 04:03:04389 scoped_ptr<QuicEncryptedPacket> ConstructAckAndRstStreamPacket(
xunjieli34291fe12016-03-02 13:58:38390 QuicPacketNumber packet_number,
391 QuicPacketNumber largest_received,
392 QuicPacketNumber ack_least_unacked,
393 QuicPacketNumber stop_least_unacked) {
394 return maker_.MakeAckAndRstPacket(
395 packet_number, !kIncludeVersion, stream_id_, QUIC_STREAM_CANCELLED,
396 largest_received, ack_least_unacked, stop_least_unacked,
397 !kIncludeCongestionFeedback);
398 }
399
400 scoped_ptr<QuicEncryptedPacket> ConstructAckAndRstStreamPacket(
rtennetia004d332015-08-28 06:44:57401 QuicPacketNumber packet_number) {
xunjieli34291fe12016-03-02 13:58:38402 return ConstructAckAndRstStreamPacket(packet_number, 2, 1, 1);
[email protected]c5e1aca2014-01-30 04:03:04403 }
404
[email protected]1e960032013-12-20 19:00:20405 scoped_ptr<QuicEncryptedPacket> ConstructAckPacket(
rtennetia004d332015-08-28 06:44:57406 QuicPacketNumber packet_number,
407 QuicPacketNumber largest_received,
408 QuicPacketNumber least_unacked) {
409 return maker_.MakeAckPacket(packet_number, largest_received, least_unacked,
410 !kIncludeCongestionFeedback);
[email protected]63534512012-12-23 18:49:00411 }
412
ckrasic3865ee0f2016-02-29 22:04:56413 void ReceivePromise(QuicStreamId id) {
414 QuicChromiumClientStream* stream =
415 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
416 stream->OnStreamHeaders(serialized_push_promise_);
417
418 stream->OnPromiseHeadersComplete(id, serialized_push_promise_.size());
419 }
420
xunjieli5fafe142016-03-23 23:32:54421 BoundTestNetLog net_log_;
[email protected]63534512012-12-23 18:49:00422 bool use_closing_stream_;
[email protected]fee17f72013-02-03 07:47:41423 MockSendAlgorithm* send_algorithm_;
[email protected]f702d572012-12-04 15:56:20424 scoped_refptr<TestTaskRunner> runner_;
[email protected]4356f0f2013-04-07 00:58:17425 scoped_ptr<MockWrite[]> mock_writes_;
[email protected]f702d572012-12-04 15:56:20426 MockClock clock_;
427 TestQuicConnection* connection_;
rch12fef552016-01-15 16:26:31428 scoped_ptr<QuicChromiumConnectionHelper> helper_;
[email protected]f702d572012-12-04 15:56:20429 testing::StrictMock<MockConnectionVisitor> visitor_;
430 scoped_ptr<QuicHttpStream> stream_;
[email protected]5db452202014-08-19 05:22:15431 TransportSecurityState transport_security_state_;
ckrasic4f9d88d2015-07-22 22:23:16432 scoped_ptr<QuicChromiumClientSession> session_;
[email protected]ef95114d2013-04-17 17:57:01433 QuicCryptoClientConfig crypto_config_;
[email protected]f702d572012-12-04 15:56:20434 TestCompletionCallback callback_;
435 HttpRequestInfo request_;
436 HttpRequestHeaders headers_;
437 HttpResponseInfo response_;
438 scoped_refptr<IOBufferWithSize> read_buffer_;
[email protected]1e960032013-12-20 19:00:20439 SpdyHeaderBlock request_headers_;
440 SpdyHeaderBlock response_headers_;
[email protected]6cca996b2013-01-25 07:43:36441 std::string request_data_;
442 std::string response_data_;
ckrasic244375a32016-02-04 21:21:22443 QuicClientPushPromiseIndex push_promise_index_;
[email protected]f702d572012-12-04 15:56:20444
ckrasic3865ee0f2016-02-29 22:04:56445 // For server push testing
446 scoped_ptr<QuicHttpStream> promised_stream_;
447 SpdyHeaderBlock push_promise_;
448 SpdyHeaderBlock promised_response_;
449 const QuicStreamId promise_id_;
450 string promise_url_;
451 string serialized_push_promise_;
452 const QuicStreamId stream_id_;
453
[email protected]f702d572012-12-04 15:56:20454 private:
[email protected]3aa9ca72014-02-27 19:39:43455 const QuicConnectionId connection_id_;
[email protected]1e960032013-12-20 19:00:20456 QuicTestPacketMaker maker_;
[email protected]f702d572012-12-04 15:56:20457 IPEndPoint self_addr_;
458 IPEndPoint peer_addr_;
[email protected]457d6952013-12-13 09:24:58459 MockRandom random_generator_;
rch03b7a202016-02-05 00:54:20460 ProofVerifyDetailsChromium verify_details_;
[email protected]e8ff26842013-03-22 21:02:05461 MockCryptoClientStreamFactory crypto_client_stream_factory_;
[email protected]f702d572012-12-04 15:56:20462 scoped_ptr<StaticSocketDataProvider> socket_data_;
463 std::vector<PacketToWrite> writes_;
ckrasic3865ee0f2016-02-29 22:04:56464 QuicStreamOffset response_offset_;
[email protected]f702d572012-12-04 15:56:20465};
466
rjshaded5ced072015-12-18 19:26:02467INSTANTIATE_TEST_CASE_P(Version,
468 QuicHttpStreamTest,
[email protected]1e960032013-12-20 19:00:20469 ::testing::ValuesIn(QuicSupportedVersions()));
470
471TEST_P(QuicHttpStreamTest, RenewStreamForAuth) {
[email protected]ed3fc15d2013-03-08 18:37:44472 Initialize();
rtennetibe635732014-10-02 22:51:42473 EXPECT_EQ(nullptr, stream_->RenewStreamForAuth());
[email protected]f702d572012-12-04 15:56:20474}
475
mmenkebd84c392015-09-02 14:12:34476TEST_P(QuicHttpStreamTest, CanReuseConnection) {
[email protected]ed3fc15d2013-03-08 18:37:44477 Initialize();
mmenkebd84c392015-09-02 14:12:34478 EXPECT_FALSE(stream_->CanReuseConnection());
[email protected]f702d572012-12-04 15:56:20479}
480
jri231c2972016-03-08 19:50:11481TEST_P(QuicHttpStreamTest, DisableConnectionMigrationForStream) {
482 request_.load_flags |= LOAD_DISABLE_CONNECTION_MIGRATION;
483 Initialize();
xunjieli5fafe142016-03-23 23:32:54484 EXPECT_EQ(OK,
485 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
486 net_log_.bound(), callback_.callback()));
jri231c2972016-03-08 19:50:11487 QuicChromiumClientStream* client_stream =
488 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
489 EXPECT_FALSE(client_stream->can_migrate());
490}
491
[email protected]1e960032013-12-20 19:00:20492TEST_P(QuicHttpStreamTest, GetRequest) {
493 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:45494 size_t spdy_request_header_frame_length;
495 AddWrite(ConstructRequestHeadersPacket(1, kFin, DEFAULT_PRIORITY,
496 &spdy_request_header_frame_length));
[email protected]f702d572012-12-04 15:56:20497 Initialize();
498
499 request_.method = "GET";
rch9ae5b3b2016-02-11 00:36:29500 request_.url = GURL("http://www.example.org/");
[email protected]f702d572012-12-04 15:56:20501
xunjieli5fafe142016-03-23 23:32:54502 EXPECT_EQ(OK,
503 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
504 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:02505 EXPECT_EQ(OK,
506 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20507
508 // Ack the request.
[email protected]1e960032013-12-20 19:00:20509 ProcessPacket(ConstructAckPacket(1, 0, 0));
[email protected]f702d572012-12-04 15:56:20510
rjshaded5ced072015-12-18 19:26:02511 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadResponseHeaders(callback_.callback()));
[email protected]f702d572012-12-04 15:56:20512
[email protected]1e960032013-12-20 19:00:20513 SetResponse("404 Not Found", std::string());
sclittlec4dc1a32015-09-24 00:15:45514 size_t spdy_response_header_frame_length;
515 ProcessPacket(ConstructResponseHeadersPacket(
516 2, kFin, &spdy_response_header_frame_length));
[email protected]f702d572012-12-04 15:56:20517
518 // Now that the headers have been processed, the callback will return.
519 EXPECT_EQ(OK, callback_.WaitForResult());
[email protected]cadac622013-06-11 16:46:36520 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:20521 EXPECT_EQ(404, response_.headers->response_code());
522 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
[email protected]6ed67432014-06-24 01:53:53523 EXPECT_FALSE(response_.response_time.is_null());
524 EXPECT_FALSE(response_.request_time.is_null());
[email protected]f702d572012-12-04 15:56:20525
526 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:02527 EXPECT_EQ(0,
528 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
529 callback_.callback()));
[email protected]f702d572012-12-04 15:56:20530 EXPECT_TRUE(stream_->IsResponseBodyComplete());
531 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:10532
533 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:45534 // headers and payload.
535 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
536 stream_->GetTotalSentBytes());
537 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length),
538 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:20539}
540
xunjieli34291fe12016-03-02 13:58:38541// QuicHttpStream does not currently support trailers. It should ignore
542// trailers upon receiving them.
543TEST_P(QuicHttpStreamTest, GetRequestWithTrailers) {
544 SetRequest("GET", "/", DEFAULT_PRIORITY);
545 size_t spdy_request_header_frame_length;
546 AddWrite(ConstructRequestHeadersPacket(1, kFin, DEFAULT_PRIORITY,
547 &spdy_request_header_frame_length));
548 AddWrite(ConstructAckPacket(2, 3, 1)); // Ack the data packet.
549
550 Initialize();
551
552 request_.method = "GET";
553 request_.url = GURL("http://www.example.org/");
554
xunjieli5fafe142016-03-23 23:32:54555 EXPECT_EQ(OK,
556 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
557 net_log_.bound(), callback_.callback()));
558
xunjieli34291fe12016-03-02 13:58:38559 EXPECT_EQ(OK,
560 stream_->SendRequest(headers_, &response_, callback_.callback()));
561
562 // Ack the request.
563 ProcessPacket(ConstructAckPacket(1, 0, 0));
564
565 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadResponseHeaders(callback_.callback()));
566
567 SetResponse("200 OK", std::string());
568
569 // Send the response headers.
570 size_t spdy_response_header_frame_length;
571 QuicStreamOffset offset = 0;
572 ProcessPacket(ConstructResponseHeadersPacketWithOffset(
573 2, !kFin, &spdy_response_header_frame_length, &offset));
574 // Now that the headers have been processed, the callback will return.
575 EXPECT_EQ(OK, callback_.WaitForResult());
576 ASSERT_TRUE(response_.headers.get());
577 EXPECT_EQ(200, response_.headers->response_code());
578 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
579 EXPECT_FALSE(response_.response_time.is_null());
580 EXPECT_FALSE(response_.request_time.is_null());
581
582 // Send the response body.
583 const char kResponseBody[] = "Hello world!";
584 ProcessPacket(
585 ConstructDataPacket(3, false, !kFin, /*offset=*/0, kResponseBody));
586 SpdyHeaderBlock trailers;
587 size_t spdy_trailers_frame_length;
588 trailers["foo"] = "bar";
xunjieli188bd402016-03-12 00:17:25589 trailers[kFinalOffsetHeaderKey] = base::IntToString(strlen(kResponseBody));
xunjieli34291fe12016-03-02 13:58:38590 ProcessPacket(ConstructResponseTrailersPacket(
591 4, kFin, trailers, &spdy_trailers_frame_length, &offset));
592
593 // Make sure trailers are processed.
594 base::MessageLoop::current()->RunUntilIdle();
595
596 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
597 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
598 callback_.callback()));
599 EXPECT_TRUE(stream_->IsResponseBodyComplete());
600
601 EXPECT_EQ(OK,
602 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
603 callback_.callback()));
604
605 EXPECT_TRUE(stream_->IsResponseBodyComplete());
606 EXPECT_TRUE(AtEof());
607
608 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
609 // headers and payload.
610 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
611 stream_->GetTotalSentBytes());
612 EXPECT_EQ(
613 static_cast<int64_t>(spdy_response_header_frame_length +
614 strlen(kResponseBody) + +spdy_trailers_frame_length),
615 stream_->GetTotalReceivedBytes());
xunjieli5fafe142016-03-23 23:32:54616 // Check that NetLog was filled as expected.
617 TestNetLogEntry::List entries;
618 net_log_.GetEntries(&entries);
619 size_t pos = ExpectLogContainsSomewhere(
620 entries, /*min_offset=*/0,
621 NetLog::TYPE_QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
622 NetLog::PHASE_NONE);
623 pos = ExpectLogContainsSomewhere(
624 entries, /*min_offset=*/pos,
625 NetLog::TYPE_QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
626 NetLog::PHASE_NONE);
627 ExpectLogContainsSomewhere(
628 entries, /*min_offset=*/pos,
629 NetLog::TYPE_QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
630 NetLog::PHASE_NONE);
xunjieli34291fe12016-03-02 13:58:38631}
632
[email protected]3e7dca62013-09-10 16:14:23633// Regression test for http://crbug.com/288128
[email protected]1e960032013-12-20 19:00:20634TEST_P(QuicHttpStreamTest, GetRequestLargeResponse) {
635 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:45636 size_t spdy_request_headers_frame_length;
637 AddWrite(ConstructRequestHeadersPacket(1, kFin, DEFAULT_PRIORITY,
638 &spdy_request_headers_frame_length));
[email protected]3e7dca62013-09-10 16:14:23639 Initialize();
640
641 request_.method = "GET";
rch9ae5b3b2016-02-11 00:36:29642 request_.url = GURL("http://www.example.org/");
[email protected]3e7dca62013-09-10 16:14:23643
xunjieli5fafe142016-03-23 23:32:54644 EXPECT_EQ(OK,
645 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
646 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:02647 EXPECT_EQ(OK,
648 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:23649
650 // Ack the request.
[email protected]1e960032013-12-20 19:00:20651 ProcessPacket(ConstructAckPacket(1, 0, 0));
[email protected]3e7dca62013-09-10 16:14:23652
rjshaded5ced072015-12-18 19:26:02653 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadResponseHeaders(callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:23654
655 SpdyHeaderBlock headers;
656 headers[":status"] = "200 OK";
657 headers[":version"] = "HTTP/1.1";
658 headers["content-type"] = "text/plain";
rch7dd15702015-07-01 18:57:57659 headers["big6"] = std::string(1000, 'x'); // Lots of x's.
[email protected]3e7dca62013-09-10 16:14:23660
rch7dd15702015-07-01 18:57:57661 response_headers_ = headers;
sclittlec4dc1a32015-09-24 00:15:45662 size_t spdy_response_headers_frame_length;
663 ProcessPacket(ConstructResponseHeadersPacket(
664 2, kFin, &spdy_response_headers_frame_length));
[email protected]3e7dca62013-09-10 16:14:23665
666 // Now that the headers have been processed, the callback will return.
667 EXPECT_EQ(OK, callback_.WaitForResult());
668 ASSERT_TRUE(response_.headers.get());
669 EXPECT_EQ(200, response_.headers->response_code());
670 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
671
672 // There is no body, so this should return immediately.
rjshaded5ced072015-12-18 19:26:02673 EXPECT_EQ(0,
674 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
675 callback_.callback()));
[email protected]3e7dca62013-09-10 16:14:23676 EXPECT_TRUE(stream_->IsResponseBodyComplete());
677 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:10678
679 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:45680 // headers and payload.
681 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
682 stream_->GetTotalSentBytes());
683 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length),
684 stream_->GetTotalReceivedBytes());
[email protected]3e7dca62013-09-10 16:14:23685}
686
rchf9f103cbc2014-08-30 05:28:04687// Regression test for http://crbug.com/409101
688TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendRequest) {
689 SetRequest("GET", "/", DEFAULT_PRIORITY);
690 Initialize();
691
692 request_.method = "GET";
rch9ae5b3b2016-02-11 00:36:29693 request_.url = GURL("http://www.example.org/");
rchf9f103cbc2014-08-30 05:28:04694
xunjieli5fafe142016-03-23 23:32:54695 EXPECT_EQ(OK,
696 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
697 net_log_.bound(), callback_.callback()));
rchf9f103cbc2014-08-30 05:28:04698
fayanga64c1a92016-02-13 01:55:58699 session_->connection()->CloseConnection(QUIC_NO_ERROR,
700 ConnectionCloseSource::FROM_PEER);
rchf9f103cbc2014-08-30 05:28:04701
702 EXPECT_EQ(ERR_CONNECTION_CLOSED,
rjshaded5ced072015-12-18 19:26:02703 stream_->SendRequest(headers_, &response_, callback_.callback()));
sclittle1edeeb22015-09-02 20:46:10704
705 EXPECT_EQ(0, stream_->GetTotalSentBytes());
706 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rchf9f103cbc2014-08-30 05:28:04707}
708
rch03b7a202016-02-05 00:54:20709// Regression test for http://crbug.com/584441
710TEST_P(QuicHttpStreamTest, GetSSLInfoAfterSessionClosed) {
711 SetRequest("GET", "/", DEFAULT_PRIORITY);
712 Initialize();
713
714 request_.method = "GET";
rch9ae5b3b2016-02-11 00:36:29715 request_.url = GURL("http://www.example.org/");
rch03b7a202016-02-05 00:54:20716
xunjieli5fafe142016-03-23 23:32:54717 EXPECT_EQ(OK,
718 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
719 net_log_.bound(), callback_.callback()));
rch03b7a202016-02-05 00:54:20720
721 SSLInfo ssl_info;
rch11565e02016-02-09 20:13:47722 EXPECT_FALSE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:20723 stream_->GetSSLInfo(&ssl_info);
rch11565e02016-02-09 20:13:47724 EXPECT_TRUE(ssl_info.is_valid());
rch03b7a202016-02-05 00:54:20725
fayanga64c1a92016-02-13 01:55:58726 session_->connection()->CloseConnection(QUIC_NO_ERROR,
727 ConnectionCloseSource::FROM_PEER);
rch03b7a202016-02-05 00:54:20728
rch11565e02016-02-09 20:13:47729 SSLInfo ssl_info2;
730 stream_->GetSSLInfo(&ssl_info2);
731 EXPECT_TRUE(ssl_info2.is_valid());
rch03b7a202016-02-05 00:54:20732}
733
zhongyica364fbb2015-12-12 03:39:12734TEST_P(QuicHttpStreamTest, LogGranularQuicConnectionError) {
735 SetRequest("GET", "/", DEFAULT_PRIORITY);
736 size_t spdy_request_headers_frame_length;
737 AddWrite(ConstructRequestHeadersPacket(1, kFin, DEFAULT_PRIORITY,
738 &spdy_request_headers_frame_length));
739 AddWrite(ConstructAckAndRstStreamPacket(2));
740 use_closing_stream_ = true;
741 Initialize();
742
743 request_.method = "GET";
rch9ae5b3b2016-02-11 00:36:29744 request_.url = GURL("http://www.example.org/");
zhongyica364fbb2015-12-12 03:39:12745
xunjieli5fafe142016-03-23 23:32:54746 EXPECT_EQ(OK,
747 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
748 net_log_.bound(), callback_.callback()));
zhongyica364fbb2015-12-12 03:39:12749 EXPECT_EQ(OK,
750 stream_->SendRequest(headers_, &response_, callback_.callback()));
751
752 // Ack the request.
753 ProcessPacket(ConstructAckPacket(1, 0, 0));
754 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadResponseHeaders(callback_.callback()));
755
756 EXPECT_TRUE(QuicHttpStreamPeer::WasHandshakeConfirmed(stream_.get()));
757 stream_->OnClose(QUIC_PEER_GOING_AWAY);
758
759 NetErrorDetails details;
760 EXPECT_EQ(QUIC_NO_ERROR, details.quic_connection_error);
761 stream_->PopulateNetErrorDetails(&details);
762 EXPECT_EQ(QUIC_PEER_GOING_AWAY, details.quic_connection_error);
763}
764
765TEST_P(QuicHttpStreamTest, DoNotLogGranularQuicErrorIfHandshakeNotConfirmed) {
766 SetRequest("GET", "/", DEFAULT_PRIORITY);
767 size_t spdy_request_headers_frame_length;
768 AddWrite(ConstructRequestHeadersPacket(1, kFin, DEFAULT_PRIORITY,
769 &spdy_request_headers_frame_length));
770 AddWrite(ConstructAckAndRstStreamPacket(2));
771 use_closing_stream_ = true;
772 Initialize();
773
774 request_.method = "GET";
rch9ae5b3b2016-02-11 00:36:29775 request_.url = GURL("http://www.example.org/");
zhongyica364fbb2015-12-12 03:39:12776
xunjieli5fafe142016-03-23 23:32:54777 EXPECT_EQ(OK,
778 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
779 net_log_.bound(), callback_.callback()));
zhongyica364fbb2015-12-12 03:39:12780 EXPECT_EQ(OK,
781 stream_->SendRequest(headers_, &response_, callback_.callback()));
782
783 // Ack the request.
784 ProcessPacket(ConstructAckPacket(1, 0, 0));
785 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadResponseHeaders(callback_.callback()));
786
787 // The test setup defaults handshake to be confirmed. Manually set
788 // it to be not confirmed.
789 // Granular errors shouldn't be reported if handshake not confirmed.
790 QuicHttpStreamPeer::SetHandshakeConfirmed(stream_.get(), false);
791
792 EXPECT_FALSE(QuicHttpStreamPeer::WasHandshakeConfirmed(stream_.get()));
793 stream_->OnClose(QUIC_PEER_GOING_AWAY);
794
795 NetErrorDetails details;
796 EXPECT_EQ(QUIC_NO_ERROR, details.quic_connection_error);
797 stream_->PopulateNetErrorDetails(&details);
798 EXPECT_EQ(QUIC_NO_ERROR, details.quic_connection_error);
799}
800
rch11a114a2014-09-04 23:41:59801// Regression test for http://crbug.com/409871
802TEST_P(QuicHttpStreamTest, SessionClosedBeforeReadResponseHeaders) {
803 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:45804 size_t spdy_request_headers_frame_length;
805 AddWrite(ConstructRequestHeadersPacket(1, kFin, DEFAULT_PRIORITY,
806 &spdy_request_headers_frame_length));
rch11a114a2014-09-04 23:41:59807 Initialize();
808
809 request_.method = "GET";
rch9ae5b3b2016-02-11 00:36:29810 request_.url = GURL("http://www.example.org/");
rch11a114a2014-09-04 23:41:59811
xunjieli5fafe142016-03-23 23:32:54812 EXPECT_EQ(OK,
813 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
814 net_log_.bound(), callback_.callback()));
rch11a114a2014-09-04 23:41:59815
rjshaded5ced072015-12-18 19:26:02816 EXPECT_EQ(OK,
817 stream_->SendRequest(headers_, &response_, callback_.callback()));
rch11a114a2014-09-04 23:41:59818
fayanga64c1a92016-02-13 01:55:58819 session_->connection()->CloseConnection(QUIC_NO_ERROR,
820 ConnectionCloseSource::FROM_PEER);
rch11a114a2014-09-04 23:41:59821
822 EXPECT_NE(OK, stream_->ReadResponseHeaders(callback_.callback()));
sclittle1edeeb22015-09-02 20:46:10823
824 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:45825 // headers and payload.
826 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
827 stream_->GetTotalSentBytes());
sclittle1edeeb22015-09-02 20:46:10828 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
rch11a114a2014-09-04 23:41:59829}
830
[email protected]1e960032013-12-20 19:00:20831TEST_P(QuicHttpStreamTest, SendPostRequest) {
832 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:45833 size_t spdy_request_headers_frame_length;
834 AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY,
835 &spdy_request_headers_frame_length));
[email protected]92bf17c2014-03-03 21:14:03836 AddWrite(ConstructDataPacket(2, kIncludeVersion, kFin, 0, kUploadData));
[email protected]1e960032013-12-20 19:00:20837 AddWrite(ConstructAckPacket(3, 3, 1));
[email protected]f702d572012-12-04 15:56:20838
839 Initialize();
840
olli.raula6df48b2a2015-11-26 07:40:22841 std::vector<scoped_ptr<UploadElementReader>> element_readers;
842 element_readers.push_back(make_scoped_ptr(
843 new UploadBytesElementReader(kUploadData, strlen(kUploadData))));
844 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]f702d572012-12-04 15:56:20845 request_.method = "POST";
rch9ae5b3b2016-02-11 00:36:29846 request_.url = GURL("http://www.example.org/");
[email protected]f702d572012-12-04 15:56:20847 request_.upload_data_stream = &upload_data_stream;
[email protected]4db27d82012-12-20 11:50:24848 ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback()));
[email protected]f702d572012-12-04 15:56:20849
xunjieli5fafe142016-03-23 23:32:54850 EXPECT_EQ(OK,
851 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
852 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:02853 EXPECT_EQ(OK,
854 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]f702d572012-12-04 15:56:20855
856 // Ack both packets in the request.
[email protected]1e960032013-12-20 19:00:20857 ProcessPacket(ConstructAckPacket(1, 0, 0));
[email protected]f702d572012-12-04 15:56:20858
859 // Send the response headers (but not the body).
[email protected]1e960032013-12-20 19:00:20860 SetResponse("200 OK", std::string());
sclittlec4dc1a32015-09-24 00:15:45861 size_t spdy_response_headers_frame_length;
862 ProcessPacket(ConstructResponseHeadersPacket(
863 2, !kFin, &spdy_response_headers_frame_length));
[email protected]f702d572012-12-04 15:56:20864
rchb27683c2015-07-29 23:53:50865 // The headers have arrived, but they are delivered asynchronously.
866 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadResponseHeaders(callback_.callback()));
867 EXPECT_EQ(OK, callback_.WaitForResult());
[email protected]cadac622013-06-11 16:46:36868 ASSERT_TRUE(response_.headers.get());
[email protected]f702d572012-12-04 15:56:20869 EXPECT_EQ(200, response_.headers->response_code());
870 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
871
872 // Send the response body.
873 const char kResponseBody[] = "Hello world!";
[email protected]92bf17c2014-03-03 21:14:03874 ProcessPacket(ConstructDataPacket(3, false, kFin, 0, kResponseBody));
[email protected]f702d572012-12-04 15:56:20875 // Since the body has already arrived, this should return immediately.
876 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
877 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
878 callback_.callback()));
879
880 EXPECT_TRUE(stream_->IsResponseBodyComplete());
881 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:10882
883 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:45884 // headers and payload.
885 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
886 strlen(kUploadData)),
sclittle1edeeb22015-09-02 20:46:10887 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:45888 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
889 strlen(kResponseBody)),
sclittle1edeeb22015-09-02 20:46:10890 stream_->GetTotalReceivedBytes());
[email protected]f702d572012-12-04 15:56:20891}
892
[email protected]1e960032013-12-20 19:00:20893TEST_P(QuicHttpStreamTest, SendChunkedPostRequest) {
894 SetRequest("POST", "/", DEFAULT_PRIORITY);
[email protected]c9e49a02013-02-26 05:56:47895 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:45896 size_t spdy_request_headers_frame_length;
897 AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY,
898 &spdy_request_headers_frame_length));
[email protected]92bf17c2014-03-03 21:14:03899 AddWrite(ConstructDataPacket(2, kIncludeVersion, !kFin, 0, kUploadData));
rjshaded5ced072015-12-18 19:26:02900 AddWrite(
901 ConstructDataPacket(3, kIncludeVersion, kFin, chunk_size, kUploadData));
[email protected]1e960032013-12-20 19:00:20902 AddWrite(ConstructAckPacket(4, 3, 1));
[email protected]c9e49a02013-02-26 05:56:47903 Initialize();
904
mmenkecbc2b712014-10-09 20:29:07905 ChunkedUploadDataStream upload_data_stream(0);
906 upload_data_stream.AppendData(kUploadData, chunk_size, false);
[email protected]c9e49a02013-02-26 05:56:47907
908 request_.method = "POST";
rch9ae5b3b2016-02-11 00:36:29909 request_.url = GURL("http://www.example.org/");
[email protected]c9e49a02013-02-26 05:56:47910 request_.upload_data_stream = &upload_data_stream;
mmenkecbc2b712014-10-09 20:29:07911 ASSERT_EQ(OK, request_.upload_data_stream->Init(
rjshaded5ced072015-12-18 19:26:02912 TestCompletionCallback().callback()));
[email protected]c9e49a02013-02-26 05:56:47913
xunjieli5fafe142016-03-23 23:32:54914 ASSERT_EQ(OK,
915 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
916 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:02917 ASSERT_EQ(ERR_IO_PENDING,
918 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]c9e49a02013-02-26 05:56:47919
mmenkecbc2b712014-10-09 20:29:07920 upload_data_stream.AppendData(kUploadData, chunk_size, true);
rchb27683c2015-07-29 23:53:50921 EXPECT_EQ(OK, callback_.WaitForResult());
[email protected]c9e49a02013-02-26 05:56:47922
923 // Ack both packets in the request.
[email protected]1e960032013-12-20 19:00:20924 ProcessPacket(ConstructAckPacket(1, 0, 0));
[email protected]c9e49a02013-02-26 05:56:47925
926 // Send the response headers (but not the body).
[email protected]1e960032013-12-20 19:00:20927 SetResponse("200 OK", std::string());
sclittlec4dc1a32015-09-24 00:15:45928 size_t spdy_response_headers_frame_length;
929 ProcessPacket(ConstructResponseHeadersPacket(
930 2, !kFin, &spdy_response_headers_frame_length));
[email protected]c9e49a02013-02-26 05:56:47931
rchb27683c2015-07-29 23:53:50932 // The headers have arrived, but they are delivered asynchronously
933 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadResponseHeaders(callback_.callback()));
934 EXPECT_EQ(OK, callback_.WaitForResult());
[email protected]cadac622013-06-11 16:46:36935 ASSERT_TRUE(response_.headers.get());
[email protected]c9e49a02013-02-26 05:56:47936 EXPECT_EQ(200, response_.headers->response_code());
937 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
938
939 // Send the response body.
940 const char kResponseBody[] = "Hello world!";
[email protected]1e960032013-12-20 19:00:20941 ProcessPacket(ConstructDataPacket(3, false, kFin, response_data_.length(),
942 kResponseBody));
[email protected]c9e49a02013-02-26 05:56:47943
944 // Since the body has already arrived, this should return immediately.
945 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
946 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
947 callback_.callback()));
948
949 EXPECT_TRUE(stream_->IsResponseBodyComplete());
950 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:10951
952 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:45953 // headers and payload.
954 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
955 strlen(kUploadData) * 2),
sclittle1edeeb22015-09-02 20:46:10956 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:45957 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
958 strlen(kResponseBody)),
sclittle1edeeb22015-09-02 20:46:10959 stream_->GetTotalReceivedBytes());
[email protected]c9e49a02013-02-26 05:56:47960}
961
[email protected]16ba7742014-08-22 00:57:25962TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithFinalEmptyDataPacket) {
963 SetRequest("POST", "/", DEFAULT_PRIORITY);
964 size_t chunk_size = strlen(kUploadData);
sclittlec4dc1a32015-09-24 00:15:45965 size_t spdy_request_headers_frame_length;
966 AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY,
967 &spdy_request_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:25968 AddWrite(ConstructDataPacket(2, kIncludeVersion, !kFin, 0, kUploadData));
969 AddWrite(ConstructDataPacket(3, kIncludeVersion, kFin, chunk_size, ""));
970 AddWrite(ConstructAckPacket(4, 3, 1));
971 Initialize();
972
mmenkecbc2b712014-10-09 20:29:07973 ChunkedUploadDataStream upload_data_stream(0);
974 upload_data_stream.AppendData(kUploadData, chunk_size, false);
[email protected]16ba7742014-08-22 00:57:25975
976 request_.method = "POST";
rch9ae5b3b2016-02-11 00:36:29977 request_.url = GURL("http://www.example.org/");
[email protected]16ba7742014-08-22 00:57:25978 request_.upload_data_stream = &upload_data_stream;
mmenkecbc2b712014-10-09 20:29:07979 ASSERT_EQ(OK, request_.upload_data_stream->Init(
rjshaded5ced072015-12-18 19:26:02980 TestCompletionCallback().callback()));
[email protected]16ba7742014-08-22 00:57:25981
xunjieli5fafe142016-03-23 23:32:54982 ASSERT_EQ(OK,
983 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
984 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:02985 ASSERT_EQ(ERR_IO_PENDING,
986 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:25987
mmenkecbc2b712014-10-09 20:29:07988 upload_data_stream.AppendData(nullptr, 0, true);
rchb27683c2015-07-29 23:53:50989 EXPECT_EQ(OK, callback_.WaitForResult());
[email protected]16ba7742014-08-22 00:57:25990
991 ProcessPacket(ConstructAckPacket(1, 0, 0));
992
993 // Send the response headers (but not the body).
994 SetResponse("200 OK", std::string());
sclittlec4dc1a32015-09-24 00:15:45995 size_t spdy_response_headers_frame_length;
996 ProcessPacket(ConstructResponseHeadersPacket(
997 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:25998
rchb27683c2015-07-29 23:53:50999 // The headers have arrived, but they are delivered asynchronously
1000 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadResponseHeaders(callback_.callback()));
1001 EXPECT_EQ(OK, callback_.WaitForResult());
[email protected]16ba7742014-08-22 00:57:251002 ASSERT_TRUE(response_.headers.get());
1003 EXPECT_EQ(200, response_.headers->response_code());
1004 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1005
1006 // Send the response body.
1007 const char kResponseBody[] = "Hello world!";
1008 ProcessPacket(ConstructDataPacket(3, false, kFin, response_data_.length(),
1009 kResponseBody));
1010
rchb27683c2015-07-29 23:53:501011 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251012 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1013 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1014 callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251015 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1016 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101017
1018 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451019 // headers and payload.
1020 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
1021 strlen(kUploadData)),
sclittle1edeeb22015-09-02 20:46:101022 stream_->GetTotalSentBytes());
sclittlec4dc1a32015-09-24 00:15:451023 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1024 strlen(kResponseBody)),
sclittle1edeeb22015-09-02 20:46:101025 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251026}
1027
1028TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithOneEmptyDataPacket) {
1029 SetRequest("POST", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451030 size_t spdy_request_headers_frame_length;
1031 AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY,
1032 &spdy_request_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251033 AddWrite(ConstructDataPacket(2, kIncludeVersion, kFin, 0, ""));
1034 AddWrite(ConstructAckPacket(3, 3, 1));
1035 Initialize();
1036
mmenkecbc2b712014-10-09 20:29:071037 ChunkedUploadDataStream upload_data_stream(0);
[email protected]16ba7742014-08-22 00:57:251038
1039 request_.method = "POST";
rch9ae5b3b2016-02-11 00:36:291040 request_.url = GURL("http://www.example.org/");
[email protected]16ba7742014-08-22 00:57:251041 request_.upload_data_stream = &upload_data_stream;
mmenkecbc2b712014-10-09 20:29:071042 ASSERT_EQ(OK, request_.upload_data_stream->Init(
rjshaded5ced072015-12-18 19:26:021043 TestCompletionCallback().callback()));
[email protected]16ba7742014-08-22 00:57:251044
xunjieli5fafe142016-03-23 23:32:541045 ASSERT_EQ(OK,
1046 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1047 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021048 ASSERT_EQ(ERR_IO_PENDING,
1049 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]16ba7742014-08-22 00:57:251050
mmenkecbc2b712014-10-09 20:29:071051 upload_data_stream.AppendData(nullptr, 0, true);
rchb27683c2015-07-29 23:53:501052 EXPECT_EQ(OK, callback_.WaitForResult());
[email protected]16ba7742014-08-22 00:57:251053
1054 ProcessPacket(ConstructAckPacket(1, 0, 0));
1055
1056 // Send the response headers (but not the body).
1057 SetResponse("200 OK", std::string());
sclittlec4dc1a32015-09-24 00:15:451058 size_t spdy_response_headers_frame_length;
1059 ProcessPacket(ConstructResponseHeadersPacket(
1060 2, !kFin, &spdy_response_headers_frame_length));
[email protected]16ba7742014-08-22 00:57:251061
rchb27683c2015-07-29 23:53:501062 // The headers have arrived, but they are delivered asynchronously
1063 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadResponseHeaders(callback_.callback()));
1064 EXPECT_EQ(OK, callback_.WaitForResult());
[email protected]16ba7742014-08-22 00:57:251065 ASSERT_TRUE(response_.headers.get());
1066 EXPECT_EQ(200, response_.headers->response_code());
1067 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1068
1069 // Send the response body.
1070 const char kResponseBody[] = "Hello world!";
1071 ProcessPacket(ConstructDataPacket(3, false, kFin, response_data_.length(),
1072 kResponseBody));
1073
rchb27683c2015-07-29 23:53:501074 // The body has arrived, but it is delivered asynchronously
[email protected]16ba7742014-08-22 00:57:251075 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
1076 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
1077 callback_.callback()));
1078
1079 EXPECT_TRUE(stream_->IsResponseBodyComplete());
1080 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101081
1082 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451083 // headers and payload.
1084 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1085 stream_->GetTotalSentBytes());
1086 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1087 strlen(kResponseBody)),
sclittle1edeeb22015-09-02 20:46:101088 stream_->GetTotalReceivedBytes());
[email protected]16ba7742014-08-22 00:57:251089}
1090
[email protected]1e960032013-12-20 19:00:201091TEST_P(QuicHttpStreamTest, DestroyedEarly) {
1092 SetRequest("GET", "/", DEFAULT_PRIORITY);
sclittlec4dc1a32015-09-24 00:15:451093 size_t spdy_request_headers_frame_length;
1094 AddWrite(ConstructRequestHeadersPacket(1, kFin, DEFAULT_PRIORITY,
1095 &spdy_request_headers_frame_length));
rtenneti4efd55dd2015-09-18 01:12:041096 AddWrite(ConstructAckAndRstStreamPacket(2));
[email protected]63534512012-12-23 18:49:001097 use_closing_stream_ = true;
1098 Initialize();
1099
1100 request_.method = "GET";
rch9ae5b3b2016-02-11 00:36:291101 request_.url = GURL("http://www.example.org/");
[email protected]63534512012-12-23 18:49:001102
xunjieli5fafe142016-03-23 23:32:541103 EXPECT_EQ(OK,
1104 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1105 net_log_.bound(), callback_.callback()));
rjshaded5ced072015-12-18 19:26:021106 EXPECT_EQ(OK,
1107 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]63534512012-12-23 18:49:001108
1109 // Ack the request.
[email protected]1e960032013-12-20 19:00:201110 ProcessPacket(ConstructAckPacket(1, 0, 0));
rjshaded5ced072015-12-18 19:26:021111 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadResponseHeaders(callback_.callback()));
[email protected]63534512012-12-23 18:49:001112
1113 // Send the response with a body.
[email protected]1e960032013-12-20 19:00:201114 SetResponse("404 OK", "hello world!");
[email protected]63534512012-12-23 18:49:001115 // In the course of processing this packet, the QuicHttpStream close itself.
sclittlec4dc1a32015-09-24 00:15:451116 ProcessPacket(ConstructResponseHeadersPacket(2, kFin, nullptr));
[email protected]63534512012-12-23 18:49:001117
rchb27683c2015-07-29 23:53:501118 base::MessageLoop::current()->RunUntilIdle();
1119
[email protected]63534512012-12-23 18:49:001120 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101121
1122 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451123 // headers and payload.
1124 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1125 stream_->GetTotalSentBytes());
1126 // Zero since the stream is closed before processing the headers.
sclittle1edeeb22015-09-02 20:46:101127 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
[email protected]63534512012-12-23 18:49:001128}
1129
[email protected]1e960032013-12-20 19:00:201130TEST_P(QuicHttpStreamTest, Priority) {
1131 SetRequest("GET", "/", MEDIUM);
sclittlec4dc1a32015-09-24 00:15:451132 size_t spdy_request_headers_frame_length;
1133 AddWrite(ConstructRequestHeadersPacket(1, kFin, MEDIUM,
1134 &spdy_request_headers_frame_length));
rtenneti4efd55dd2015-09-18 01:12:041135 AddWrite(ConstructAckAndRstStreamPacket(2));
[email protected]24e5bc52013-09-18 15:36:581136 use_closing_stream_ = true;
1137 Initialize();
1138
1139 request_.method = "GET";
rch9ae5b3b2016-02-11 00:36:291140 request_.url = GURL("http://www.example.org/");
[email protected]24e5bc52013-09-18 15:36:581141
xunjieli5fafe142016-03-23 23:32:541142 EXPECT_EQ(OK, stream_->InitializeStream(&request_, MEDIUM, net_log_.bound(),
rjshaded5ced072015-12-18 19:26:021143 callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581144
1145 // Check that priority is highest.
rch12fef552016-01-15 16:26:311146 QuicChromiumClientStream* reliable_stream =
1147 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
[email protected]24e5bc52013-09-18 15:36:581148 DCHECK(reliable_stream);
fayanga64c1a92016-02-13 01:55:581149 DCHECK_EQ(kV3HighestPriority, reliable_stream->priority());
[email protected]24e5bc52013-09-18 15:36:581150
rjshaded5ced072015-12-18 19:26:021151 EXPECT_EQ(OK,
1152 stream_->SendRequest(headers_, &response_, callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581153
1154 // Check that priority has now dropped back to MEDIUM.
ianswett0888cff2015-11-24 17:42:161155 DCHECK_EQ(MEDIUM,
fayanga64c1a92016-02-13 01:55:581156 ConvertQuicPriorityToRequestPriority(reliable_stream->priority()));
[email protected]24e5bc52013-09-18 15:36:581157
1158 // Ack the request.
[email protected]1e960032013-12-20 19:00:201159 ProcessPacket(ConstructAckPacket(1, 0, 0));
rjshaded5ced072015-12-18 19:26:021160 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadResponseHeaders(callback_.callback()));
[email protected]24e5bc52013-09-18 15:36:581161
1162 // Send the response with a body.
[email protected]1e960032013-12-20 19:00:201163 SetResponse("404 OK", "hello world!");
[email protected]24e5bc52013-09-18 15:36:581164 // In the course of processing this packet, the QuicHttpStream close itself.
sclittlec4dc1a32015-09-24 00:15:451165 ProcessPacket(ConstructResponseHeadersPacket(2, kFin, nullptr));
[email protected]24e5bc52013-09-18 15:36:581166
rchb27683c2015-07-29 23:53:501167 base::MessageLoop::current()->RunUntilIdle();
1168
[email protected]24e5bc52013-09-18 15:36:581169 EXPECT_TRUE(AtEof());
sclittle1edeeb22015-09-02 20:46:101170
1171 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
sclittlec4dc1a32015-09-24 00:15:451172 // headers and payload.
1173 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
1174 stream_->GetTotalSentBytes());
1175 // Zero since the stream is closed before processing the headers.
sclittle1edeeb22015-09-02 20:46:101176 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
[email protected]24e5bc52013-09-18 15:36:581177}
1178
[email protected]e1cca9a2013-09-20 17:14:441179// Regression test for http://crbug.com/294870
[email protected]1e960032013-12-20 19:00:201180TEST_P(QuicHttpStreamTest, CheckPriorityWithNoDelegate) {
1181 SetRequest("GET", "/", MEDIUM);
[email protected]e1cca9a2013-09-20 17:14:441182 use_closing_stream_ = true;
[email protected]459a7402014-02-10 12:58:521183
[email protected]08da9adb2014-04-24 08:33:311184 AddWrite(ConstructRstStreamPacket(1));
[email protected]459a7402014-02-10 12:58:521185
[email protected]e1cca9a2013-09-20 17:14:441186 Initialize();
1187
1188 request_.method = "GET";
rch9ae5b3b2016-02-11 00:36:291189 request_.url = GURL("http://www.example.org/");
[email protected]e1cca9a2013-09-20 17:14:441190
xunjieli5fafe142016-03-23 23:32:541191 EXPECT_EQ(OK, stream_->InitializeStream(&request_, MEDIUM, net_log_.bound(),
rjshaded5ced072015-12-18 19:26:021192 callback_.callback()));
[email protected]e1cca9a2013-09-20 17:14:441193
1194 // Check that priority is highest.
rch12fef552016-01-15 16:26:311195 QuicChromiumClientStream* reliable_stream =
1196 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
[email protected]e1cca9a2013-09-20 17:14:441197 DCHECK(reliable_stream);
rch12fef552016-01-15 16:26:311198 QuicChromiumClientStream::Delegate* delegate = reliable_stream->GetDelegate();
[email protected]e1cca9a2013-09-20 17:14:441199 DCHECK(delegate);
fayanga64c1a92016-02-13 01:55:581200 DCHECK_EQ(kV3HighestPriority, reliable_stream->priority());
[email protected]e1cca9a2013-09-20 17:14:441201
ianswett0888cff2015-11-24 17:42:161202 // Set Delegate to nullptr and make sure Priority returns highest
[email protected]e1cca9a2013-09-20 17:14:441203 // priority.
rtennetibe635732014-10-02 22:51:421204 reliable_stream->SetDelegate(nullptr);
fayanga64c1a92016-02-13 01:55:581205 DCHECK_EQ(kV3HighestPriority, reliable_stream->priority());
[email protected]e1cca9a2013-09-20 17:14:441206 reliable_stream->SetDelegate(delegate);
sclittle1edeeb22015-09-02 20:46:101207
sclittle1edeeb22015-09-02 20:46:101208 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1209 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
[email protected]e1cca9a2013-09-20 17:14:441210}
1211
rtenneti15656ae2016-01-23 03:05:031212TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersComplete) {
1213 SetRequest("POST", "/", DEFAULT_PRIORITY);
1214 AddWrite(SYNCHRONOUS, ERR_FAILED);
1215 Initialize();
1216
1217 ChunkedUploadDataStream upload_data_stream(0);
1218
1219 request_.method = "POST";
rch9ae5b3b2016-02-11 00:36:291220 request_.url = GURL("http://www.example.org/");
rtenneti15656ae2016-01-23 03:05:031221 request_.upload_data_stream = &upload_data_stream;
1222 ASSERT_EQ(OK, request_.upload_data_stream->Init(
1223 TestCompletionCallback().callback()));
1224
xunjieli5fafe142016-03-23 23:32:541225 ASSERT_EQ(OK,
1226 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1227 net_log_.bound(), callback_.callback()));
rtenneti15656ae2016-01-23 03:05:031228 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1229 stream_->SendRequest(headers_, &response_, callback_.callback()));
1230}
1231
1232TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBodyComplete) {
1233 SetRequest("POST", "/", DEFAULT_PRIORITY);
1234 size_t spdy_request_headers_frame_length;
1235 AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY,
1236 &spdy_request_headers_frame_length));
1237 AddWrite(SYNCHRONOUS, ERR_FAILED);
1238 Initialize();
1239
1240 ChunkedUploadDataStream upload_data_stream(0);
1241 size_t chunk_size = strlen(kUploadData);
1242 upload_data_stream.AppendData(kUploadData, chunk_size, false);
1243
1244 request_.method = "POST";
rch9ae5b3b2016-02-11 00:36:291245 request_.url = GURL("http://www.example.org/");
rtenneti15656ae2016-01-23 03:05:031246 request_.upload_data_stream = &upload_data_stream;
1247 ASSERT_EQ(OK, request_.upload_data_stream->Init(
1248 TestCompletionCallback().callback()));
1249
xunjieli5fafe142016-03-23 23:32:541250 ASSERT_EQ(OK,
1251 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1252 net_log_.bound(), callback_.callback()));
rtenneti15656ae2016-01-23 03:05:031253 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1254 stream_->SendRequest(headers_, &response_, callback_.callback()));
1255}
1256
ckrasic3865ee0f2016-02-29 22:04:561257TEST_P(QuicHttpStreamTest, ServerPushGetRequest) {
1258 SetRequest("GET", "/", DEFAULT_PRIORITY);
1259 Initialize();
1260
1261 // Initialize the first stream, for receiving the promise on.
1262 request_.method = "GET";
1263 request_.url = GURL("http://www.example.org/");
1264
xunjieli5fafe142016-03-23 23:32:541265 EXPECT_EQ(OK,
1266 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1267 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561268
1269 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
1270 // packet, but does it matter?
1271 ReceivePromise(promise_id_);
1272 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
1273
1274 request_.url = GURL(promise_url_);
1275
1276 // Make the second stream that will exercise the first step of the
1277 // server push rendezvous mechanism.
xunjieli5fafe142016-03-23 23:32:541278 EXPECT_EQ(OK, promised_stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1279 net_log_.bound(),
1280 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561281
1282 // Receive the promised response headers.
1283 response_headers_ = promised_response_;
1284 size_t spdy_response_headers_frame_length;
1285 ProcessPacket(InnerConstructResponseHeadersPacket(
1286 1, promise_id_, false, &spdy_response_headers_frame_length));
1287
1288 // Receive the promised response body.
1289 const char kResponseBody[] = "Hello world!";
1290 ProcessPacket(
1291 InnerConstructDataPacket(2, promise_id_, false, kFin, 0, kResponseBody));
1292
1293 // Now sending a matching request will have successful rendezvous
1294 // with the promised stream.
1295 EXPECT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
1296 callback_.callback()));
1297
1298 EXPECT_EQ(
1299 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
1300 ->id(),
1301 promise_id_);
1302
1303 // The headers will be immediately available.
1304 EXPECT_EQ(OK, promised_stream_->ReadResponseHeaders(callback_.callback()));
1305
1306 // As will be the body.
1307 EXPECT_EQ(
1308 static_cast<int>(strlen(kResponseBody)),
1309 promised_stream_->ReadResponseBody(
1310 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
1311 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
1312 EXPECT_TRUE(AtEof());
1313
1314 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1315 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1316 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
1317 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1318 strlen(kResponseBody)),
1319 promised_stream_->GetTotalReceivedBytes());
1320}
1321
1322TEST_P(QuicHttpStreamTest, ServerPushGetRequestSlowResponse) {
1323 SetRequest("GET", "/", DEFAULT_PRIORITY);
1324 Initialize();
1325
1326 // Initialize the first stream, for receiving the promise on.
1327 request_.method = "GET";
1328 request_.url = GURL("http://www.example.org/");
1329
xunjieli5fafe142016-03-23 23:32:541330 EXPECT_EQ(OK,
1331 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1332 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561333
1334 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
1335 // packet, but does it matter?
1336 ReceivePromise(promise_id_);
1337 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
1338
1339 request_.url = GURL(promise_url_);
1340
1341 // Make the second stream that will exercise the first step of the
1342 // server push rendezvous mechanism.
xunjieli5fafe142016-03-23 23:32:541343 EXPECT_EQ(OK, promised_stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1344 net_log_.bound(),
1345 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561346
1347 // Now sending a matching request will rendezvous with the promised
1348 // stream, but pending secondary validation.
1349 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
1350 headers_, &response_, callback_.callback()));
1351
1352 // Receive the promised response headers.
1353 response_headers_ = promised_response_;
1354 size_t spdy_response_headers_frame_length;
1355 ProcessPacket(InnerConstructResponseHeadersPacket(
1356 1, promise_id_, false, &spdy_response_headers_frame_length));
1357
1358 // Receive the promised response body.
1359 const char kResponseBody[] = "Hello world!";
1360 ProcessPacket(
1361 InnerConstructDataPacket(2, promise_id_, false, kFin, 0, kResponseBody));
1362
1363 base::MessageLoop::current()->RunUntilIdle();
1364
1365 // Rendezvous should have succeeded now, so the promised stream
1366 // should point at our push stream, and we should be able read
1367 // headers and data from it.
1368 EXPECT_EQ(OK, callback_.WaitForResult());
1369
1370 EXPECT_EQ(
1371 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
1372 ->id(),
1373 promise_id_);
1374
1375 EXPECT_EQ(OK, promised_stream_->ReadResponseHeaders(callback_.callback()));
1376
1377 EXPECT_EQ(
1378 static_cast<int>(strlen(kResponseBody)),
1379 promised_stream_->ReadResponseBody(
1380 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
1381
1382 // Callback should return
1383 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
1384 EXPECT_TRUE(AtEof());
1385
1386 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1387 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1388 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
1389 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1390 strlen(kResponseBody)),
1391 promised_stream_->GetTotalReceivedBytes());
1392}
1393
1394TEST_P(QuicHttpStreamTest, ServerPushCrossOriginOK) {
1395 SetRequest("GET", "/", DEFAULT_PRIORITY);
1396 Initialize();
1397
1398 // Initialize the first stream, for receiving the promise on.
1399 request_.method = "GET";
1400 request_.url = GURL("http://www.example.org/");
1401
xunjieli5fafe142016-03-23 23:32:541402 EXPECT_EQ(OK,
1403 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1404 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561405
1406 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
1407 // packet, but does it matter?
1408
1409 push_promise_[":authority"] = "mail.example.org";
1410 promise_url_ = SpdyUtils::GetUrlFromHeaderBlock(push_promise_);
1411 serialized_push_promise_ =
1412 SpdyUtils::SerializeUncompressedHeaders(push_promise_);
1413
1414 ReceivePromise(promise_id_);
1415 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
1416
1417 request_.url = GURL(promise_url_);
1418
1419 // Make the second stream that will exercise the first step of the
1420 // server push rendezvous mechanism.
xunjieli5fafe142016-03-23 23:32:541421 EXPECT_EQ(OK, promised_stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1422 net_log_.bound(),
1423 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561424
1425 // Receive the promised response headers.
1426 response_headers_ = promised_response_;
1427 size_t spdy_response_headers_frame_length;
1428 ProcessPacket(InnerConstructResponseHeadersPacket(
1429 1, promise_id_, false, &spdy_response_headers_frame_length));
1430
1431 // Receive the promised response body.
1432 const char kResponseBody[] = "Hello world!";
1433 ProcessPacket(
1434 InnerConstructDataPacket(2, promise_id_, false, kFin, 0, kResponseBody));
1435
1436 // Now sending a matching request will have successful rendezvous
1437 // with the promised stream.
1438 EXPECT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
1439 callback_.callback()));
1440
1441 EXPECT_EQ(
1442 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
1443 ->id(),
1444 promise_id_);
1445
1446 // The headers will be immediately available.
1447 EXPECT_EQ(OK, promised_stream_->ReadResponseHeaders(callback_.callback()));
1448
1449 // As will be the body.
1450 EXPECT_EQ(
1451 static_cast<int>(strlen(kResponseBody)),
1452 promised_stream_->ReadResponseBody(
1453 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
1454 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
1455 EXPECT_TRUE(AtEof());
1456
1457 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1458 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1459 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
1460 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1461 strlen(kResponseBody)),
1462 promised_stream_->GetTotalReceivedBytes());
1463}
1464
1465TEST_P(QuicHttpStreamTest, ServerPushCrossOriginFail) {
1466 SetRequest("GET", "/", DEFAULT_PRIORITY);
1467 Initialize();
1468
1469 // Initialize the first stream, for receiving the promise on.
1470 request_.method = "GET";
1471 request_.url = GURL("http://www.example.org/");
1472
xunjieli5fafe142016-03-23 23:32:541473 EXPECT_EQ(OK,
1474 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1475 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561476
1477 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
1478 // packet, but does it matter?
1479 push_promise_[":authority"] = "www.notexample.org";
1480 promise_url_ = SpdyUtils::GetUrlFromHeaderBlock(push_promise_);
1481 serialized_push_promise_ =
1482 SpdyUtils::SerializeUncompressedHeaders(push_promise_);
1483
1484 ReceivePromise(promise_id_);
1485 // The promise will have been rejected because the cert doesn't
1486 // match.
1487 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
1488}
1489
1490TEST_P(QuicHttpStreamTest, ServerPushVaryCheckOK) {
1491 SetRequest("GET", "/", DEFAULT_PRIORITY);
1492 Initialize();
1493
1494 // Initialize the first stream, for receiving the promise on.
1495 request_.method = "GET";
1496 request_.url = GURL("http://www.example.org/");
1497
xunjieli5fafe142016-03-23 23:32:541498 EXPECT_EQ(OK,
1499 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1500 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561501
1502 push_promise_["accept-encoding"] = "gzip";
1503 serialized_push_promise_ =
1504 SpdyUtils::SerializeUncompressedHeaders(push_promise_);
1505
1506 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
1507 // packet, but does it matter?
1508 ReceivePromise(promise_id_);
1509 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
1510
1511 request_.url = GURL(promise_url_);
1512
1513 // Make the second stream that will exercise the first step of the
1514 // server push rendezvous mechanism.
xunjieli5fafe142016-03-23 23:32:541515 EXPECT_EQ(OK, promised_stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1516 net_log_.bound(),
1517 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561518
1519 headers_.SetHeader("accept-encoding", "gzip");
1520
1521 // Now sending a matching request will rendezvous with the promised
1522 // stream, but pending secondary validation.
1523 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
1524 headers_, &response_, callback_.callback()));
1525
1526 // Receive the promised response headers.
1527 promised_response_["vary"] = "accept-encoding";
1528 response_headers_ = promised_response_;
1529 size_t spdy_response_headers_frame_length;
1530 ProcessPacket(InnerConstructResponseHeadersPacket(
1531 1, promise_id_, false, &spdy_response_headers_frame_length));
1532
1533 // Receive the promised response body.
1534 const char kResponseBody[] = "Hello world!";
1535 ProcessPacket(
1536 InnerConstructDataPacket(2, promise_id_, false, kFin, 0, kResponseBody));
1537
1538 base::MessageLoop::current()->RunUntilIdle();
1539
1540 // Rendezvous should have succeeded now, so the promised stream
1541 // should point at our push stream, and we should be able read
1542 // headers and data from it.
1543 EXPECT_EQ(OK, callback_.WaitForResult());
1544
1545 EXPECT_EQ(
1546 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
1547 ->id(),
1548 promise_id_);
1549
1550 EXPECT_EQ(OK, promised_stream_->ReadResponseHeaders(callback_.callback()));
1551
1552 EXPECT_EQ(
1553 static_cast<int>(strlen(kResponseBody)),
1554 promised_stream_->ReadResponseBody(
1555 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
1556
1557 // Callback should return
1558 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
1559 EXPECT_TRUE(AtEof());
1560
1561 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1562 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1563 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
1564 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1565 strlen(kResponseBody)),
1566 promised_stream_->GetTotalReceivedBytes());
1567}
1568
1569TEST_P(QuicHttpStreamTest, ServerPushVaryCheckFail) {
1570 SetRequest("GET", "/", DEFAULT_PRIORITY);
1571 request_headers_[":scheme"] = "https";
1572 request_headers_[":path"] = "/bar";
1573 request_headers_["accept-encoding"] = "sdch";
1574
1575 size_t spdy_request_header_frame_length;
1576 AddWrite(ConstructRstStreamVaryMismatchPacket(1));
1577 AddWrite(InnerConstructRequestHeadersPacket(
1578 2, stream_id_ + 2, !kIncludeVersion, kFin, DEFAULT_PRIORITY,
1579 &spdy_request_header_frame_length));
1580 AddWrite(ConstructAckPacket(3, 3, 1));
1581 AddWrite(ConstructRstStreamCancelledPacket(4));
1582 Initialize();
1583
1584 // Initialize the first stream, for receiving the promise on.
1585 request_.method = "GET";
1586 request_.url = GURL("http://www.example.org/");
1587
xunjieli5fafe142016-03-23 23:32:541588 EXPECT_EQ(OK,
1589 stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1590 net_log_.bound(), callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561591
1592 push_promise_["accept-encoding"] = "gzip";
1593 serialized_push_promise_ =
1594 SpdyUtils::SerializeUncompressedHeaders(push_promise_);
1595
1596 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
1597 // packet, but does it matter?
1598 ReceivePromise(promise_id_);
1599 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
1600
1601 request_.url = GURL(promise_url_);
1602
1603 // Make the second stream that will exercise the first step of the
1604 // server push rendezvous mechanism.
xunjieli5fafe142016-03-23 23:32:541605 EXPECT_EQ(OK, promised_stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1606 net_log_.bound(),
1607 callback_.callback()));
ckrasic3865ee0f2016-02-29 22:04:561608
1609 headers_.SetHeader("accept-encoding", "sdch");
1610
1611 // Now sending a matching request will rendezvous with the promised
1612 // stream, but pending secondary validation.
1613 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
1614 headers_, &response_, callback_.callback()));
1615
1616 // Receive the promised response headers.
1617 promised_response_["vary"] = "accept-encoding";
1618 response_headers_ = promised_response_;
1619 size_t spdy_response_headers_frame_length;
1620 ProcessPacket(InnerConstructResponseHeadersPacket(
1621 1, promise_id_, false, &spdy_response_headers_frame_length));
1622
1623 base::MessageLoop::current()->RunUntilIdle();
1624
1625 // Rendezvous should have failed due to vary mismatch, so the
1626 // promised stream should have been aborted, and instead we have a
1627 // new, regular client initiated stream.
1628 EXPECT_EQ(OK, callback_.WaitForResult());
1629
1630 // Not a server-initiated stream.
1631 EXPECT_NE(
1632 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
1633 ->id(),
1634 promise_id_);
1635
1636 // Instead, a new client-initiated stream.
1637 EXPECT_EQ(
1638 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
1639 ->id(),
1640 stream_id_ + 2);
1641
1642 // After rendezvous failure, the push stream has been cancelled.
1643 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
1644
1645 // The rest of the test verifies that the retried as
1646 // client-initiated version of |promised_stream_| works as intended.
1647
1648 // Ack the request.
1649 ProcessPacket(ConstructAckPacket(2, 0, 0));
1650
1651 SetResponse("404 Not Found", std::string());
1652 size_t spdy_response_header_frame_length;
1653 ProcessPacket(InnerConstructResponseHeadersPacket(
1654 3, stream_id_ + 2, kFin, &spdy_response_header_frame_length));
1655
1656 base::MessageLoop::current()->RunUntilIdle();
1657
1658 EXPECT_EQ(OK, promised_stream_->ReadResponseHeaders(callback_.callback()));
1659 ASSERT_TRUE(response_.headers.get());
1660 EXPECT_EQ(404, response_.headers->response_code());
1661 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1662 EXPECT_FALSE(response_.response_time.is_null());
1663 EXPECT_FALSE(response_.request_time.is_null());
1664
1665 // There is no body, so this should return immediately.
1666 EXPECT_EQ(
1667 0, promised_stream_->ReadResponseBody(
1668 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
1669 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
1670
1671 stream_->Close(true);
1672
1673 EXPECT_TRUE(AtEof());
1674
1675 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
1676 // headers and payload.
1677 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
1678 promised_stream_->GetTotalSentBytes());
1679 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length),
1680 promised_stream_->GetTotalReceivedBytes());
1681}
1682
[email protected]f702d572012-12-04 15:56:201683} // namespace test
[email protected]f702d572012-12-04 15:56:201684} // namespace net