blob: 7746ff256266c3c4ef6d0522596d2405093e3e3c [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright 2013 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/third_party/quiche/src/quic/core/http/quic_spdy_stream.h"
6
bncb9d5e792020-03-20 17:43:41 -07007#include <cstring>
QUICHE teama6ef0a62019-03-07 20:34:33 -05008#include <memory>
vasilvv872e7a32019-03-12 16:42:44 -07009#include <string>
QUICHE teama6ef0a62019-03-07 20:34:33 -050010#include <utility>
11
fayanga45ee8a2020-03-20 08:56:11 -070012#include "net/third_party/quiche/src/quic/core/crypto/null_encrypter.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050013#include "net/third_party/quiche/src/quic/core/http/http_encoder.h"
14#include "net/third_party/quiche/src/quic/core/http/spdy_utils.h"
15#include "net/third_party/quiche/src/quic/core/quic_connection.h"
16#include "net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer.h"
17#include "net/third_party/quiche/src/quic/core/quic_utils.h"
18#include "net/third_party/quiche/src/quic/core/quic_versions.h"
19#include "net/third_party/quiche/src/quic/core/quic_write_blocked_list.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050020#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
21#include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
22#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050023#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
bnc7e9155d2019-11-21 17:50:40 -080024#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h"
renjietangbb2e22a2019-09-12 15:46:39 -070025#include "net/third_party/quiche/src/quic/test_tools/quic_config_peer.h"
fayang8790d292020-03-18 13:17:23 -070026#include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050027#include "net/third_party/quiche/src/quic/test_tools/quic_flow_controller_peer.h"
28#include "net/third_party/quiche/src/quic/test_tools/quic_session_peer.h"
29#include "net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h"
30#include "net/third_party/quiche/src/quic/test_tools/quic_spdy_stream_peer.h"
31#include "net/third_party/quiche/src/quic/test_tools/quic_stream_peer.h"
32#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
bnc4e9283d2019-12-17 07:08:57 -080033#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
dmcardleba2fb7e2019-12-13 07:44:34 -080034#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
35#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050036
37using spdy::kV3HighestPriority;
38using spdy::kV3LowestPriority;
39using spdy::SpdyHeaderBlock;
40using spdy::SpdyPriority;
41using testing::_;
bncf8623cc2020-04-27 11:06:31 -070042using testing::AnyNumber;
QUICHE teama6ef0a62019-03-07 20:34:33 -050043using testing::AtLeast;
QUICHE team315d2882020-07-16 16:02:15 -070044using testing::DoAll;
bnc8d041302019-06-10 10:19:04 -070045using testing::ElementsAre;
QUICHE teama6ef0a62019-03-07 20:34:33 -050046using testing::Invoke;
bnc519216c2019-07-09 05:03:48 -070047using testing::InvokeWithoutArgs;
bncbdd303e2019-07-09 05:33:17 -070048using testing::MatchesRegex;
bnc8d041302019-06-10 10:19:04 -070049using testing::Pair;
QUICHE teama6ef0a62019-03-07 20:34:33 -050050using testing::Return;
bncf8623cc2020-04-27 11:06:31 -070051using testing::SaveArg;
QUICHE teama6ef0a62019-03-07 20:34:33 -050052using testing::StrictMock;
53
54namespace quic {
55namespace test {
56namespace {
57
58const bool kShouldProcessData = true;
bnc9f977e42019-06-07 11:36:34 -070059const char kDataFramePayload[] = "some data";
QUICHE teama6ef0a62019-03-07 20:34:33 -050060
fayang8790d292020-03-18 13:17:23 -070061class TestCryptoStream : public QuicCryptoStream, public QuicCryptoHandshaker {
62 public:
63 explicit TestCryptoStream(QuicSession* session)
64 : QuicCryptoStream(session),
65 QuicCryptoHandshaker(this, session),
66 encryption_established_(false),
67 one_rtt_keys_available_(false),
68 params_(new QuicCryptoNegotiatedParameters) {
69 // Simulate a negotiated cipher_suite with a fake value.
70 params_->cipher_suite = 1;
71 }
72
73 void OnHandshakeMessage(const CryptoHandshakeMessage& /*message*/) override {
74 encryption_established_ = true;
75 one_rtt_keys_available_ = true;
76 QuicErrorCode error;
77 std::string error_details;
78 session()->config()->SetInitialStreamFlowControlWindowToSend(
79 kInitialStreamFlowControlWindowForTest);
80 session()->config()->SetInitialSessionFlowControlWindowToSend(
81 kInitialSessionFlowControlWindowForTest);
dschinazie7c38a52020-05-29 15:25:45 -070082 if (session()->version().AuthenticatesHandshakeConnectionIds()) {
83 if (session()->perspective() == Perspective::IS_CLIENT) {
84 session()->config()->SetOriginalConnectionIdToSend(
85 session()->connection()->connection_id());
86 session()->config()->SetInitialSourceConnectionIdToSend(
87 session()->connection()->connection_id());
88 } else {
89 session()->config()->SetInitialSourceConnectionIdToSend(
90 session()->connection()->client_connection_id());
91 }
92 }
dschinazi47692202020-07-30 11:09:42 -070093 if (session()->version().UsesTls()) {
fayang8790d292020-03-18 13:17:23 -070094 TransportParameters transport_parameters;
95 EXPECT_TRUE(
96 session()->config()->FillTransportParameters(&transport_parameters));
97 error = session()->config()->ProcessTransportParameters(
renjietangc31106b2020-05-06 10:44:17 -070098 transport_parameters, CLIENT, /* is_resumption = */ false,
99 &error_details);
fayang8790d292020-03-18 13:17:23 -0700100 } else {
101 CryptoHandshakeMessage msg;
102 session()->config()->ToHandshakeMessage(&msg, transport_version());
103 error =
104 session()->config()->ProcessPeerHello(msg, CLIENT, &error_details);
105 }
106 EXPECT_THAT(error, IsQuicNoError());
fayanga45ee8a2020-03-20 08:56:11 -0700107 session()->OnNewEncryptionKeyAvailable(
108 ENCRYPTION_FORWARD_SECURE,
109 std::make_unique<NullEncrypter>(session()->perspective()));
fayang8790d292020-03-18 13:17:23 -0700110 session()->OnConfigNegotiated();
dschinazi47692202020-07-30 11:09:42 -0700111 if (session()->version().UsesTls()) {
fayangd18bfb92020-03-19 17:24:21 -0700112 session()->OnOneRttKeysAvailable();
113 } else {
114 session()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
115 }
dschinazi47692202020-07-30 11:09:42 -0700116 if (session()->version().HasHandshakeDone()) {
117 EXPECT_CALL(*this, HasPendingRetransmission());
118 }
fayang8790d292020-03-18 13:17:23 -0700119 session()->DiscardOldEncryptionKey(ENCRYPTION_INITIAL);
120 }
121
122 // QuicCryptoStream implementation
123 bool encryption_established() const override {
124 return encryption_established_;
125 }
126 bool one_rtt_keys_available() const override {
127 return one_rtt_keys_available_;
128 }
129 HandshakeState GetHandshakeState() const override {
130 return one_rtt_keys_available() ? HANDSHAKE_COMPLETE : HANDSHAKE_START;
131 }
nharperac52a862020-06-08 12:41:06 -0700132 void SetServerApplicationStateForResumption(
133 std::unique_ptr<ApplicationState> /*application_state*/) override {}
fayang8790d292020-03-18 13:17:23 -0700134 const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
135 const override {
136 return *params_;
137 }
138 CryptoMessageParser* crypto_message_parser() override {
139 return QuicCryptoHandshaker::crypto_message_parser();
140 }
141 void OnPacketDecrypted(EncryptionLevel /*level*/) override {}
142 void OnOneRttPacketAcknowledged() override {}
fayang44ae4e92020-04-28 13:09:42 -0700143 void OnHandshakePacketSent() override {}
fayanga6a85a82020-05-04 08:58:53 -0700144 void OnConnectionClosed(QuicErrorCode /*error*/,
145 ConnectionCloseSource /*source*/) override {}
fayang8790d292020-03-18 13:17:23 -0700146 void OnHandshakeDoneReceived() override {}
147
wub713afae2020-04-27 07:48:31 -0700148 MOCK_METHOD(void, OnCanWrite, (), (override));
fayang8790d292020-03-18 13:17:23 -0700149
150 bool HasPendingCryptoRetransmission() const override { return false; }
151
wub713afae2020-04-27 07:48:31 -0700152 MOCK_METHOD(bool, HasPendingRetransmission, (), (const, override));
fayang8790d292020-03-18 13:17:23 -0700153
154 private:
155 using QuicCryptoStream::session;
156
157 bool encryption_established_;
158 bool one_rtt_keys_available_;
159 QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params_;
160};
161
QUICHE teama6ef0a62019-03-07 20:34:33 -0500162class TestStream : public QuicSpdyStream {
163 public:
164 TestStream(QuicStreamId id,
165 QuicSpdySession* session,
166 bool should_process_data)
167 : QuicSpdyStream(id, session, BIDIRECTIONAL),
bnc7ffadb82020-04-07 10:01:30 -0700168 should_process_data_(should_process_data),
169 headers_payload_length_(0) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -0500170 ~TestStream() override = default;
171
172 using QuicSpdyStream::set_ack_listener;
173 using QuicStream::CloseWriteSide;
174 using QuicStream::WriteOrBufferData;
175
176 void OnBodyAvailable() override {
177 if (!should_process_data_) {
178 return;
179 }
180 char buffer[2048];
181 struct iovec vec;
182 vec.iov_base = buffer;
bnc4e9283d2019-12-17 07:08:57 -0800183 vec.iov_len = QUICHE_ARRAYSIZE(buffer);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500184 size_t bytes_read = Readv(&vec, 1);
vasilvvc48c8712019-03-11 13:38:16 -0700185 data_ += std::string(buffer, bytes_read);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500186 }
187
wub713afae2020-04-27 07:48:31 -0700188 MOCK_METHOD(void, WriteHeadersMock, (bool fin), ());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500189
190 size_t WriteHeadersImpl(spdy::SpdyHeaderBlock header_block,
191 bool fin,
192 QuicReferenceCountedPointer<QuicAckListenerInterface>
dschinazi17d42422019-06-18 16:35:07 -0700193 /*ack_listener*/) override {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500194 saved_headers_ = std::move(header_block);
195 WriteHeadersMock(fin);
renjietanga29a96a2019-10-10 12:47:50 -0700196 if (VersionUsesHttp3(transport_version())) {
renjietang2abedac2019-05-20 14:04:50 -0700197 // In this case, call QuicSpdyStream::WriteHeadersImpl() that does the
198 // actual work of closing the stream.
bncf8623cc2020-04-27 11:06:31 -0700199 return QuicSpdyStream::WriteHeadersImpl(saved_headers_.Clone(), fin,
200 nullptr);
renjietang2abedac2019-05-20 14:04:50 -0700201 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500202 return 0;
203 }
204
vasilvvc48c8712019-03-11 13:38:16 -0700205 const std::string& data() const { return data_; }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500206 const spdy::SpdyHeaderBlock& saved_headers() const { return saved_headers_; }
207
bnc8d041302019-06-10 10:19:04 -0700208 // Expose protected accessor.
209 const QuicStreamSequencer* sequencer() const {
210 return QuicStream::sequencer();
211 }
212
bnc7ffadb82020-04-07 10:01:30 -0700213 void OnStreamHeaderList(bool fin,
214 size_t frame_len,
215 const QuicHeaderList& header_list) override {
216 headers_payload_length_ = frame_len;
217 QuicSpdyStream::OnStreamHeaderList(fin, frame_len, header_list);
218 }
219
220 size_t headers_payload_length() const { return headers_payload_length_; }
221
QUICHE teama6ef0a62019-03-07 20:34:33 -0500222 private:
223 bool should_process_data_;
224 spdy::SpdyHeaderBlock saved_headers_;
vasilvvc48c8712019-03-11 13:38:16 -0700225 std::string data_;
bnc7ffadb82020-04-07 10:01:30 -0700226 size_t headers_payload_length_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500227};
228
fayang8790d292020-03-18 13:17:23 -0700229class TestSession : public MockQuicSpdySession {
230 public:
231 explicit TestSession(QuicConnection* connection)
232 : MockQuicSpdySession(connection, /*create_mock_crypto_stream=*/false),
233 crypto_stream_(this) {}
234
235 TestCryptoStream* GetMutableCryptoStream() override {
236 return &crypto_stream_;
237 }
238
239 const TestCryptoStream* GetCryptoStream() const override {
240 return &crypto_stream_;
241 }
242
243 private:
244 StrictMock<TestCryptoStream> crypto_stream_;
245};
246
QUICHE teama6ef0a62019-03-07 20:34:33 -0500247class TestMockUpdateStreamSession : public MockQuicSpdySession {
248 public:
249 explicit TestMockUpdateStreamSession(QuicConnection* connection)
fayang476683a2019-07-25 12:42:16 -0700250 : MockQuicSpdySession(connection),
251 expected_precedence_(
252 spdy::SpdyStreamPrecedence(QuicStream::kDefaultPriority)) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -0500253
fayang476683a2019-07-25 12:42:16 -0700254 void UpdateStreamPriority(
255 QuicStreamId id,
256 const spdy::SpdyStreamPrecedence& precedence) override {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500257 EXPECT_EQ(id, expected_stream_->id());
fayang476683a2019-07-25 12:42:16 -0700258 EXPECT_EQ(expected_precedence_, precedence);
259 EXPECT_EQ(expected_precedence_, expected_stream_->precedence());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500260 }
261
262 void SetExpectedStream(QuicSpdyStream* stream) { expected_stream_ = stream; }
fayang476683a2019-07-25 12:42:16 -0700263 void SetExpectedPriority(const spdy::SpdyStreamPrecedence& precedence) {
264 expected_precedence_ = precedence;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500265 }
266
267 private:
268 QuicSpdyStream* expected_stream_;
fayang476683a2019-07-25 12:42:16 -0700269 spdy::SpdyStreamPrecedence expected_precedence_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500270};
271
272class QuicSpdyStreamTest : public QuicTestWithParam<ParsedQuicVersion> {
bnc9f977e42019-06-07 11:36:34 -0700273 protected:
QUICHE teama6ef0a62019-03-07 20:34:33 -0500274 QuicSpdyStreamTest() {
275 headers_[":host"] = "www.google.com";
276 headers_[":path"] = "/index.hml";
277 headers_[":scheme"] = "https";
278 headers_["cookie"] =
279 "__utma=208381060.1228362404.1372200928.1372200928.1372200928.1; "
280 "__utmc=160408618; "
281 "GX=DQAAAOEAAACWJYdewdE9rIrW6qw3PtVi2-d729qaa-74KqOsM1NVQblK4VhX"
282 "hoALMsy6HOdDad2Sz0flUByv7etmo3mLMidGrBoljqO9hSVA40SLqpG_iuKKSHX"
283 "RW3Np4bq0F0SDGDNsW0DSmTS9ufMRrlpARJDS7qAI6M3bghqJp4eABKZiRqebHT"
284 "pMU-RXvTI5D5oCF1vYxYofH_l1Kviuiy3oQ1kS1enqWgbhJ2t61_SNdv-1XJIS0"
285 "O3YeHLmVCs62O6zp89QwakfAWK9d3IDQvVSJzCQsvxvNIvaZFa567MawWlXg0Rh"
286 "1zFMi5vzcns38-8_Sns; "
287 "GA=v*2%2Fmem*57968640*47239936%2Fmem*57968640*47114716%2Fno-nm-"
288 "yj*15%2Fno-cc-yj*5%2Fpc-ch*133685%2Fpc-s-cr*133947%2Fpc-s-t*1339"
289 "47%2Fno-nm-yj*4%2Fno-cc-yj*1%2Fceft-as*1%2Fceft-nqas*0%2Fad-ra-c"
290 "v_p%2Fad-nr-cv_p-f*1%2Fad-v-cv_p*859%2Fad-ns-cv_p-f*1%2Ffn-v-ad%"
291 "2Fpc-t*250%2Fpc-cm*461%2Fpc-s-cr*722%2Fpc-s-t*722%2Fau_p*4"
292 "SICAID=AJKiYcHdKgxum7KMXG0ei2t1-W4OD1uW-ecNsCqC0wDuAXiDGIcT_HA2o1"
293 "3Rs1UKCuBAF9g8rWNOFbxt8PSNSHFuIhOo2t6bJAVpCsMU5Laa6lewuTMYI8MzdQP"
294 "ARHKyW-koxuhMZHUnGBJAM1gJODe0cATO_KGoX4pbbFxxJ5IicRxOrWK_5rU3cdy6"
295 "edlR9FsEdH6iujMcHkbE5l18ehJDwTWmBKBzVD87naobhMMrF6VvnDGxQVGp9Ir_b"
296 "Rgj3RWUoPumQVCxtSOBdX0GlJOEcDTNCzQIm9BSfetog_eP_TfYubKudt5eMsXmN6"
297 "QnyXHeGeK2UINUzJ-D30AFcpqYgH9_1BvYSpi7fc7_ydBU8TaD8ZRxvtnzXqj0RfG"
298 "tuHghmv3aD-uzSYJ75XDdzKdizZ86IG6Fbn1XFhYZM-fbHhm3mVEXnyRW4ZuNOLFk"
299 "Fas6LMcVC6Q8QLlHYbXBpdNFuGbuZGUnav5C-2I_-46lL0NGg3GewxGKGHvHEfoyn"
300 "EFFlEYHsBQ98rXImL8ySDycdLEFvBPdtctPmWCfTxwmoSMLHU2SCVDhbqMWU5b0yr"
301 "JBCScs_ejbKaqBDoB7ZGxTvqlrB__2ZmnHHjCr8RgMRtKNtIeuZAo ";
302 }
303
bnc8d041302019-06-10 10:19:04 -0700304 ~QuicSpdyStreamTest() override = default;
305
bnc2e963aa2019-07-31 18:03:17 -0700306 // Return QPACK-encoded header block without using the dynamic table.
307 std::string EncodeQpackHeaders(
dmcardleba2fb7e2019-12-13 07:44:34 -0800308 std::vector<std::pair<quiche::QuicheStringPiece,
309 quiche::QuicheStringPiece>> headers) {
bnc2e963aa2019-07-31 18:03:17 -0700310 SpdyHeaderBlock header_block;
311 for (const auto& header_field : headers) {
312 header_block.AppendValueOrAddHeader(header_field.first,
313 header_field.second);
314 }
315
316 return EncodeQpackHeaders(header_block);
317 }
318
319 // Return QPACK-encoded header block without using the dynamic table.
320 std::string EncodeQpackHeaders(const SpdyHeaderBlock& header) {
renjietangc2aa5cb2019-06-20 12:22:53 -0700321 NoopQpackStreamSenderDelegate encoder_stream_sender_delegate;
vasilvv0fc587f2019-09-06 13:33:08 -0700322 auto qpack_encoder = std::make_unique<QpackEncoder>(session_.get());
renjietang8a2df8f2019-08-07 10:43:52 -0700323 qpack_encoder->set_qpack_stream_sender_delegate(
324 &encoder_stream_sender_delegate);
bnc2e963aa2019-07-31 18:03:17 -0700325 // QpackEncoder does not use the dynamic table by default,
326 // therefore the value of |stream_id| does not matter.
bnc609c24e2019-09-10 05:24:32 -0700327 return qpack_encoder->EncodeHeaderList(/* stream_id = */ 0, header,
328 nullptr);
renjietangbd1a0392019-05-31 11:36:24 -0700329 }
330
QUICHE teama6ef0a62019-03-07 20:34:33 -0500331 void Initialize(bool stream_should_process_data) {
renjietang7498c8c2019-07-02 19:28:42 -0700332 InitializeWithPerspective(stream_should_process_data,
333 Perspective::IS_SERVER);
334 }
335
336 void InitializeWithPerspective(bool stream_should_process_data,
337 Perspective perspective) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500338 connection_ = new StrictMock<MockQuicConnection>(
renjietang7498c8c2019-07-02 19:28:42 -0700339 &helper_, &alarm_factory_, perspective, SupportedVersions(GetParam()));
fayang8790d292020-03-18 13:17:23 -0700340 session_ = std::make_unique<StrictMock<TestSession>>(connection_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500341 session_->Initialize();
fayang6a258412020-05-28 08:57:12 -0700342 if (connection_->version().SupportsAntiAmplificationLimit()) {
343 QuicConnectionPeer::SetAddressValidated(connection_);
344 }
fayangd62ea772020-04-17 06:32:16 -0700345 connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
renjietang41a1b412020-02-27 15:05:14 -0800346 ON_CALL(*session_, WritevData(_, _, _, _, _, _))
renjietang7c239172020-02-21 13:50:39 -0800347 .WillByDefault(
348 Invoke(session_.get(), &MockQuicSpdySession::ConsumeData));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500349
350 stream_ =
351 new StrictMock<TestStream>(GetNthClientInitiatedBidirectionalId(0),
352 session_.get(), stream_should_process_data);
353 session_->ActivateStream(QuicWrapUnique(stream_));
354 stream2_ =
355 new StrictMock<TestStream>(GetNthClientInitiatedBidirectionalId(1),
356 session_.get(), stream_should_process_data);
357 session_->ActivateStream(QuicWrapUnique(stream2_));
renjietangbb2e22a2019-09-12 15:46:39 -0700358 QuicConfigPeer::SetReceivedInitialSessionFlowControlWindow(
359 session_->config(), kMinimumFlowControlSendWindow);
dschinazi18cdf132019-10-09 16:08:18 -0700360 QuicConfigPeer::SetReceivedInitialMaxStreamDataBytesUnidirectional(
361 session_->config(), kMinimumFlowControlSendWindow);
362 QuicConfigPeer::SetReceivedInitialMaxStreamDataBytesIncomingBidirectional(
363 session_->config(), kMinimumFlowControlSendWindow);
364 QuicConfigPeer::SetReceivedInitialMaxStreamDataBytesOutgoingBidirectional(
365 session_->config(), kMinimumFlowControlSendWindow);
renjietange6d94672020-01-07 10:30:10 -0800366 QuicConfigPeer::SetReceivedMaxUnidirectionalStreams(session_->config(), 10);
renjietangbb2e22a2019-09-12 15:46:39 -0700367 session_->OnConfigNegotiated();
rchee322322019-10-11 14:56:03 -0700368 if (UsesHttp3()) {
renjietangd6e461b2020-02-04 16:16:35 -0800369 // The control stream will write the stream type, a greased frame, and
370 // SETTINGS frame.
371 int num_control_stream_writes = 3;
bnccd3c4b52020-01-10 11:13:18 -0800372 auto send_control_stream =
373 QuicSpdySessionPeer::GetSendControlStream(session_.get());
renjietang41a1b412020-02-27 15:05:14 -0800374 EXPECT_CALL(*session_,
375 WritevData(send_control_stream->id(), _, _, _, _, _))
rch4cd745d2019-12-03 13:19:41 -0800376 .Times(num_control_stream_writes);
rchee322322019-10-11 14:56:03 -0700377 }
fayang8790d292020-03-18 13:17:23 -0700378 TestCryptoStream* crypto_stream = session_->GetMutableCryptoStream();
bncf8623cc2020-04-27 11:06:31 -0700379 EXPECT_CALL(*crypto_stream, HasPendingRetransmission()).Times(AnyNumber());
fayang8790d292020-03-18 13:17:23 -0700380
381 if (connection_->version().HasHandshakeDone() &&
382 session_->perspective() == Perspective::IS_SERVER) {
383 EXPECT_CALL(*connection_, SendControlFrame(_))
384 .WillOnce(Invoke(&ClearControlFrame));
385 }
386 CryptoHandshakeMessage message;
387 session_->GetMutableCryptoStream()->OnHandshakeMessage(message);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500388 }
389
390 QuicHeaderList ProcessHeaders(bool fin, const SpdyHeaderBlock& headers) {
391 QuicHeaderList h = AsHeaderList(headers);
392 stream_->OnStreamHeaderList(fin, h.uncompressed_header_bytes(), h);
393 return h;
394 }
395
396 QuicStreamId GetNthClientInitiatedBidirectionalId(int n) {
397 return GetNthClientInitiatedBidirectionalStreamId(
398 connection_->transport_version(), n);
399 }
400
renjietanga29a96a2019-10-10 12:47:50 -0700401 bool UsesHttp3() const {
402 return VersionUsesHttp3(GetParam().transport_version);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500403 }
404
bnc2e963aa2019-07-31 18:03:17 -0700405 // Construct HEADERS frame with QPACK-encoded |headers| without using the
406 // dynamic table.
407 std::string HeadersFrame(
dmcardleba2fb7e2019-12-13 07:44:34 -0800408 std::vector<std::pair<quiche::QuicheStringPiece,
409 quiche::QuicheStringPiece>> headers) {
bnc2e963aa2019-07-31 18:03:17 -0700410 return HeadersFrame(EncodeQpackHeaders(headers));
411 }
412
413 // Construct HEADERS frame with QPACK-encoded |headers| without using the
414 // dynamic table.
415 std::string HeadersFrame(const SpdyHeaderBlock& headers) {
416 return HeadersFrame(EncodeQpackHeaders(headers));
417 }
418
419 // Construct HEADERS frame with given payload.
dmcardleba2fb7e2019-12-13 07:44:34 -0800420 std::string HeadersFrame(quiche::QuicheStringPiece payload) {
bnc9f977e42019-06-07 11:36:34 -0700421 std::unique_ptr<char[]> headers_buffer;
422 QuicByteCount headers_frame_header_length =
bnc46942722019-10-29 11:56:21 -0700423 HttpEncoder::SerializeHeadersFrameHeader(payload.length(),
424 &headers_buffer);
dmcardleba2fb7e2019-12-13 07:44:34 -0800425 quiche::QuicheStringPiece headers_frame_header(headers_buffer.get(),
426 headers_frame_header_length);
427 return quiche::QuicheStrCat(headers_frame_header, payload);
bnc9f977e42019-06-07 11:36:34 -0700428 }
429
bnc7ffadb82020-04-07 10:01:30 -0700430 // Construct PUSH_PROMISE frame with given payload.
431 std::string SerializePushPromiseFrame(PushId push_id,
432 quiche::QuicheStringPiece payload) {
433 PushPromiseFrame frame;
434 frame.push_id = push_id;
435 frame.headers = payload;
436 std::unique_ptr<char[]> push_promise_buffer;
437 QuicByteCount push_promise_frame_header_length =
438 HttpEncoder::SerializePushPromiseFrameWithOnlyPushId(
439 frame, &push_promise_buffer);
440 quiche::QuicheStringPiece push_promise_frame_header(
441 push_promise_buffer.get(), push_promise_frame_header_length);
442 return quiche::QuicheStrCat(push_promise_frame_header, payload);
443 }
444
dmcardleba2fb7e2019-12-13 07:44:34 -0800445 std::string DataFrame(quiche::QuicheStringPiece payload) {
bnc9f977e42019-06-07 11:36:34 -0700446 std::unique_ptr<char[]> data_buffer;
447 QuicByteCount data_frame_header_length =
bnc46942722019-10-29 11:56:21 -0700448 HttpEncoder::SerializeDataFrameHeader(payload.length(), &data_buffer);
dmcardleba2fb7e2019-12-13 07:44:34 -0800449 quiche::QuicheStringPiece data_frame_header(data_buffer.get(),
450 data_frame_header_length);
451 return quiche::QuicheStrCat(data_frame_header, payload);
bnc9f977e42019-06-07 11:36:34 -0700452 }
453
dmcardleba2fb7e2019-12-13 07:44:34 -0800454 std::string UnknownFrame(uint64_t frame_type,
455 quiche::QuicheStringPiece payload) {
bnc25827c42019-07-29 08:57:24 -0700456 std::string frame;
457 const size_t length = QuicDataWriter::GetVarInt62Len(frame_type) +
458 QuicDataWriter::GetVarInt62Len(payload.size()) +
459 payload.size();
460 frame.resize(length);
461
fayangf0041ed2019-07-31 02:39:45 -0700462 QuicDataWriter writer(length, const_cast<char*>(frame.data()));
bnc25827c42019-07-29 08:57:24 -0700463 writer.WriteVarInt62(frame_type);
464 writer.WriteStringPieceVarInt62(payload);
465 // Even though integers can be encoded with different lengths,
466 // QuicDataWriter is expected to produce an encoding in Write*() of length
467 // promised in GetVarInt62Len().
468 DCHECK_EQ(length, writer.length());
469
470 return frame;
471 }
472
QUICHE teama6ef0a62019-03-07 20:34:33 -0500473 MockQuicConnectionHelper helper_;
474 MockAlarmFactory alarm_factory_;
475 MockQuicConnection* connection_;
fayang8790d292020-03-18 13:17:23 -0700476 std::unique_ptr<TestSession> session_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500477
478 // Owned by the |session_|.
479 TestStream* stream_;
480 TestStream* stream2_;
481
482 SpdyHeaderBlock headers_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500483};
484
vasilvvc48c8712019-03-11 13:38:16 -0700485INSTANTIATE_TEST_SUITE_P(Tests,
486 QuicSpdyStreamTest,
dschinazi142051a2019-09-18 18:17:29 -0700487 ::testing::ValuesIn(AllSupportedVersions()),
488 ::testing::PrintToStringParamName());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500489
490TEST_P(QuicSpdyStreamTest, ProcessHeaderList) {
491 Initialize(kShouldProcessData);
492
fayang476683a2019-07-25 12:42:16 -0700493 stream_->OnStreamHeadersPriority(
494 spdy::SpdyStreamPrecedence(kV3HighestPriority));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500495 ProcessHeaders(false, headers_);
496 EXPECT_EQ("", stream_->data());
497 EXPECT_FALSE(stream_->header_list().empty());
498 EXPECT_FALSE(stream_->IsDoneReading());
499}
500
501TEST_P(QuicSpdyStreamTest, ProcessTooLargeHeaderList) {
502 Initialize(kShouldProcessData);
503
bnc446887e2019-11-27 13:08:28 -0800504 if (!UsesHttp3()) {
505 QuicHeaderList headers;
506 stream_->OnStreamHeadersPriority(
507 spdy::SpdyStreamPrecedence(kV3HighestPriority));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500508
renjietang2abedac2019-05-20 14:04:50 -0700509 EXPECT_CALL(*session_,
renjietang9946bc02020-07-16 15:14:27 -0700510 SendRstStream(stream_->id(), QUIC_HEADERS_TOO_LARGE, 0, _));
bnc446887e2019-11-27 13:08:28 -0800511 stream_->OnStreamHeaderList(false, 1 << 20, headers);
renjietang2abedac2019-05-20 14:04:50 -0700512
bncc5769502019-11-27 10:01:44 -0800513 EXPECT_THAT(stream_->stream_error(), IsStreamError(QUIC_HEADERS_TOO_LARGE));
bnc446887e2019-11-27 13:08:28 -0800514
515 return;
renjietang2abedac2019-05-20 14:04:50 -0700516 }
bnc446887e2019-11-27 13:08:28 -0800517
518 // Header list size includes 32 bytes for overhead per header field.
519 session_->set_max_inbound_header_list_size(40);
520 std::string headers =
521 HeadersFrame({std::make_pair("foo", "too long headers")});
522
523 QuicStreamFrame frame(stream_->id(), false, 0, headers);
524
bnc52ffb982020-05-01 11:31:28 -0700525 EXPECT_CALL(*session_,
renjietang9946bc02020-07-16 15:14:27 -0700526 SendRstStream(stream_->id(), QUIC_HEADERS_TOO_LARGE, 0, _));
bnc52ffb982020-05-01 11:31:28 -0700527
528 auto qpack_decoder_stream =
529 QuicSpdySessionPeer::GetQpackDecoderSendStream(session_.get());
530 // Stream type and stream cancellation.
531 EXPECT_CALL(*session_,
532 WritevData(qpack_decoder_stream->id(), _, _, NO_FIN, _, _))
533 .Times(2);
bnc446887e2019-11-27 13:08:28 -0800534
535 stream_->OnStreamFrame(frame);
bnc52ffb982020-05-01 11:31:28 -0700536 EXPECT_THAT(stream_->stream_error(), IsStreamError(QUIC_HEADERS_TOO_LARGE));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500537}
538
539TEST_P(QuicSpdyStreamTest, ProcessHeaderListWithFin) {
540 Initialize(kShouldProcessData);
541
542 size_t total_bytes = 0;
543 QuicHeaderList headers;
544 for (auto p : headers_) {
545 headers.OnHeader(p.first, p.second);
546 total_bytes += p.first.size() + p.second.size();
547 }
fayang476683a2019-07-25 12:42:16 -0700548 stream_->OnStreamHeadersPriority(
549 spdy::SpdyStreamPrecedence(kV3HighestPriority));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500550 stream_->OnStreamHeaderList(true, total_bytes, headers);
551 EXPECT_EQ("", stream_->data());
552 EXPECT_FALSE(stream_->header_list().empty());
553 EXPECT_FALSE(stream_->IsDoneReading());
renjietang6c066562019-11-04 17:05:59 -0800554 EXPECT_TRUE(stream_->HasReceivedFinalOffset());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500555}
556
bnc677451a2019-06-07 10:13:30 -0700557// A valid status code should be 3-digit integer. The first digit should be in
558// the range of [1, 5]. All the others are invalid.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500559TEST_P(QuicSpdyStreamTest, ParseHeaderStatusCode) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500560 Initialize(kShouldProcessData);
561 int status_code = 0;
562
563 // Valid status codes.
564 headers_[":status"] = "404";
565 EXPECT_TRUE(stream_->ParseHeaderStatusCode(headers_, &status_code));
566 EXPECT_EQ(404, status_code);
567
568 headers_[":status"] = "100";
569 EXPECT_TRUE(stream_->ParseHeaderStatusCode(headers_, &status_code));
570 EXPECT_EQ(100, status_code);
571
572 headers_[":status"] = "599";
573 EXPECT_TRUE(stream_->ParseHeaderStatusCode(headers_, &status_code));
574 EXPECT_EQ(599, status_code);
575
576 // Invalid status codes.
577 headers_[":status"] = "010";
578 EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
579
580 headers_[":status"] = "600";
581 EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
582
583 headers_[":status"] = "200 ok";
584 EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
585
586 headers_[":status"] = "2000";
587 EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
588
589 headers_[":status"] = "+200";
590 EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
591
592 headers_[":status"] = "+20";
593 EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
594
595 headers_[":status"] = "-10";
596 EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
597
598 headers_[":status"] = "-100";
599 EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
600
601 // Leading or trailing spaces are also invalid.
602 headers_[":status"] = " 200";
603 EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
604
605 headers_[":status"] = "200 ";
606 EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
607
608 headers_[":status"] = " 200 ";
609 EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
610
611 headers_[":status"] = " ";
612 EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
613}
614
615TEST_P(QuicSpdyStreamTest, MarkHeadersConsumed) {
616 Initialize(kShouldProcessData);
617
vasilvvc48c8712019-03-11 13:38:16 -0700618 std::string body = "this is the body";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500619 QuicHeaderList headers = ProcessHeaders(false, headers_);
620 EXPECT_EQ(headers, stream_->header_list());
621
622 stream_->ConsumeHeaderList();
623 EXPECT_EQ(QuicHeaderList(), stream_->header_list());
624}
625
QUICHE team396d1092019-03-20 10:21:07 -0700626TEST_P(QuicSpdyStreamTest, ProcessWrongFramesOnSpdyStream) {
renjietanga29a96a2019-10-10 12:47:50 -0700627 if (!UsesHttp3()) {
QUICHE team396d1092019-03-20 10:21:07 -0700628 return;
629 }
bnc677451a2019-06-07 10:13:30 -0700630
bnc677451a2019-06-07 10:13:30 -0700631 Initialize(kShouldProcessData);
fayang8790d292020-03-18 13:17:23 -0700632 testing::InSequence s;
QUICHE team396d1092019-03-20 10:21:07 -0700633 connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
634 GoAwayFrame goaway;
bnc8b6881b2020-07-21 10:44:43 -0700635 goaway.id = 0x1;
QUICHE team396d1092019-03-20 10:21:07 -0700636 std::unique_ptr<char[]> buffer;
bnc46942722019-10-29 11:56:21 -0700637 QuicByteCount header_length =
638 HttpEncoder::SerializeGoAwayFrame(goaway, &buffer);
QUICHE team396d1092019-03-20 10:21:07 -0700639 std::string data = std::string(buffer.get(), header_length);
640
641 EXPECT_EQ("", stream_->data());
642 QuicHeaderList headers = ProcessHeaders(false, headers_);
643 EXPECT_EQ(headers, stream_->header_list());
644 stream_->ConsumeHeaderList();
645 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
dmcardleba2fb7e2019-12-13 07:44:34 -0800646 quiche::QuicheStringPiece(data));
QUICHE team396d1092019-03-20 10:21:07 -0700647
bncdfabdfb2020-01-17 17:46:40 -0800648 EXPECT_CALL(*connection_,
649 CloseConnection(QUIC_HTTP_FRAME_UNEXPECTED_ON_SPDY_STREAM, _, _))
QUICHE team396d1092019-03-20 10:21:07 -0700650 .WillOnce(
651 (Invoke([this](QuicErrorCode error, const std::string& error_details,
652 ConnectionCloseBehavior connection_close_behavior) {
653 connection_->ReallyCloseConnection(error, error_details,
654 connection_close_behavior);
655 })));
ianswettdc1e7ab2019-05-03 16:10:44 -0700656 EXPECT_CALL(*connection_, SendConnectionClosePacket(_, _));
fkastenholz5d880a92019-06-21 09:01:56 -0700657 EXPECT_CALL(*session_, OnConnectionClosed(_, _))
658 .WillOnce(Invoke([this](const QuicConnectionCloseFrame& frame,
659 ConnectionCloseSource source) {
660 session_->ReallyOnConnectionClosed(frame, source);
661 }));
renjietang9946bc02020-07-16 15:14:27 -0700662 EXPECT_CALL(*session_, SendRstStream(_, _, _, _));
663 EXPECT_CALL(*session_, SendRstStream(_, _, _, _));
QUICHE team396d1092019-03-20 10:21:07 -0700664
665 stream_->OnStreamFrame(frame);
666}
667
bncdfabdfb2020-01-17 17:46:40 -0800668TEST_P(QuicSpdyStreamTest, Http3FrameError) {
669 if (!UsesHttp3()) {
670 return;
671 }
672
673 Initialize(kShouldProcessData);
674
675 // PUSH_PROMISE frame with empty payload is considered invalid.
676 std::string invalid_http3_frame = quiche::QuicheTextUtils::HexDecode("0500");
677 QuicStreamFrame stream_frame(stream_->id(), /* fin = */ false,
678 /* offset = */ 0, invalid_http3_frame);
679
680 EXPECT_CALL(*connection_, CloseConnection(QUIC_HTTP_FRAME_ERROR, _, _));
681 stream_->OnStreamFrame(stream_frame);
682}
683
684TEST_P(QuicSpdyStreamTest, UnexpectedHttp3Frame) {
685 if (!UsesHttp3()) {
686 return;
687 }
688
689 Initialize(kShouldProcessData);
690
691 // SETTINGS frame with empty payload.
692 std::string settings = quiche::QuicheTextUtils::HexDecode("0400");
693 QuicStreamFrame stream_frame(stream_->id(), /* fin = */ false,
694 /* offset = */ 0, settings);
695
696 EXPECT_CALL(*connection_,
697 CloseConnection(QUIC_HTTP_FRAME_UNEXPECTED_ON_SPDY_STREAM, _, _));
698 stream_->OnStreamFrame(stream_frame);
699}
700
QUICHE teama6ef0a62019-03-07 20:34:33 -0500701TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBody) {
702 Initialize(kShouldProcessData);
703
vasilvvc48c8712019-03-11 13:38:16 -0700704 std::string body = "this is the body";
renjietanga29a96a2019-10-10 12:47:50 -0700705 std::string data = UsesHttp3() ? DataFrame(body) : body;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500706
707 EXPECT_EQ("", stream_->data());
708 QuicHeaderList headers = ProcessHeaders(false, headers_);
709 EXPECT_EQ(headers, stream_->header_list());
710 stream_->ConsumeHeaderList();
711 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
dmcardleba2fb7e2019-12-13 07:44:34 -0800712 quiche::QuicheStringPiece(data));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500713 stream_->OnStreamFrame(frame);
714 EXPECT_EQ(QuicHeaderList(), stream_->header_list());
715 EXPECT_EQ(body, stream_->data());
716}
717
718TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBodyFragments) {
vasilvvc48c8712019-03-11 13:38:16 -0700719 std::string body = "this is the body";
renjietanga29a96a2019-10-10 12:47:50 -0700720 std::string data = UsesHttp3() ? DataFrame(body) : body;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500721
722 for (size_t fragment_size = 1; fragment_size < data.size(); ++fragment_size) {
723 Initialize(kShouldProcessData);
724 QuicHeaderList headers = ProcessHeaders(false, headers_);
725 ASSERT_EQ(headers, stream_->header_list());
726 stream_->ConsumeHeaderList();
727 for (size_t offset = 0; offset < data.size(); offset += fragment_size) {
728 size_t remaining_data = data.size() - offset;
dmcardleba2fb7e2019-12-13 07:44:34 -0800729 quiche::QuicheStringPiece fragment(
730 data.data() + offset, std::min(fragment_size, remaining_data));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500731 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false,
dmcardleba2fb7e2019-12-13 07:44:34 -0800732 offset, quiche::QuicheStringPiece(fragment));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500733 stream_->OnStreamFrame(frame);
734 }
735 ASSERT_EQ(body, stream_->data()) << "fragment_size: " << fragment_size;
736 }
737}
738
739TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBodyFragmentsSplit) {
vasilvvc48c8712019-03-11 13:38:16 -0700740 std::string body = "this is the body";
renjietanga29a96a2019-10-10 12:47:50 -0700741 std::string data = UsesHttp3() ? DataFrame(body) : body;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500742
743 for (size_t split_point = 1; split_point < data.size() - 1; ++split_point) {
744 Initialize(kShouldProcessData);
745 QuicHeaderList headers = ProcessHeaders(false, headers_);
746 ASSERT_EQ(headers, stream_->header_list());
747 stream_->ConsumeHeaderList();
748
dmcardleba2fb7e2019-12-13 07:44:34 -0800749 quiche::QuicheStringPiece fragment1(data.data(), split_point);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500750 QuicStreamFrame frame1(GetNthClientInitiatedBidirectionalId(0), false, 0,
dmcardleba2fb7e2019-12-13 07:44:34 -0800751 quiche::QuicheStringPiece(fragment1));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500752 stream_->OnStreamFrame(frame1);
753
dmcardleba2fb7e2019-12-13 07:44:34 -0800754 quiche::QuicheStringPiece fragment2(data.data() + split_point,
755 data.size() - split_point);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500756 QuicStreamFrame frame2(GetNthClientInitiatedBidirectionalId(0), false,
dmcardleba2fb7e2019-12-13 07:44:34 -0800757 split_point, quiche::QuicheStringPiece(fragment2));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500758 stream_->OnStreamFrame(frame2);
759
760 ASSERT_EQ(body, stream_->data()) << "split_point: " << split_point;
761 }
762}
763
764TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBodyReadv) {
765 Initialize(!kShouldProcessData);
766
vasilvvc48c8712019-03-11 13:38:16 -0700767 std::string body = "this is the body";
renjietanga29a96a2019-10-10 12:47:50 -0700768 std::string data = UsesHttp3() ? DataFrame(body) : body;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500769
770 ProcessHeaders(false, headers_);
771 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
dmcardleba2fb7e2019-12-13 07:44:34 -0800772 quiche::QuicheStringPiece(data));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500773 stream_->OnStreamFrame(frame);
774 stream_->ConsumeHeaderList();
775
776 char buffer[2048];
bnc4e9283d2019-12-17 07:08:57 -0800777 ASSERT_LT(data.length(), QUICHE_ARRAYSIZE(buffer));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500778 struct iovec vec;
779 vec.iov_base = buffer;
bnc4e9283d2019-12-17 07:08:57 -0800780 vec.iov_len = QUICHE_ARRAYSIZE(buffer);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500781
782 size_t bytes_read = stream_->Readv(&vec, 1);
QUICHE team396d1092019-03-20 10:21:07 -0700783 QuicStreamPeer::CloseReadSide(stream_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500784 EXPECT_EQ(body.length(), bytes_read);
vasilvvc48c8712019-03-11 13:38:16 -0700785 EXPECT_EQ(body, std::string(buffer, bytes_read));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500786}
787
788TEST_P(QuicSpdyStreamTest, ProcessHeadersAndLargeBodySmallReadv) {
789 Initialize(kShouldProcessData);
vasilvvc48c8712019-03-11 13:38:16 -0700790 std::string body(12 * 1024, 'a');
renjietanga29a96a2019-10-10 12:47:50 -0700791 std::string data = UsesHttp3() ? DataFrame(body) : body;
bnc9f977e42019-06-07 11:36:34 -0700792
QUICHE teama6ef0a62019-03-07 20:34:33 -0500793 ProcessHeaders(false, headers_);
794 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
dmcardleba2fb7e2019-12-13 07:44:34 -0800795 quiche::QuicheStringPiece(data));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500796 stream_->OnStreamFrame(frame);
797 stream_->ConsumeHeaderList();
798 char buffer[2048];
799 char buffer2[2048];
800 struct iovec vec[2];
801 vec[0].iov_base = buffer;
bnc4e9283d2019-12-17 07:08:57 -0800802 vec[0].iov_len = QUICHE_ARRAYSIZE(buffer);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500803 vec[1].iov_base = buffer2;
bnc4e9283d2019-12-17 07:08:57 -0800804 vec[1].iov_len = QUICHE_ARRAYSIZE(buffer2);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500805 size_t bytes_read = stream_->Readv(vec, 2);
806 EXPECT_EQ(2048u * 2, bytes_read);
vasilvvc48c8712019-03-11 13:38:16 -0700807 EXPECT_EQ(body.substr(0, 2048), std::string(buffer, 2048));
808 EXPECT_EQ(body.substr(2048, 2048), std::string(buffer2, 2048));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500809}
810
811TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBodyMarkConsumed) {
812 Initialize(!kShouldProcessData);
813
vasilvvc48c8712019-03-11 13:38:16 -0700814 std::string body = "this is the body";
renjietanga29a96a2019-10-10 12:47:50 -0700815 std::string data = UsesHttp3() ? DataFrame(body) : body;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500816
817 ProcessHeaders(false, headers_);
818 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
dmcardleba2fb7e2019-12-13 07:44:34 -0800819 quiche::QuicheStringPiece(data));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500820 stream_->OnStreamFrame(frame);
821 stream_->ConsumeHeaderList();
822
823 struct iovec vec;
824
825 EXPECT_EQ(1, stream_->GetReadableRegions(&vec, 1));
826 EXPECT_EQ(body.length(), vec.iov_len);
vasilvvc48c8712019-03-11 13:38:16 -0700827 EXPECT_EQ(body, std::string(static_cast<char*>(vec.iov_base), vec.iov_len));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500828
829 stream_->MarkConsumed(body.length());
renjietang07b2e8d2020-08-10 15:18:24 -0700830 EXPECT_EQ(data.length(), QuicStreamPeer::bytes_consumed(stream_));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500831}
832
833TEST_P(QuicSpdyStreamTest, ProcessHeadersAndConsumeMultipleBody) {
834 Initialize(!kShouldProcessData);
vasilvvc48c8712019-03-11 13:38:16 -0700835 std::string body1 = "this is body 1";
renjietanga29a96a2019-10-10 12:47:50 -0700836 std::string data1 = UsesHttp3() ? DataFrame(body1) : body1;
vasilvvc48c8712019-03-11 13:38:16 -0700837 std::string body2 = "body 2";
renjietanga29a96a2019-10-10 12:47:50 -0700838 std::string data2 = UsesHttp3() ? DataFrame(body2) : body2;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500839
840 ProcessHeaders(false, headers_);
841 QuicStreamFrame frame1(GetNthClientInitiatedBidirectionalId(0), false, 0,
dmcardleba2fb7e2019-12-13 07:44:34 -0800842 quiche::QuicheStringPiece(data1));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500843 QuicStreamFrame frame2(GetNthClientInitiatedBidirectionalId(0), false,
dmcardleba2fb7e2019-12-13 07:44:34 -0800844 data1.length(), quiche::QuicheStringPiece(data2));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500845 stream_->OnStreamFrame(frame1);
846 stream_->OnStreamFrame(frame2);
847 stream_->ConsumeHeaderList();
848
849 stream_->MarkConsumed(body1.length() + body2.length());
850 EXPECT_EQ(data1.length() + data2.length(),
renjietang07b2e8d2020-08-10 15:18:24 -0700851 QuicStreamPeer::bytes_consumed(stream_));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500852}
853
854TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBodyIncrementalReadv) {
855 Initialize(!kShouldProcessData);
856
vasilvvc48c8712019-03-11 13:38:16 -0700857 std::string body = "this is the body";
renjietanga29a96a2019-10-10 12:47:50 -0700858 std::string data = UsesHttp3() ? DataFrame(body) : body;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500859
860 ProcessHeaders(false, headers_);
861 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
dmcardleba2fb7e2019-12-13 07:44:34 -0800862 quiche::QuicheStringPiece(data));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500863 stream_->OnStreamFrame(frame);
864 stream_->ConsumeHeaderList();
865
866 char buffer[1];
867 struct iovec vec;
868 vec.iov_base = buffer;
bnc4e9283d2019-12-17 07:08:57 -0800869 vec.iov_len = QUICHE_ARRAYSIZE(buffer);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500870
871 for (size_t i = 0; i < body.length(); ++i) {
872 size_t bytes_read = stream_->Readv(&vec, 1);
873 ASSERT_EQ(1u, bytes_read);
874 EXPECT_EQ(body.data()[i], buffer[0]);
875 }
876}
877
878TEST_P(QuicSpdyStreamTest, ProcessHeadersUsingReadvWithMultipleIovecs) {
879 Initialize(!kShouldProcessData);
880
vasilvvc48c8712019-03-11 13:38:16 -0700881 std::string body = "this is the body";
renjietanga29a96a2019-10-10 12:47:50 -0700882 std::string data = UsesHttp3() ? DataFrame(body) : body;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500883
884 ProcessHeaders(false, headers_);
885 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
dmcardleba2fb7e2019-12-13 07:44:34 -0800886 quiche::QuicheStringPiece(data));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500887 stream_->OnStreamFrame(frame);
888 stream_->ConsumeHeaderList();
889
890 char buffer1[1];
891 char buffer2[1];
892 struct iovec vec[2];
893 vec[0].iov_base = buffer1;
bnc4e9283d2019-12-17 07:08:57 -0800894 vec[0].iov_len = QUICHE_ARRAYSIZE(buffer1);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500895 vec[1].iov_base = buffer2;
bnc4e9283d2019-12-17 07:08:57 -0800896 vec[1].iov_len = QUICHE_ARRAYSIZE(buffer2);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500897
898 for (size_t i = 0; i < body.length(); i += 2) {
899 size_t bytes_read = stream_->Readv(vec, 2);
900 ASSERT_EQ(2u, bytes_read) << i;
901 ASSERT_EQ(body.data()[i], buffer1[0]) << i;
902 ASSERT_EQ(body.data()[i + 1], buffer2[0]) << i;
903 }
904}
905
bnc677451a2019-06-07 10:13:30 -0700906// Tests that we send a BLOCKED frame to the peer when we attempt to write, but
907// are flow control blocked.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500908TEST_P(QuicSpdyStreamTest, StreamFlowControlBlocked) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500909 Initialize(kShouldProcessData);
fayang8790d292020-03-18 13:17:23 -0700910 testing::InSequence seq;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500911
912 // Set a small flow control limit.
913 const uint64_t kWindow = 36;
renjietang07b2e8d2020-08-10 15:18:24 -0700914 QuicStreamPeer::SetSendWindowOffset(stream_, kWindow);
915 EXPECT_EQ(kWindow, QuicStreamPeer::SendWindowOffset(stream_));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500916
917 // Try to send more data than the flow control limit allows.
918 const uint64_t kOverflow = 15;
vasilvvc48c8712019-03-11 13:38:16 -0700919 std::string body(kWindow + kOverflow, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500920
renjietanga29a96a2019-10-10 12:47:50 -0700921 const uint64_t kHeaderLength = UsesHttp3() ? 2 : 0;
922 if (UsesHttp3()) {
renjietang41a1b412020-02-27 15:05:14 -0800923 EXPECT_CALL(*session_, WritevData(_, kHeaderLength, _, NO_FIN, _, _));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500924 }
renjietang41a1b412020-02-27 15:05:14 -0800925 EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
QUICHE teama6ef0a62019-03-07 20:34:33 -0500926 .WillOnce(Return(QuicConsumedData(kWindow - kHeaderLength, true)));
wub713afae2020-04-27 07:48:31 -0700927 EXPECT_CALL(*session_, SendBlocked(_));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500928 EXPECT_CALL(*connection_, SendControlFrame(_));
929 stream_->WriteOrBufferBody(body, false);
930
931 // Should have sent as much as possible, resulting in no send window left.
renjietang07b2e8d2020-08-10 15:18:24 -0700932 EXPECT_EQ(0u, QuicStreamPeer::SendWindowSize(stream_));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500933
934 // And we should have queued the overflowed data.
bncc7d9e0c2019-04-16 10:22:15 -0700935 EXPECT_EQ(kOverflow + kHeaderLength, stream_->BufferedDataBytes());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500936}
937
bnc677451a2019-06-07 10:13:30 -0700938// The flow control receive window decreases whenever we add new bytes to the
939// sequencer, whether they are consumed immediately or buffered. However we only
940// send WINDOW_UPDATE frames based on increasing number of bytes consumed.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500941TEST_P(QuicSpdyStreamTest, StreamFlowControlNoWindowUpdateIfNotConsumed) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500942 // Don't process data - it will be buffered instead.
943 Initialize(!kShouldProcessData);
944
945 // Expect no WINDOW_UPDATE frames to be sent.
wub713afae2020-04-27 07:48:31 -0700946 EXPECT_CALL(*session_, SendWindowUpdate(_, _)).Times(0);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500947
948 // Set a small flow control receive window.
949 const uint64_t kWindow = 36;
renjietang07b2e8d2020-08-10 15:18:24 -0700950 QuicStreamPeer::SetReceiveWindowOffset(stream_, kWindow);
951 QuicStreamPeer::SetMaxReceiveWindow(stream_, kWindow);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500952
953 // Stream receives enough data to fill a fraction of the receive window.
vasilvvc48c8712019-03-11 13:38:16 -0700954 std::string body(kWindow / 3, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500955 QuicByteCount header_length = 0;
vasilvvc48c8712019-03-11 13:38:16 -0700956 std::string data;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500957
renjietanga29a96a2019-10-10 12:47:50 -0700958 if (UsesHttp3()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500959 std::unique_ptr<char[]> buffer;
bnc46942722019-10-29 11:56:21 -0700960 header_length =
961 HttpEncoder::SerializeDataFrameHeader(body.length(), &buffer);
vasilvvc48c8712019-03-11 13:38:16 -0700962 std::string header = std::string(buffer.get(), header_length);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500963 data = header + body;
964 } else {
965 data = body;
966 }
967
968 ProcessHeaders(false, headers_);
969
970 QuicStreamFrame frame1(GetNthClientInitiatedBidirectionalId(0), false, 0,
dmcardleba2fb7e2019-12-13 07:44:34 -0800971 quiche::QuicheStringPiece(data));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500972 stream_->OnStreamFrame(frame1);
renjietang07b2e8d2020-08-10 15:18:24 -0700973 EXPECT_EQ(kWindow - (kWindow / 3) - header_length,
974 QuicStreamPeer::ReceiveWindowSize(stream_));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500975
976 // Now receive another frame which results in the receive window being over
977 // half full. This should all be buffered, decreasing the receive window but
978 // not sending WINDOW_UPDATE.
979 QuicStreamFrame frame2(GetNthClientInitiatedBidirectionalId(0), false,
dmcardleba2fb7e2019-12-13 07:44:34 -0800980 kWindow / 3 + header_length,
981 quiche::QuicheStringPiece(data));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500982 stream_->OnStreamFrame(frame2);
renjietang07b2e8d2020-08-10 15:18:24 -0700983 EXPECT_EQ(kWindow - (2 * kWindow / 3) - 2 * header_length,
984 QuicStreamPeer::ReceiveWindowSize(stream_));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500985}
986
bnc677451a2019-06-07 10:13:30 -0700987// Tests that on receipt of data, the stream updates its receive window offset
988// appropriately, and sends WINDOW_UPDATE frames when its receive window drops
989// too low.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500990TEST_P(QuicSpdyStreamTest, StreamFlowControlWindowUpdate) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500991 Initialize(kShouldProcessData);
992
993 // Set a small flow control limit.
994 const uint64_t kWindow = 36;
renjietang07b2e8d2020-08-10 15:18:24 -0700995 QuicStreamPeer::SetReceiveWindowOffset(stream_, kWindow);
996 QuicStreamPeer::SetMaxReceiveWindow(stream_, kWindow);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500997
998 // Stream receives enough data to fill a fraction of the receive window.
vasilvvc48c8712019-03-11 13:38:16 -0700999 std::string body(kWindow / 3, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -05001000 QuicByteCount header_length = 0;
vasilvvc48c8712019-03-11 13:38:16 -07001001 std::string data;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001002
renjietanga29a96a2019-10-10 12:47:50 -07001003 if (UsesHttp3()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001004 std::unique_ptr<char[]> buffer;
bnc46942722019-10-29 11:56:21 -07001005 header_length =
1006 HttpEncoder::SerializeDataFrameHeader(body.length(), &buffer);
vasilvvc48c8712019-03-11 13:38:16 -07001007 std::string header = std::string(buffer.get(), header_length);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001008 data = header + body;
1009 } else {
1010 data = body;
1011 }
1012
1013 ProcessHeaders(false, headers_);
1014 stream_->ConsumeHeaderList();
1015
1016 QuicStreamFrame frame1(GetNthClientInitiatedBidirectionalId(0), false, 0,
dmcardleba2fb7e2019-12-13 07:44:34 -08001017 quiche::QuicheStringPiece(data));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001018 stream_->OnStreamFrame(frame1);
renjietang07b2e8d2020-08-10 15:18:24 -07001019 EXPECT_EQ(kWindow - (kWindow / 3) - header_length,
1020 QuicStreamPeer::ReceiveWindowSize(stream_));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001021
1022 // Now receive another frame which results in the receive window being over
1023 // half full. This will trigger the stream to increase its receive window
1024 // offset and send a WINDOW_UPDATE. The result will be again an available
1025 // window of kWindow bytes.
1026 QuicStreamFrame frame2(GetNthClientInitiatedBidirectionalId(0), false,
dmcardleba2fb7e2019-12-13 07:44:34 -08001027 kWindow / 3 + header_length,
1028 quiche::QuicheStringPiece(data));
wub713afae2020-04-27 07:48:31 -07001029 EXPECT_CALL(*session_, SendWindowUpdate(_, _));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001030 EXPECT_CALL(*connection_, SendControlFrame(_));
1031 stream_->OnStreamFrame(frame2);
renjietang07b2e8d2020-08-10 15:18:24 -07001032 EXPECT_EQ(kWindow, QuicStreamPeer::ReceiveWindowSize(stream_));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001033}
1034
bnc677451a2019-06-07 10:13:30 -07001035// Tests that on receipt of data, the connection updates its receive window
1036// offset appropriately, and sends WINDOW_UPDATE frames when its receive window
1037// drops too low.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001038TEST_P(QuicSpdyStreamTest, ConnectionFlowControlWindowUpdate) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001039 Initialize(kShouldProcessData);
1040
1041 // Set a small flow control limit for streams and connection.
1042 const uint64_t kWindow = 36;
renjietang07b2e8d2020-08-10 15:18:24 -07001043 QuicStreamPeer::SetReceiveWindowOffset(stream_, kWindow);
1044 QuicStreamPeer::SetMaxReceiveWindow(stream_, kWindow);
1045 QuicStreamPeer::SetReceiveWindowOffset(stream2_, kWindow);
1046 QuicStreamPeer::SetMaxReceiveWindow(stream2_, kWindow);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001047 QuicFlowControllerPeer::SetReceiveWindowOffset(session_->flow_controller(),
1048 kWindow);
1049 QuicFlowControllerPeer::SetMaxReceiveWindow(session_->flow_controller(),
1050 kWindow);
1051
1052 // Supply headers to both streams so that they are happy to receive data.
1053 auto headers = AsHeaderList(headers_);
1054 stream_->OnStreamHeaderList(false, headers.uncompressed_header_bytes(),
1055 headers);
1056 stream_->ConsumeHeaderList();
1057 stream2_->OnStreamHeaderList(false, headers.uncompressed_header_bytes(),
1058 headers);
1059 stream2_->ConsumeHeaderList();
1060
1061 // Each stream gets a quarter window of data. This should not trigger a
1062 // WINDOW_UPDATE for either stream, nor for the connection.
1063 QuicByteCount header_length = 0;
vasilvvc48c8712019-03-11 13:38:16 -07001064 std::string body;
1065 std::string data;
1066 std::string data2;
1067 std::string body2(1, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -05001068
renjietanga29a96a2019-10-10 12:47:50 -07001069 if (UsesHttp3()) {
vasilvvc48c8712019-03-11 13:38:16 -07001070 body = std::string(kWindow / 4 - 2, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -05001071 std::unique_ptr<char[]> buffer;
bnc46942722019-10-29 11:56:21 -07001072 header_length =
1073 HttpEncoder::SerializeDataFrameHeader(body.length(), &buffer);
vasilvvc48c8712019-03-11 13:38:16 -07001074 std::string header = std::string(buffer.get(), header_length);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001075 data = header + body;
1076 std::unique_ptr<char[]> buffer2;
1077 QuicByteCount header_length2 =
bnc46942722019-10-29 11:56:21 -07001078 HttpEncoder::SerializeDataFrameHeader(body2.length(), &buffer2);
vasilvvc48c8712019-03-11 13:38:16 -07001079 std::string header2 = std::string(buffer2.get(), header_length2);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001080 data2 = header2 + body2;
1081 } else {
vasilvvc48c8712019-03-11 13:38:16 -07001082 body = std::string(kWindow / 4, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -05001083 data = body;
1084 data2 = body2;
1085 }
1086
1087 QuicStreamFrame frame1(GetNthClientInitiatedBidirectionalId(0), false, 0,
dmcardleba2fb7e2019-12-13 07:44:34 -08001088 quiche::QuicheStringPiece(data));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001089 stream_->OnStreamFrame(frame1);
1090 QuicStreamFrame frame2(GetNthClientInitiatedBidirectionalId(1), false, 0,
dmcardleba2fb7e2019-12-13 07:44:34 -08001091 quiche::QuicheStringPiece(data));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001092 stream2_->OnStreamFrame(frame2);
1093
1094 // Now receive a further single byte on one stream - again this does not
1095 // trigger a stream WINDOW_UPDATE, but now the connection flow control window
1096 // is over half full and thus a connection WINDOW_UPDATE is sent.
wub713afae2020-04-27 07:48:31 -07001097 EXPECT_CALL(*session_, SendWindowUpdate(_, _));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001098 EXPECT_CALL(*connection_, SendControlFrame(_));
1099 QuicStreamFrame frame3(GetNthClientInitiatedBidirectionalId(0), false,
dmcardleba2fb7e2019-12-13 07:44:34 -08001100 body.length() + header_length,
1101 quiche::QuicheStringPiece(data2));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001102 stream_->OnStreamFrame(frame3);
1103}
1104
bnc677451a2019-06-07 10:13:30 -07001105// Tests that on if the peer sends too much data (i.e. violates the flow control
1106// protocol), then we terminate the connection.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001107TEST_P(QuicSpdyStreamTest, StreamFlowControlViolation) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001108 // Stream should not process data, so that data gets buffered in the
1109 // sequencer, triggering flow control limits.
1110 Initialize(!kShouldProcessData);
1111
1112 // Set a small flow control limit.
1113 const uint64_t kWindow = 50;
renjietang07b2e8d2020-08-10 15:18:24 -07001114 QuicStreamPeer::SetReceiveWindowOffset(stream_, kWindow);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001115
1116 ProcessHeaders(false, headers_);
1117
1118 // Receive data to overflow the window, violating flow control.
vasilvvc48c8712019-03-11 13:38:16 -07001119 std::string body(kWindow + 1, 'a');
renjietanga29a96a2019-10-10 12:47:50 -07001120 std::string data = UsesHttp3() ? DataFrame(body) : body;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001121 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
dmcardleba2fb7e2019-12-13 07:44:34 -08001122 quiche::QuicheStringPiece(data));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001123 EXPECT_CALL(*connection_,
1124 CloseConnection(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA, _, _));
1125 stream_->OnStreamFrame(frame);
1126}
1127
1128TEST_P(QuicSpdyStreamTest, TestHandlingQuicRstStreamNoError) {
1129 Initialize(kShouldProcessData);
1130 ProcessHeaders(false, headers_);
1131
1132 stream_->OnStreamReset(QuicRstStreamFrame(
1133 kInvalidControlFrameId, stream_->id(), QUIC_STREAM_NO_ERROR, 0));
1134 EXPECT_TRUE(stream_->write_side_closed());
1135 EXPECT_FALSE(stream_->reading_stopped());
1136}
1137
bnc677451a2019-06-07 10:13:30 -07001138// Tests that on if the peer sends too much data (i.e. violates the flow control
1139// protocol), at the connection level (rather than the stream level) then we
1140// terminate the connection.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001141TEST_P(QuicSpdyStreamTest, ConnectionFlowControlViolation) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001142 // Stream should not process data, so that data gets buffered in the
1143 // sequencer, triggering flow control limits.
1144 Initialize(!kShouldProcessData);
1145
1146 // Set a small flow control window on streams, and connection.
1147 const uint64_t kStreamWindow = 50;
1148 const uint64_t kConnectionWindow = 10;
renjietang07b2e8d2020-08-10 15:18:24 -07001149 QuicStreamPeer::SetReceiveWindowOffset(stream_, kStreamWindow);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001150 QuicFlowControllerPeer::SetReceiveWindowOffset(session_->flow_controller(),
1151 kConnectionWindow);
1152
1153 ProcessHeaders(false, headers_);
1154
1155 // Send enough data to overflow the connection level flow control window.
vasilvvc48c8712019-03-11 13:38:16 -07001156 std::string body(kConnectionWindow + 1, 'a');
renjietanga29a96a2019-10-10 12:47:50 -07001157 std::string data = UsesHttp3() ? DataFrame(body) : body;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001158
1159 EXPECT_LT(data.size(), kStreamWindow);
1160 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
dmcardleba2fb7e2019-12-13 07:44:34 -08001161 quiche::QuicheStringPiece(data));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001162
1163 EXPECT_CALL(*connection_,
1164 CloseConnection(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA, _, _));
1165 stream_->OnStreamFrame(frame);
1166}
1167
bnc677451a2019-06-07 10:13:30 -07001168// An attempt to write a FIN with no data should not be flow control blocked,
1169// even if the send window is 0.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001170TEST_P(QuicSpdyStreamTest, StreamFlowControlFinNotBlocked) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001171 Initialize(kShouldProcessData);
1172
1173 // Set a flow control limit of zero.
renjietang07b2e8d2020-08-10 15:18:24 -07001174 QuicStreamPeer::SetReceiveWindowOffset(stream_, 0);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001175
1176 // Send a frame with a FIN but no data. This should not be blocked.
vasilvvc48c8712019-03-11 13:38:16 -07001177 std::string body = "";
QUICHE teama6ef0a62019-03-07 20:34:33 -05001178 bool fin = true;
1179
wub713afae2020-04-27 07:48:31 -07001180 EXPECT_CALL(*session_, SendBlocked(GetNthClientInitiatedBidirectionalId(0)))
QUICHE teama6ef0a62019-03-07 20:34:33 -05001181 .Times(0);
renjietang41a1b412020-02-27 15:05:14 -08001182 EXPECT_CALL(*session_, WritevData(_, 0, _, FIN, _, _));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001183
1184 stream_->WriteOrBufferBody(body, fin);
1185}
1186
bnc677451a2019-06-07 10:13:30 -07001187// Test that receiving trailing headers from the peer via OnStreamHeaderList()
1188// works, and can be read from the stream and consumed.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001189TEST_P(QuicSpdyStreamTest, ReceivingTrailersViaHeaderList) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001190 Initialize(kShouldProcessData);
1191
1192 // Receive initial headers.
1193 size_t total_bytes = 0;
1194 QuicHeaderList headers;
1195 for (const auto& p : headers_) {
1196 headers.OnHeader(p.first, p.second);
1197 total_bytes += p.first.size() + p.second.size();
1198 }
1199
fayang476683a2019-07-25 12:42:16 -07001200 stream_->OnStreamHeadersPriority(
1201 spdy::SpdyStreamPrecedence(kV3HighestPriority));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001202 stream_->OnStreamHeaderList(/*fin=*/false, total_bytes, headers);
1203 stream_->ConsumeHeaderList();
1204
1205 // Receive trailing headers.
1206 SpdyHeaderBlock trailers_block;
1207 trailers_block["key1"] = "value1";
1208 trailers_block["key2"] = "value2";
1209 trailers_block["key3"] = "value3";
1210 SpdyHeaderBlock trailers_block_with_final_offset = trailers_block.Clone();
renjietange47e15f2019-10-29 14:19:30 -07001211 if (!UsesHttp3()) {
renjietang2abedac2019-05-20 14:04:50 -07001212 // :final-offset pseudo-header is only added if trailers are sent
1213 // on the headers stream.
1214 trailers_block_with_final_offset[kFinalOffsetHeaderKey] = "0";
1215 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001216 total_bytes = 0;
1217 QuicHeaderList trailers;
1218 for (const auto& p : trailers_block_with_final_offset) {
1219 trailers.OnHeader(p.first, p.second);
1220 total_bytes += p.first.size() + p.second.size();
1221 }
1222 stream_->OnStreamHeaderList(/*fin=*/true, total_bytes, trailers);
1223
1224 // The trailers should be decompressed, and readable from the stream.
1225 EXPECT_TRUE(stream_->trailers_decompressed());
1226 EXPECT_EQ(trailers_block, stream_->received_trailers());
1227
1228 // IsDoneReading() returns false until trailers marked consumed.
1229 EXPECT_FALSE(stream_->IsDoneReading());
1230 stream_->MarkTrailersConsumed();
1231 EXPECT_TRUE(stream_->IsDoneReading());
1232}
1233
bnc677451a2019-06-07 10:13:30 -07001234// Test that when receiving trailing headers with an offset before response
1235// body, stream is closed at the right offset.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001236TEST_P(QuicSpdyStreamTest, ReceivingTrailersWithOffset) {
renjietang2abedac2019-05-20 14:04:50 -07001237 // kFinalOffsetHeaderKey is not used when HEADERS are sent on the
1238 // request/response stream.
renjietange47e15f2019-10-29 14:19:30 -07001239 if (UsesHttp3()) {
renjietang2abedac2019-05-20 14:04:50 -07001240 return;
1241 }
1242
bnc677451a2019-06-07 10:13:30 -07001243 Initialize(kShouldProcessData);
1244
QUICHE teama6ef0a62019-03-07 20:34:33 -05001245 // Receive initial headers.
1246 QuicHeaderList headers = ProcessHeaders(false, headers_);
1247 stream_->ConsumeHeaderList();
1248
vasilvvc48c8712019-03-11 13:38:16 -07001249 const std::string body = "this is the body";
renjietanga29a96a2019-10-10 12:47:50 -07001250 std::string data = UsesHttp3() ? DataFrame(body) : body;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001251
1252 // Receive trailing headers.
1253 SpdyHeaderBlock trailers_block;
1254 trailers_block["key1"] = "value1";
1255 trailers_block["key2"] = "value2";
1256 trailers_block["key3"] = "value3";
1257 trailers_block[kFinalOffsetHeaderKey] =
dmcardleba2fb7e2019-12-13 07:44:34 -08001258 quiche::QuicheTextUtils::Uint64ToString(data.size());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001259
1260 QuicHeaderList trailers = ProcessHeaders(true, trailers_block);
1261
1262 // The trailers should be decompressed, and readable from the stream.
1263 EXPECT_TRUE(stream_->trailers_decompressed());
1264
1265 // The final offset trailer will be consumed by QUIC.
1266 trailers_block.erase(kFinalOffsetHeaderKey);
1267 EXPECT_EQ(trailers_block, stream_->received_trailers());
1268
1269 // Consuming the trailers erases them from the stream.
1270 stream_->MarkTrailersConsumed();
1271 EXPECT_TRUE(stream_->FinishedReadingTrailers());
1272
1273 EXPECT_FALSE(stream_->IsDoneReading());
1274 // Receive and consume body.
1275 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), /*fin=*/false,
1276 0, data);
1277 stream_->OnStreamFrame(frame);
1278 EXPECT_EQ(body, stream_->data());
1279 EXPECT_TRUE(stream_->IsDoneReading());
1280}
1281
bnc677451a2019-06-07 10:13:30 -07001282// Test that receiving trailers without a final offset field is an error.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001283TEST_P(QuicSpdyStreamTest, ReceivingTrailersWithoutOffset) {
renjietang2abedac2019-05-20 14:04:50 -07001284 // kFinalOffsetHeaderKey is not used when HEADERS are sent on the
1285 // request/response stream.
renjietange47e15f2019-10-29 14:19:30 -07001286 if (UsesHttp3()) {
renjietang2abedac2019-05-20 14:04:50 -07001287 return;
1288 }
1289
bnc677451a2019-06-07 10:13:30 -07001290 Initialize(kShouldProcessData);
1291
QUICHE teama6ef0a62019-03-07 20:34:33 -05001292 // Receive initial headers.
1293 ProcessHeaders(false, headers_);
1294 stream_->ConsumeHeaderList();
1295
1296 // Receive trailing headers, without kFinalOffsetHeaderKey.
1297 SpdyHeaderBlock trailers_block;
1298 trailers_block["key1"] = "value1";
1299 trailers_block["key2"] = "value2";
1300 trailers_block["key3"] = "value3";
1301 auto trailers = AsHeaderList(trailers_block);
1302
1303 // Verify that the trailers block didn't contain a final offset.
1304 EXPECT_EQ("", trailers_block[kFinalOffsetHeaderKey].as_string());
1305
1306 // Receipt of the malformed trailers will close the connection.
1307 EXPECT_CALL(*connection_,
1308 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA, _, _))
1309 .Times(1);
1310 stream_->OnStreamHeaderList(/*fin=*/true,
1311 trailers.uncompressed_header_bytes(), trailers);
1312}
1313
bnc677451a2019-06-07 10:13:30 -07001314// Test that received Trailers must always have the FIN set.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001315TEST_P(QuicSpdyStreamTest, ReceivingTrailersWithoutFin) {
renjietang2abedac2019-05-20 14:04:50 -07001316 // In IETF QUIC, there is no such thing as FIN flag on HTTP/3 frames like the
1317 // HEADERS frame.
renjietange47e15f2019-10-29 14:19:30 -07001318 if (UsesHttp3()) {
renjietang2abedac2019-05-20 14:04:50 -07001319 return;
1320 }
1321
bnc677451a2019-06-07 10:13:30 -07001322 Initialize(kShouldProcessData);
1323
QUICHE teama6ef0a62019-03-07 20:34:33 -05001324 // Receive initial headers.
1325 auto headers = AsHeaderList(headers_);
1326 stream_->OnStreamHeaderList(/*fin=*/false,
1327 headers.uncompressed_header_bytes(), headers);
1328 stream_->ConsumeHeaderList();
1329
1330 // Receive trailing headers with FIN deliberately set to false.
1331 SpdyHeaderBlock trailers_block;
1332 trailers_block["foo"] = "bar";
1333 auto trailers = AsHeaderList(trailers_block);
1334
1335 EXPECT_CALL(*connection_,
1336 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA, _, _))
1337 .Times(1);
1338 stream_->OnStreamHeaderList(/*fin=*/false,
1339 trailers.uncompressed_header_bytes(), trailers);
1340}
1341
1342TEST_P(QuicSpdyStreamTest, ReceivingTrailersAfterHeadersWithFin) {
1343 // If headers are received with a FIN, no trailers should then arrive.
1344 Initialize(kShouldProcessData);
1345
bnc8d041302019-06-10 10:19:04 -07001346 // If HEADERS frames are sent on the request/response stream, then the
1347 // sequencer will signal an error if any stream data arrives after a FIN,
1348 // so QuicSpdyStream does not need to.
renjietange47e15f2019-10-29 14:19:30 -07001349 if (UsesHttp3()) {
bnc8d041302019-06-10 10:19:04 -07001350 return;
1351 }
1352
QUICHE teama6ef0a62019-03-07 20:34:33 -05001353 // Receive initial headers with FIN set.
1354 ProcessHeaders(true, headers_);
1355 stream_->ConsumeHeaderList();
1356
1357 // Receive trailing headers after FIN already received.
1358 SpdyHeaderBlock trailers_block;
1359 trailers_block["foo"] = "bar";
1360 EXPECT_CALL(*connection_,
1361 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA, _, _))
1362 .Times(1);
1363 ProcessHeaders(true, trailers_block);
1364}
1365
bnc677451a2019-06-07 10:13:30 -07001366// If body data are received with a FIN, no trailers should then arrive.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001367TEST_P(QuicSpdyStreamTest, ReceivingTrailersAfterBodyWithFin) {
renjietang2abedac2019-05-20 14:04:50 -07001368 // If HEADERS frames are sent on the request/response stream,
1369 // then the sequencer will block them from reaching QuicSpdyStream
1370 // after the stream is closed.
renjietange47e15f2019-10-29 14:19:30 -07001371 if (UsesHttp3()) {
renjietang2abedac2019-05-20 14:04:50 -07001372 return;
1373 }
1374
bnc677451a2019-06-07 10:13:30 -07001375 Initialize(kShouldProcessData);
1376
QUICHE teama6ef0a62019-03-07 20:34:33 -05001377 // Receive initial headers without FIN set.
1378 ProcessHeaders(false, headers_);
1379 stream_->ConsumeHeaderList();
1380
1381 // Receive body data, with FIN.
1382 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), /*fin=*/true,
1383 0, "body");
1384 stream_->OnStreamFrame(frame);
1385
1386 // Receive trailing headers after FIN already received.
1387 SpdyHeaderBlock trailers_block;
1388 trailers_block["foo"] = "bar";
1389 EXPECT_CALL(*connection_,
1390 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA, _, _))
1391 .Times(1);
1392 ProcessHeaders(true, trailers_block);
1393}
1394
1395TEST_P(QuicSpdyStreamTest, ClosingStreamWithNoTrailers) {
1396 // Verify that a stream receiving headers, body, and no trailers is correctly
1397 // marked as done reading on consumption of headers and body.
1398 Initialize(kShouldProcessData);
1399
1400 // Receive and consume initial headers with FIN not set.
1401 auto h = AsHeaderList(headers_);
1402 stream_->OnStreamHeaderList(/*fin=*/false, h.uncompressed_header_bytes(), h);
1403 stream_->ConsumeHeaderList();
1404
1405 // Receive and consume body with FIN set, and no trailers.
vasilvvc48c8712019-03-11 13:38:16 -07001406 std::string body(1024, 'x');
renjietanga29a96a2019-10-10 12:47:50 -07001407 std::string data = UsesHttp3() ? DataFrame(body) : body;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001408
1409 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), /*fin=*/true,
1410 0, data);
1411 stream_->OnStreamFrame(frame);
1412
1413 EXPECT_TRUE(stream_->IsDoneReading());
1414}
1415
bnc677451a2019-06-07 10:13:30 -07001416// Test that writing trailers will send a FIN, as Trailers are the last thing to
1417// be sent on a stream.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001418TEST_P(QuicSpdyStreamTest, WritingTrailersSendsAFin) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001419 Initialize(kShouldProcessData);
1420
renjietange47e15f2019-10-29 14:19:30 -07001421 if (UsesHttp3()) {
renjietang2abedac2019-05-20 14:04:50 -07001422 // In this case, TestStream::WriteHeadersImpl() does not prevent writes.
bnccd3c4b52020-01-10 11:13:18 -08001423 // Four writes on the request stream: HEADERS frame header and payload both
1424 // for headers and trailers.
renjietang41a1b412020-02-27 15:05:14 -08001425 EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _, _)).Times(4);
renjietang2abedac2019-05-20 14:04:50 -07001426 }
1427
QUICHE teama6ef0a62019-03-07 20:34:33 -05001428 // Write the initial headers, without a FIN.
1429 EXPECT_CALL(*stream_, WriteHeadersMock(false));
1430 stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/false, nullptr);
1431
1432 // Writing trailers implicitly sends a FIN.
1433 SpdyHeaderBlock trailers;
1434 trailers["trailer key"] = "trailer value";
1435 EXPECT_CALL(*stream_, WriteHeadersMock(true));
1436 stream_->WriteTrailers(std::move(trailers), nullptr);
1437 EXPECT_TRUE(stream_->fin_sent());
1438}
1439
bncb8abf382020-01-30 11:26:12 -08001440TEST_P(QuicSpdyStreamTest, DoNotSendPriorityUpdateWithDefaultUrgency) {
1441 if (!UsesHttp3()) {
1442 return;
1443 }
1444
1445 InitializeWithPerspective(kShouldProcessData, Perspective::IS_CLIENT);
bncb9d5e792020-03-20 17:43:41 -07001446 StrictMock<MockHttp3DebugVisitor> debug_visitor;
1447 session_->set_debug_visitor(&debug_visitor);
bncb8abf382020-01-30 11:26:12 -08001448
1449 // Four writes on the request stream: HEADERS frame header and payload both
1450 // for headers and trailers.
renjietang41a1b412020-02-27 15:05:14 -08001451 EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _, _)).Times(4);
bncb8abf382020-01-30 11:26:12 -08001452
bnc5f202512020-02-01 18:43:02 -08001453 // No PRIORITY_UPDATE frames on the control stream,
1454 // because the stream has default priority.
bncb8abf382020-01-30 11:26:12 -08001455 auto send_control_stream =
1456 QuicSpdySessionPeer::GetSendControlStream(session_.get());
renjietang41a1b412020-02-27 15:05:14 -08001457 EXPECT_CALL(*session_, WritevData(send_control_stream->id(), _, _, _, _, _))
bncb8abf382020-01-30 11:26:12 -08001458 .Times(0);
1459
1460 // Write the initial headers, without a FIN.
1461 EXPECT_CALL(*stream_, WriteHeadersMock(false));
bncb9d5e792020-03-20 17:43:41 -07001462 EXPECT_CALL(debug_visitor, OnHeadersFrameSent(stream_->id(), _));
bncb8abf382020-01-30 11:26:12 -08001463 stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/false, nullptr);
1464
1465 // Writing trailers implicitly sends a FIN.
1466 SpdyHeaderBlock trailers;
1467 trailers["trailer key"] = "trailer value";
1468 EXPECT_CALL(*stream_, WriteHeadersMock(true));
bncb9d5e792020-03-20 17:43:41 -07001469 EXPECT_CALL(debug_visitor, OnHeadersFrameSent(stream_->id(), _));
bncb8abf382020-01-30 11:26:12 -08001470 stream_->WriteTrailers(std::move(trailers), nullptr);
1471 EXPECT_TRUE(stream_->fin_sent());
1472}
1473
bnccf09f952020-01-30 17:35:59 -08001474TEST_P(QuicSpdyStreamTest, ChangePriority) {
1475 if (!UsesHttp3()) {
1476 return;
1477 }
1478
1479 InitializeWithPerspective(kShouldProcessData, Perspective::IS_CLIENT);
bncb9d5e792020-03-20 17:43:41 -07001480 StrictMock<MockHttp3DebugVisitor> debug_visitor;
1481 session_->set_debug_visitor(&debug_visitor);
bnccf09f952020-01-30 17:35:59 -08001482
1483 // Two writes on the request stream: HEADERS frame header and payload.
renjietang41a1b412020-02-27 15:05:14 -08001484 EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _, _)).Times(2);
bnccf09f952020-01-30 17:35:59 -08001485 EXPECT_CALL(*stream_, WriteHeadersMock(false));
bncb9d5e792020-03-20 17:43:41 -07001486 EXPECT_CALL(debug_visitor, OnHeadersFrameSent(stream_->id(), _));
bnc5f202512020-02-01 18:43:02 -08001487 stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/false, nullptr);
1488
bnccf09f952020-01-30 17:35:59 -08001489 // PRIORITY_UPDATE frame on the control stream.
1490 auto send_control_stream =
1491 QuicSpdySessionPeer::GetSendControlStream(session_.get());
renjietang41a1b412020-02-27 15:05:14 -08001492 EXPECT_CALL(*session_, WritevData(send_control_stream->id(), _, _, _, _, _));
bncb9d5e792020-03-20 17:43:41 -07001493 PriorityUpdateFrame priority_update;
1494 priority_update.prioritized_element_id = 0;
1495 priority_update.priority_field_value = "u=0";
1496 EXPECT_CALL(debug_visitor, OnPriorityUpdateFrameSent(priority_update));
bnccf09f952020-01-30 17:35:59 -08001497 stream_->SetPriority(spdy::SpdyStreamPrecedence(kV3HighestPriority));
1498}
1499
1500TEST_P(QuicSpdyStreamTest, ChangePriorityBeforeWritingHeaders) {
1501 if (!UsesHttp3()) {
1502 return;
1503 }
1504
1505 InitializeWithPerspective(kShouldProcessData, Perspective::IS_CLIENT);
1506
1507 // PRIORITY_UPDATE frame sent on the control stream as soon as SetPriority()
1508 // is called, before HEADERS frame is sent.
1509 auto send_control_stream =
1510 QuicSpdySessionPeer::GetSendControlStream(session_.get());
renjietang41a1b412020-02-27 15:05:14 -08001511 EXPECT_CALL(*session_, WritevData(send_control_stream->id(), _, _, _, _, _));
bnccf09f952020-01-30 17:35:59 -08001512
1513 stream_->SetPriority(spdy::SpdyStreamPrecedence(kV3HighestPriority));
1514 testing::Mock::VerifyAndClearExpectations(session_.get());
1515
1516 // Two writes on the request stream: HEADERS frame header and payload.
1517 // PRIORITY_UPDATE frame is not sent this time, because one is already sent.
renjietang41a1b412020-02-27 15:05:14 -08001518 EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _, _)).Times(2);
bnccf09f952020-01-30 17:35:59 -08001519 EXPECT_CALL(*stream_, WriteHeadersMock(true));
1520 stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/true, nullptr);
1521}
1522
bnc677451a2019-06-07 10:13:30 -07001523// Test that when writing trailers, the trailers that are actually sent to the
1524// peer contain the final offset field indicating last byte of data.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001525TEST_P(QuicSpdyStreamTest, WritingTrailersFinalOffset) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001526 Initialize(kShouldProcessData);
1527
renjietange47e15f2019-10-29 14:19:30 -07001528 if (UsesHttp3()) {
renjietang2abedac2019-05-20 14:04:50 -07001529 // In this case, TestStream::WriteHeadersImpl() does not prevent writes.
bnccd3c4b52020-01-10 11:13:18 -08001530 // HEADERS frame header and payload on the request stream.
renjietang41a1b412020-02-27 15:05:14 -08001531 EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _, _)).Times(2);
renjietang2abedac2019-05-20 14:04:50 -07001532 }
1533
QUICHE teama6ef0a62019-03-07 20:34:33 -05001534 // Write the initial headers.
1535 EXPECT_CALL(*stream_, WriteHeadersMock(false));
1536 stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/false, nullptr);
1537
1538 // Write non-zero body data to force a non-zero final offset.
renjietang41a1b412020-02-27 15:05:14 -08001539 EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(AtLeast(1));
vasilvvc48c8712019-03-11 13:38:16 -07001540 std::string body(1024, 'x'); // 1 kB
QUICHE teama6ef0a62019-03-07 20:34:33 -05001541 QuicByteCount header_length = 0;
renjietanga29a96a2019-10-10 12:47:50 -07001542 if (UsesHttp3()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001543 std::unique_ptr<char[]> buf;
bnc46942722019-10-29 11:56:21 -07001544 header_length = HttpEncoder::SerializeDataFrameHeader(body.length(), &buf);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001545 }
1546
1547 stream_->WriteOrBufferBody(body, false);
1548
1549 // The final offset field in the trailing headers is populated with the
1550 // number of body bytes written (including queued bytes).
1551 SpdyHeaderBlock trailers;
1552 trailers["trailer key"] = "trailer value";
renjietang2abedac2019-05-20 14:04:50 -07001553
1554 SpdyHeaderBlock expected_trailers(trailers.Clone());
1555 // :final-offset pseudo-header is only added if trailers are sent
1556 // on the headers stream.
renjietange47e15f2019-10-29 14:19:30 -07001557 if (!UsesHttp3()) {
renjietang2abedac2019-05-20 14:04:50 -07001558 expected_trailers[kFinalOffsetHeaderKey] =
dmcardleba2fb7e2019-12-13 07:44:34 -08001559 quiche::QuicheTextUtils::Uint64ToString(body.length() + header_length);
renjietang2abedac2019-05-20 14:04:50 -07001560 }
1561
QUICHE teama6ef0a62019-03-07 20:34:33 -05001562 EXPECT_CALL(*stream_, WriteHeadersMock(true));
1563 stream_->WriteTrailers(std::move(trailers), nullptr);
renjietang2abedac2019-05-20 14:04:50 -07001564 EXPECT_EQ(expected_trailers, stream_->saved_headers());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001565}
1566
bnc677451a2019-06-07 10:13:30 -07001567// Test that if trailers are written after all other data has been written
1568// (headers and body), that this closes the stream for writing.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001569TEST_P(QuicSpdyStreamTest, WritingTrailersClosesWriteSide) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001570 Initialize(kShouldProcessData);
1571
renjietang2abedac2019-05-20 14:04:50 -07001572 // Expect data being written on the stream. In addition to that, headers are
1573 // also written on the stream in case of IETF QUIC.
renjietang41a1b412020-02-27 15:05:14 -08001574 EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _, _))
renjietang2abedac2019-05-20 14:04:50 -07001575 .Times(AtLeast(1));
1576
QUICHE teama6ef0a62019-03-07 20:34:33 -05001577 // Write the initial headers.
1578 EXPECT_CALL(*stream_, WriteHeadersMock(false));
1579 stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/false, nullptr);
1580
1581 // Write non-zero body data.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001582 const int kBodySize = 1 * 1024; // 1 kB
vasilvvc48c8712019-03-11 13:38:16 -07001583 stream_->WriteOrBufferBody(std::string(kBodySize, 'x'), false);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001584 EXPECT_EQ(0u, stream_->BufferedDataBytes());
1585
1586 // Headers and body have been fully written, there is no queued data. Writing
1587 // trailers marks the end of this stream, and thus the write side is closed.
1588 EXPECT_CALL(*stream_, WriteHeadersMock(true));
1589 stream_->WriteTrailers(SpdyHeaderBlock(), nullptr);
1590 EXPECT_TRUE(stream_->write_side_closed());
1591}
1592
bnc677451a2019-06-07 10:13:30 -07001593// Test that the stream is not closed for writing when trailers are sent while
1594// there are still body bytes queued.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001595TEST_P(QuicSpdyStreamTest, WritingTrailersWithQueuedBytes) {
renjietang2abedac2019-05-20 14:04:50 -07001596 // This test exercises sending trailers on the headers stream while data is
1597 // still queued on the response/request stream. In IETF QUIC, data and
1598 // trailers are sent on the same stream, so this test does not apply.
renjietange47e15f2019-10-29 14:19:30 -07001599 if (UsesHttp3()) {
renjietang2abedac2019-05-20 14:04:50 -07001600 return;
1601 }
1602
QUICHE teama6ef0a62019-03-07 20:34:33 -05001603 testing::InSequence seq;
1604 Initialize(kShouldProcessData);
1605
1606 // Write the initial headers.
1607 EXPECT_CALL(*stream_, WriteHeadersMock(false));
1608 stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/false, nullptr);
1609
1610 // Write non-zero body data, but only consume partially, ensuring queueing.
1611 const int kBodySize = 1 * 1024; // 1 kB
renjietanga29a96a2019-10-10 12:47:50 -07001612 if (UsesHttp3()) {
renjietang41a1b412020-02-27 15:05:14 -08001613 EXPECT_CALL(*session_, WritevData(_, 3, _, NO_FIN, _, _));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001614 }
renjietang41a1b412020-02-27 15:05:14 -08001615 EXPECT_CALL(*session_, WritevData(_, kBodySize, _, NO_FIN, _, _))
QUICHE teama6ef0a62019-03-07 20:34:33 -05001616 .WillOnce(Return(QuicConsumedData(kBodySize - 1, false)));
vasilvvc48c8712019-03-11 13:38:16 -07001617 stream_->WriteOrBufferBody(std::string(kBodySize, 'x'), false);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001618 EXPECT_EQ(1u, stream_->BufferedDataBytes());
1619
1620 // Writing trailers will send a FIN, but not close the write side of the
1621 // stream as there are queued bytes.
1622 EXPECT_CALL(*stream_, WriteHeadersMock(true));
1623 stream_->WriteTrailers(SpdyHeaderBlock(), nullptr);
1624 EXPECT_TRUE(stream_->fin_sent());
1625 EXPECT_FALSE(stream_->write_side_closed());
1626
1627 // Writing the queued bytes will close the write side of the stream.
renjietang41a1b412020-02-27 15:05:14 -08001628 EXPECT_CALL(*session_, WritevData(_, 1, _, NO_FIN, _, _));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001629 stream_->OnCanWrite();
1630 EXPECT_TRUE(stream_->write_side_closed());
1631}
1632
bnc677451a2019-06-07 10:13:30 -07001633// Test that it is not possible to write Trailers after a FIN has been sent.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001634TEST_P(QuicSpdyStreamTest, WritingTrailersAfterFIN) {
renjietang2abedac2019-05-20 14:04:50 -07001635 // In IETF QUIC, there is no such thing as FIN flag on HTTP/3 frames like the
bnc01de0b82020-02-25 11:36:51 -08001636 // HEADERS frame.
1637 if (UsesHttp3()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001638 return;
1639 }
1640
QUICHE teama6ef0a62019-03-07 20:34:33 -05001641 Initialize(kShouldProcessData);
1642
1643 // Write the initial headers, with a FIN.
1644 EXPECT_CALL(*stream_, WriteHeadersMock(true));
1645 stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/true, nullptr);
1646 EXPECT_TRUE(stream_->fin_sent());
1647
1648 // Writing Trailers should fail, as the FIN has already been sent.
1649 // populated with the number of body bytes written.
1650 EXPECT_QUIC_BUG(stream_->WriteTrailers(SpdyHeaderBlock(), nullptr),
1651 "Trailers cannot be sent after a FIN");
1652}
1653
1654TEST_P(QuicSpdyStreamTest, HeaderStreamNotiferCorrespondingSpdyStream) {
bnc9f977e42019-06-07 11:36:34 -07001655 // There is no headers stream if QPACK is used.
renjietange47e15f2019-10-29 14:19:30 -07001656 if (UsesHttp3()) {
bnc9f977e42019-06-07 11:36:34 -07001657 return;
1658 }
1659
bnc9f977e42019-06-07 11:36:34 -07001660 const char kHeader1[] = "Header1";
1661 const char kHeader2[] = "Header2";
1662 const char kBody1[] = "Test1";
1663 const char kBody2[] = "Test2";
1664
QUICHE teama6ef0a62019-03-07 20:34:33 -05001665 Initialize(kShouldProcessData);
renjietang41a1b412020-02-27 15:05:14 -08001666 EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(AtLeast(1));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001667 testing::InSequence s;
1668 QuicReferenceCountedPointer<MockAckListener> ack_listener1(
1669 new MockAckListener());
1670 QuicReferenceCountedPointer<MockAckListener> ack_listener2(
1671 new MockAckListener());
1672 stream_->set_ack_listener(ack_listener1);
1673 stream2_->set_ack_listener(ack_listener2);
1674
bnc9f977e42019-06-07 11:36:34 -07001675 session_->headers_stream()->WriteOrBufferData(kHeader1, false, ack_listener1);
1676 stream_->WriteOrBufferBody(kBody1, true);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001677
bnc9f977e42019-06-07 11:36:34 -07001678 session_->headers_stream()->WriteOrBufferData(kHeader2, false, ack_listener2);
1679 stream2_->WriteOrBufferBody(kBody2, false);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001680
1681 QuicStreamFrame frame1(
1682 QuicUtils::GetHeadersStreamId(connection_->transport_version()), false, 0,
bnc9f977e42019-06-07 11:36:34 -07001683 kHeader1);
1684
renjietanga29a96a2019-10-10 12:47:50 -07001685 std::string data1 = UsesHttp3() ? DataFrame(kBody1) : kBody1;
bnc9f977e42019-06-07 11:36:34 -07001686 QuicStreamFrame frame2(stream_->id(), true, 0, data1);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001687 QuicStreamFrame frame3(
1688 QuicUtils::GetHeadersStreamId(connection_->transport_version()), false, 7,
bnc9f977e42019-06-07 11:36:34 -07001689 kHeader2);
renjietanga29a96a2019-10-10 12:47:50 -07001690 std::string data2 = UsesHttp3() ? DataFrame(kBody2) : kBody2;
bnc9f977e42019-06-07 11:36:34 -07001691 QuicStreamFrame frame4(stream2_->id(), false, 0, data2);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001692
1693 EXPECT_CALL(*ack_listener1, OnPacketRetransmitted(7));
1694 session_->OnStreamFrameRetransmitted(frame1);
1695
1696 EXPECT_CALL(*ack_listener1, OnPacketAcked(7, _));
QUICHE team9467db02019-05-30 09:38:45 -07001697 EXPECT_TRUE(session_->OnFrameAcked(QuicFrame(frame1), QuicTime::Delta::Zero(),
1698 QuicTime::Zero()));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001699 EXPECT_CALL(*ack_listener1, OnPacketAcked(5, _));
QUICHE team9467db02019-05-30 09:38:45 -07001700 EXPECT_TRUE(session_->OnFrameAcked(QuicFrame(frame2), QuicTime::Delta::Zero(),
1701 QuicTime::Zero()));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001702 EXPECT_CALL(*ack_listener2, OnPacketAcked(7, _));
QUICHE team9467db02019-05-30 09:38:45 -07001703 EXPECT_TRUE(session_->OnFrameAcked(QuicFrame(frame3), QuicTime::Delta::Zero(),
1704 QuicTime::Zero()));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001705 EXPECT_CALL(*ack_listener2, OnPacketAcked(5, _));
QUICHE team9467db02019-05-30 09:38:45 -07001706 EXPECT_TRUE(session_->OnFrameAcked(QuicFrame(frame4), QuicTime::Delta::Zero(),
1707 QuicTime::Zero()));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001708}
1709
QUICHE teama6ef0a62019-03-07 20:34:33 -05001710TEST_P(QuicSpdyStreamTest, OnPriorityFrame) {
1711 Initialize(kShouldProcessData);
fayang476683a2019-07-25 12:42:16 -07001712 stream_->OnPriorityFrame(spdy::SpdyStreamPrecedence(kV3HighestPriority));
1713 EXPECT_EQ(spdy::SpdyStreamPrecedence(kV3HighestPriority),
1714 stream_->precedence());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001715}
1716
1717TEST_P(QuicSpdyStreamTest, OnPriorityFrameAfterSendingData) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001718 Initialize(kShouldProcessData);
fayang8790d292020-03-18 13:17:23 -07001719 testing::InSequence seq;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001720
renjietanga29a96a2019-10-10 12:47:50 -07001721 if (UsesHttp3()) {
renjietang41a1b412020-02-27 15:05:14 -08001722 EXPECT_CALL(*session_, WritevData(_, 2, _, NO_FIN, _, _));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001723 }
renjietang41a1b412020-02-27 15:05:14 -08001724 EXPECT_CALL(*session_, WritevData(_, 4, _, FIN, _, _));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001725 stream_->WriteOrBufferBody("data", true);
fayang476683a2019-07-25 12:42:16 -07001726 stream_->OnPriorityFrame(spdy::SpdyStreamPrecedence(kV3HighestPriority));
1727 EXPECT_EQ(spdy::SpdyStreamPrecedence(kV3HighestPriority),
1728 stream_->precedence());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001729}
1730
1731TEST_P(QuicSpdyStreamTest, SetPriorityBeforeUpdateStreamPriority) {
1732 MockQuicConnection* connection = new StrictMock<MockQuicConnection>(
1733 &helper_, &alarm_factory_, Perspective::IS_SERVER,
1734 SupportedVersions(GetParam()));
1735 std::unique_ptr<TestMockUpdateStreamSession> session(
1736 new StrictMock<TestMockUpdateStreamSession>(connection));
renjietangd1d00852019-09-06 10:43:12 -07001737 auto stream =
1738 new StrictMock<TestStream>(GetNthClientInitiatedBidirectionalStreamId(
1739 session->transport_version(), 0),
1740 session.get(),
1741 /*should_process_data=*/true);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001742 session->ActivateStream(QuicWrapUnique(stream));
1743
1744 // QuicSpdyStream::SetPriority() should eventually call UpdateStreamPriority()
1745 // on the session. Make sure stream->priority() returns the updated priority
1746 // if called within UpdateStreamPriority(). This expectation is enforced in
1747 // TestMockUpdateStreamSession::UpdateStreamPriority().
1748 session->SetExpectedStream(stream);
fayang476683a2019-07-25 12:42:16 -07001749 session->SetExpectedPriority(spdy::SpdyStreamPrecedence(kV3HighestPriority));
1750 stream->SetPriority(spdy::SpdyStreamPrecedence(kV3HighestPriority));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001751
fayang476683a2019-07-25 12:42:16 -07001752 session->SetExpectedPriority(spdy::SpdyStreamPrecedence(kV3LowestPriority));
1753 stream->SetPriority(spdy::SpdyStreamPrecedence(kV3LowestPriority));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001754}
1755
1756TEST_P(QuicSpdyStreamTest, StreamWaitsForAcks) {
1757 Initialize(kShouldProcessData);
1758 QuicReferenceCountedPointer<MockAckListener> mock_ack_listener(
1759 new StrictMock<MockAckListener>);
1760 stream_->set_ack_listener(mock_ack_listener);
renjietang41a1b412020-02-27 15:05:14 -08001761 EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(AtLeast(1));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001762 // Stream is not waiting for acks initially.
1763 EXPECT_FALSE(stream_->IsWaitingForAcks());
1764 EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
1765
1766 // Send kData1.
1767 stream_->WriteOrBufferData("FooAndBar", false, nullptr);
1768 EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
1769 EXPECT_TRUE(stream_->IsWaitingForAcks());
1770 EXPECT_CALL(*mock_ack_listener, OnPacketAcked(9, _));
1771 QuicByteCount newly_acked_length = 0;
1772 EXPECT_TRUE(stream_->OnStreamFrameAcked(0, 9, false, QuicTime::Delta::Zero(),
QUICHE team2f5f30b2020-02-18 08:52:28 -08001773 QuicTime::Zero(),
QUICHE teama6ef0a62019-03-07 20:34:33 -05001774 &newly_acked_length));
1775 // Stream is not waiting for acks as all sent data is acked.
1776 EXPECT_FALSE(stream_->IsWaitingForAcks());
1777 EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
1778
1779 // Send kData2.
1780 stream_->WriteOrBufferData("FooAndBar", false, nullptr);
1781 EXPECT_TRUE(stream_->IsWaitingForAcks());
1782 EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
1783 // Send FIN.
1784 stream_->WriteOrBufferData("", true, nullptr);
1785 // Fin only frame is not stored in send buffer.
1786 EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
1787
1788 // kData2 is retransmitted.
1789 EXPECT_CALL(*mock_ack_listener, OnPacketRetransmitted(9));
1790 stream_->OnStreamFrameRetransmitted(9, 9, false);
1791
1792 // kData2 is acked.
1793 EXPECT_CALL(*mock_ack_listener, OnPacketAcked(9, _));
1794 EXPECT_TRUE(stream_->OnStreamFrameAcked(9, 9, false, QuicTime::Delta::Zero(),
QUICHE team2f5f30b2020-02-18 08:52:28 -08001795 QuicTime::Zero(),
QUICHE teama6ef0a62019-03-07 20:34:33 -05001796 &newly_acked_length));
1797 // Stream is waiting for acks as FIN is not acked.
1798 EXPECT_TRUE(stream_->IsWaitingForAcks());
1799 EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
1800
1801 // FIN is acked.
1802 EXPECT_CALL(*mock_ack_listener, OnPacketAcked(0, _));
1803 EXPECT_TRUE(stream_->OnStreamFrameAcked(18, 0, true, QuicTime::Delta::Zero(),
QUICHE team2f5f30b2020-02-18 08:52:28 -08001804 QuicTime::Zero(),
QUICHE teama6ef0a62019-03-07 20:34:33 -05001805 &newly_acked_length));
1806 EXPECT_FALSE(stream_->IsWaitingForAcks());
1807 EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
1808}
1809
1810TEST_P(QuicSpdyStreamTest, StreamDataGetAckedMultipleTimes) {
1811 Initialize(kShouldProcessData);
1812 QuicReferenceCountedPointer<MockAckListener> mock_ack_listener(
1813 new StrictMock<MockAckListener>);
1814 stream_->set_ack_listener(mock_ack_listener);
renjietang41a1b412020-02-27 15:05:14 -08001815 EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(AtLeast(1));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001816 // Send [0, 27) and fin.
1817 stream_->WriteOrBufferData("FooAndBar", false, nullptr);
1818 stream_->WriteOrBufferData("FooAndBar", false, nullptr);
1819 stream_->WriteOrBufferData("FooAndBar", true, nullptr);
1820
1821 // Ack [0, 9), [5, 22) and [18, 26)
1822 // Verify [0, 9) 9 bytes are acked.
1823 QuicByteCount newly_acked_length = 0;
1824 EXPECT_CALL(*mock_ack_listener, OnPacketAcked(9, _));
1825 EXPECT_TRUE(stream_->OnStreamFrameAcked(0, 9, false, QuicTime::Delta::Zero(),
QUICHE team2f5f30b2020-02-18 08:52:28 -08001826 QuicTime::Zero(),
QUICHE teama6ef0a62019-03-07 20:34:33 -05001827 &newly_acked_length));
1828 EXPECT_EQ(2u, QuicStreamPeer::SendBuffer(stream_).size());
1829 // Verify [9, 22) 13 bytes are acked.
1830 EXPECT_CALL(*mock_ack_listener, OnPacketAcked(13, _));
1831 EXPECT_TRUE(stream_->OnStreamFrameAcked(5, 17, false, QuicTime::Delta::Zero(),
QUICHE team2f5f30b2020-02-18 08:52:28 -08001832 QuicTime::Zero(),
QUICHE teama6ef0a62019-03-07 20:34:33 -05001833 &newly_acked_length));
1834 EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
1835 // Verify [22, 26) 4 bytes are acked.
1836 EXPECT_CALL(*mock_ack_listener, OnPacketAcked(4, _));
1837 EXPECT_TRUE(stream_->OnStreamFrameAcked(18, 8, false, QuicTime::Delta::Zero(),
QUICHE team2f5f30b2020-02-18 08:52:28 -08001838 QuicTime::Zero(),
QUICHE teama6ef0a62019-03-07 20:34:33 -05001839 &newly_acked_length));
1840 EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
1841 EXPECT_TRUE(stream_->IsWaitingForAcks());
1842
1843 // Ack [0, 27).
1844 // Verify [26, 27) 1 byte is acked.
1845 EXPECT_CALL(*mock_ack_listener, OnPacketAcked(1, _));
1846 EXPECT_TRUE(stream_->OnStreamFrameAcked(26, 1, false, QuicTime::Delta::Zero(),
QUICHE team2f5f30b2020-02-18 08:52:28 -08001847 QuicTime::Zero(),
QUICHE teama6ef0a62019-03-07 20:34:33 -05001848 &newly_acked_length));
1849 EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
1850 EXPECT_TRUE(stream_->IsWaitingForAcks());
1851
1852 // Ack Fin. Verify OnPacketAcked is called.
1853 EXPECT_CALL(*mock_ack_listener, OnPacketAcked(0, _));
1854 EXPECT_TRUE(stream_->OnStreamFrameAcked(27, 0, true, QuicTime::Delta::Zero(),
QUICHE team2f5f30b2020-02-18 08:52:28 -08001855 QuicTime::Zero(),
QUICHE teama6ef0a62019-03-07 20:34:33 -05001856 &newly_acked_length));
1857 EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
1858 EXPECT_FALSE(stream_->IsWaitingForAcks());
1859
1860 // Ack [10, 27) and fin.
1861 // No new data is acked, verify OnPacketAcked is not called.
1862 EXPECT_CALL(*mock_ack_listener, OnPacketAcked(_, _)).Times(0);
QUICHE team2f5f30b2020-02-18 08:52:28 -08001863 EXPECT_FALSE(
1864 stream_->OnStreamFrameAcked(10, 17, true, QuicTime::Delta::Zero(),
1865 QuicTime::Zero(), &newly_acked_length));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001866 EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
1867 EXPECT_FALSE(stream_->IsWaitingForAcks());
1868}
1869
1870// HTTP/3 only.
1871TEST_P(QuicSpdyStreamTest, HeadersAckNotReportedWriteOrBufferBody) {
renjietanga29a96a2019-10-10 12:47:50 -07001872 if (!UsesHttp3()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001873 return;
1874 }
bnc677451a2019-06-07 10:13:30 -07001875
1876 Initialize(kShouldProcessData);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001877 QuicReferenceCountedPointer<MockAckListener> mock_ack_listener(
1878 new StrictMock<MockAckListener>);
1879 stream_->set_ack_listener(mock_ack_listener);
vasilvvc48c8712019-03-11 13:38:16 -07001880 std::string body = "Test1";
1881 std::string body2(100, 'x');
QUICHE teama6ef0a62019-03-07 20:34:33 -05001882
renjietang41a1b412020-02-27 15:05:14 -08001883 EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(AtLeast(1));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001884 stream_->WriteOrBufferBody(body, false);
1885 stream_->WriteOrBufferBody(body2, true);
1886
1887 std::unique_ptr<char[]> buffer;
1888 QuicByteCount header_length =
bnc46942722019-10-29 11:56:21 -07001889 HttpEncoder::SerializeDataFrameHeader(body.length(), &buffer);
vasilvvc48c8712019-03-11 13:38:16 -07001890 std::string header = std::string(buffer.get(), header_length);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001891
bnc46942722019-10-29 11:56:21 -07001892 header_length =
1893 HttpEncoder::SerializeDataFrameHeader(body2.length(), &buffer);
vasilvvc48c8712019-03-11 13:38:16 -07001894 std::string header2 = std::string(buffer.get(), header_length);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001895
1896 EXPECT_CALL(*mock_ack_listener, OnPacketAcked(body.length(), _));
1897 QuicStreamFrame frame(stream_->id(), false, 0, header + body);
QUICHE team9467db02019-05-30 09:38:45 -07001898 EXPECT_TRUE(session_->OnFrameAcked(QuicFrame(frame), QuicTime::Delta::Zero(),
1899 QuicTime::Zero()));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001900
1901 EXPECT_CALL(*mock_ack_listener, OnPacketAcked(0, _));
bnc9f977e42019-06-07 11:36:34 -07001902 QuicStreamFrame frame2(stream_->id(), false, header.length() + body.length(),
QUICHE teama6ef0a62019-03-07 20:34:33 -05001903 header2);
QUICHE team9467db02019-05-30 09:38:45 -07001904 EXPECT_TRUE(session_->OnFrameAcked(QuicFrame(frame2), QuicTime::Delta::Zero(),
1905 QuicTime::Zero()));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001906
1907 EXPECT_CALL(*mock_ack_listener, OnPacketAcked(body2.length(), _));
1908 QuicStreamFrame frame3(stream_->id(), true,
bnc9f977e42019-06-07 11:36:34 -07001909 header.length() + body.length() + header2.length(),
1910 body2);
QUICHE team9467db02019-05-30 09:38:45 -07001911 EXPECT_TRUE(session_->OnFrameAcked(QuicFrame(frame3), QuicTime::Delta::Zero(),
1912 QuicTime::Zero()));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001913
1914 EXPECT_TRUE(
1915 QuicSpdyStreamPeer::unacked_frame_headers_offsets(stream_).Empty());
1916}
1917
1918// HTTP/3 only.
1919TEST_P(QuicSpdyStreamTest, HeadersAckNotReportedWriteBodySlices) {
renjietanga29a96a2019-10-10 12:47:50 -07001920 if (!UsesHttp3()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001921 return;
1922 }
bnc677451a2019-06-07 10:13:30 -07001923
1924 Initialize(kShouldProcessData);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001925 QuicReferenceCountedPointer<MockAckListener> mock_ack_listener(
1926 new StrictMock<MockAckListener>);
1927 stream_->set_ack_listener(mock_ack_listener);
bnc9f977e42019-06-07 11:36:34 -07001928 std::string body1 = "Test1";
vasilvvc48c8712019-03-11 13:38:16 -07001929 std::string body2(100, 'x');
bnc9f977e42019-06-07 11:36:34 -07001930 struct iovec body1_iov = {const_cast<char*>(body1.data()), body1.length()};
QUICHE teama6ef0a62019-03-07 20:34:33 -05001931 struct iovec body2_iov = {const_cast<char*>(body2.data()), body2.length()};
1932 QuicMemSliceStorage storage(&body1_iov, 1,
1933 helper_.GetStreamSendBufferAllocator(), 1024);
1934 QuicMemSliceStorage storage2(&body2_iov, 1,
1935 helper_.GetStreamSendBufferAllocator(), 1024);
renjietang41a1b412020-02-27 15:05:14 -08001936 EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(AtLeast(1));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001937 stream_->WriteBodySlices(storage.ToSpan(), false);
1938 stream_->WriteBodySlices(storage2.ToSpan(), true);
1939
bnc9f977e42019-06-07 11:36:34 -07001940 std::string data1 = DataFrame(body1);
1941 std::string data2 = DataFrame(body2);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001942
1943 EXPECT_CALL(*mock_ack_listener,
bnc9f977e42019-06-07 11:36:34 -07001944 OnPacketAcked(body1.length() + body2.length(), _));
1945 QuicStreamFrame frame(stream_->id(), true, 0, data1 + data2);
QUICHE team9467db02019-05-30 09:38:45 -07001946 EXPECT_TRUE(session_->OnFrameAcked(QuicFrame(frame), QuicTime::Delta::Zero(),
1947 QuicTime::Zero()));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001948
1949 EXPECT_TRUE(
1950 QuicSpdyStreamPeer::unacked_frame_headers_offsets(stream_).Empty());
1951}
1952
1953// HTTP/3 only.
1954TEST_P(QuicSpdyStreamTest, HeaderBytesNotReportedOnRetransmission) {
renjietanga29a96a2019-10-10 12:47:50 -07001955 if (!UsesHttp3()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001956 return;
1957 }
bnc677451a2019-06-07 10:13:30 -07001958
1959 Initialize(kShouldProcessData);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001960 QuicReferenceCountedPointer<MockAckListener> mock_ack_listener(
1961 new StrictMock<MockAckListener>);
1962 stream_->set_ack_listener(mock_ack_listener);
bnc9f977e42019-06-07 11:36:34 -07001963 std::string body1 = "Test1";
vasilvvc48c8712019-03-11 13:38:16 -07001964 std::string body2(100, 'x');
QUICHE teama6ef0a62019-03-07 20:34:33 -05001965
renjietang41a1b412020-02-27 15:05:14 -08001966 EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(AtLeast(1));
bnc9f977e42019-06-07 11:36:34 -07001967 stream_->WriteOrBufferBody(body1, false);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001968 stream_->WriteOrBufferBody(body2, true);
1969
bnc9f977e42019-06-07 11:36:34 -07001970 std::string data1 = DataFrame(body1);
1971 std::string data2 = DataFrame(body2);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001972
bnc9f977e42019-06-07 11:36:34 -07001973 EXPECT_CALL(*mock_ack_listener, OnPacketRetransmitted(body1.length()));
1974 QuicStreamFrame frame(stream_->id(), false, 0, data1);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001975 session_->OnStreamFrameRetransmitted(frame);
1976
1977 EXPECT_CALL(*mock_ack_listener, OnPacketRetransmitted(body2.length()));
bnc9f977e42019-06-07 11:36:34 -07001978 QuicStreamFrame frame2(stream_->id(), true, data1.length(), data2);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001979 session_->OnStreamFrameRetransmitted(frame2);
1980
1981 EXPECT_FALSE(
1982 QuicSpdyStreamPeer::unacked_frame_headers_offsets(stream_).Empty());
1983}
1984
renjietang2abedac2019-05-20 14:04:50 -07001985TEST_P(QuicSpdyStreamTest, HeadersFrameOnRequestStream) {
renjietange47e15f2019-10-29 14:19:30 -07001986 if (!UsesHttp3()) {
renjietang2abedac2019-05-20 14:04:50 -07001987 return;
1988 }
1989
1990 Initialize(kShouldProcessData);
1991
fayang7e3c1a12019-08-02 08:07:13 -07001992 std::string headers = HeadersFrame({std::make_pair("foo", "bar")});
bnc9f977e42019-06-07 11:36:34 -07001993 std::string data = DataFrame(kDataFramePayload);
fayang7e3c1a12019-08-02 08:07:13 -07001994 std::string trailers =
1995 HeadersFrame({std::make_pair("custom-key", "custom-value")});
renjietang2abedac2019-05-20 14:04:50 -07001996
dmcardleba2fb7e2019-12-13 07:44:34 -08001997 std::string stream_frame_payload =
1998 quiche::QuicheStrCat(headers, data, trailers);
renjietang2abedac2019-05-20 14:04:50 -07001999 QuicStreamFrame frame(stream_->id(), false, 0, stream_frame_payload);
2000 stream_->OnStreamFrame(frame);
2001
bnc8d041302019-06-10 10:19:04 -07002002 EXPECT_THAT(stream_->header_list(), ElementsAre(Pair("foo", "bar")));
renjietang2abedac2019-05-20 14:04:50 -07002003
2004 // QuicSpdyStream only calls OnBodyAvailable()
2005 // after the header list has been consumed.
2006 EXPECT_EQ("", stream_->data());
2007 stream_->ConsumeHeaderList();
bnc9f977e42019-06-07 11:36:34 -07002008 EXPECT_EQ(kDataFramePayload, stream_->data());
renjietang2abedac2019-05-20 14:04:50 -07002009
bnc8d041302019-06-10 10:19:04 -07002010 EXPECT_THAT(stream_->received_trailers(),
2011 ElementsAre(Pair("custom-key", "custom-value")));
renjietang2abedac2019-05-20 14:04:50 -07002012}
2013
renjietangbd1a0392019-05-31 11:36:24 -07002014TEST_P(QuicSpdyStreamTest, ProcessBodyAfterTrailers) {
renjietange47e15f2019-10-29 14:19:30 -07002015 if (!UsesHttp3()) {
renjietangbd1a0392019-05-31 11:36:24 -07002016 return;
2017 }
bnc677451a2019-06-07 10:13:30 -07002018
2019 Initialize(!kShouldProcessData);
renjietangbd1a0392019-05-31 11:36:24 -07002020
fayang7e3c1a12019-08-02 08:07:13 -07002021 std::string headers = HeadersFrame({std::make_pair("foo", "bar")});
bnc9f977e42019-06-07 11:36:34 -07002022 std::string data = DataFrame(kDataFramePayload);
renjietangbd1a0392019-05-31 11:36:24 -07002023
2024 // A header block that will take more than one block of sequencer buffer.
2025 // This ensures that when the trailers are consumed, some buffer buckets will
2026 // be freed.
2027 SpdyHeaderBlock trailers_block;
2028 trailers_block["key1"] = std::string(10000, 'x');
bnc2e963aa2019-07-31 18:03:17 -07002029 std::string trailers = HeadersFrame(trailers_block);
renjietangbd1a0392019-05-31 11:36:24 -07002030
bncd48a92e2019-06-18 19:24:58 -07002031 // Feed all three HTTP/3 frames in a single stream frame.
dmcardleba2fb7e2019-12-13 07:44:34 -08002032 std::string stream_frame_payload =
2033 quiche::QuicheStrCat(headers, data, trailers);
renjietangbd1a0392019-05-31 11:36:24 -07002034 QuicStreamFrame frame(stream_->id(), false, 0, stream_frame_payload);
2035 stream_->OnStreamFrame(frame);
2036
2037 stream_->ConsumeHeaderList();
2038 stream_->MarkTrailersConsumed();
bncd48a92e2019-06-18 19:24:58 -07002039
2040 EXPECT_TRUE(stream_->trailers_decompressed());
2041 EXPECT_EQ(trailers_block, stream_->received_trailers());
2042
bncab33c712019-06-28 15:42:15 -07002043 EXPECT_TRUE(stream_->HasBytesToRead());
bncd48a92e2019-06-18 19:24:58 -07002044
2045 // Consume data.
renjietangbd1a0392019-05-31 11:36:24 -07002046 char buffer[2048];
2047 struct iovec vec;
2048 vec.iov_base = buffer;
bnc4e9283d2019-12-17 07:08:57 -08002049 vec.iov_len = QUICHE_ARRAYSIZE(buffer);
renjietangbd1a0392019-05-31 11:36:24 -07002050 size_t bytes_read = stream_->Readv(&vec, 1);
dmcardleba2fb7e2019-12-13 07:44:34 -08002051 EXPECT_EQ(kDataFramePayload, quiche::QuicheStringPiece(buffer, bytes_read));
bncd48a92e2019-06-18 19:24:58 -07002052
bncab33c712019-06-28 15:42:15 -07002053 EXPECT_FALSE(stream_->HasBytesToRead());
renjietangbd1a0392019-05-31 11:36:24 -07002054}
2055
bnc677451a2019-06-07 10:13:30 -07002056// The test stream will receive a stream frame containing malformed headers and
2057// normal body. Make sure the http decoder stops processing body after the
2058// connection shuts down.
renjietang546a6282019-06-03 10:21:21 -07002059TEST_P(QuicSpdyStreamTest, MalformedHeadersStopHttpDecoder) {
renjietange47e15f2019-10-29 14:19:30 -07002060 if (!UsesHttp3()) {
renjietang546a6282019-06-03 10:21:21 -07002061 return;
2062 }
2063
2064 Initialize(kShouldProcessData);
fayang8790d292020-03-18 13:17:23 -07002065 testing::InSequence s;
renjietang546a6282019-06-03 10:21:21 -07002066 connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
2067
2068 // Random bad headers.
bnc9f977e42019-06-07 11:36:34 -07002069 std::string headers =
dmcardleba2fb7e2019-12-13 07:44:34 -08002070 HeadersFrame(quiche::QuicheTextUtils::HexDecode("00002a94e7036261"));
bnc9f977e42019-06-07 11:36:34 -07002071 std::string data = DataFrame(kDataFramePayload);
renjietang546a6282019-06-03 10:21:21 -07002072
dmcardleba2fb7e2019-12-13 07:44:34 -08002073 std::string stream_frame_payload = quiche::QuicheStrCat(headers, data);
renjietang546a6282019-06-03 10:21:21 -07002074 QuicStreamFrame frame(stream_->id(), false, 0, stream_frame_payload);
2075
dschinazi552accc2019-06-17 17:07:34 -07002076 EXPECT_CALL(
2077 *connection_,
bnc232ff9b2019-11-13 18:38:22 -08002078 CloseConnection(QUIC_QPACK_DECOMPRESSION_FAILED,
2079 MatchesRegex("Error decoding headers on stream \\d+: "
2080 "Incomplete header block."),
2081 _))
renjietang546a6282019-06-03 10:21:21 -07002082 .WillOnce(
2083 (Invoke([this](QuicErrorCode error, const std::string& error_details,
2084 ConnectionCloseBehavior connection_close_behavior) {
2085 connection_->ReallyCloseConnection(error, error_details,
2086 connection_close_behavior);
2087 })));
2088 EXPECT_CALL(*connection_, SendConnectionClosePacket(_, _));
fkastenholz5d880a92019-06-21 09:01:56 -07002089 EXPECT_CALL(*session_, OnConnectionClosed(_, _))
2090 .WillOnce(Invoke([this](const QuicConnectionCloseFrame& frame,
2091 ConnectionCloseSource source) {
2092 session_->ReallyOnConnectionClosed(frame, source);
2093 }));
renjietang9946bc02020-07-16 15:14:27 -07002094 EXPECT_CALL(*session_, SendRstStream(_, _, _, _));
2095 EXPECT_CALL(*session_, SendRstStream(_, _, _, _));
renjietang546a6282019-06-03 10:21:21 -07002096 stream_->OnStreamFrame(frame);
2097}
2098
bncf9ff46b2019-11-26 10:32:09 -08002099// Regression test for https://crbug.com/1027895: a HEADERS frame triggers an
2100// error in QuicSpdyStream::OnHeadersFramePayload(). This closes the
2101// connection, freeing the buffer of QuicStreamSequencer. Therefore
2102// QuicStreamSequencer::MarkConsumed() must not be called from
2103// QuicSpdyStream::OnHeadersFramePayload().
2104TEST_P(QuicSpdyStreamTest, DoNotMarkConsumedAfterQpackDecodingError) {
2105 if (!UsesHttp3()) {
2106 return;
2107 }
2108
2109 Initialize(kShouldProcessData);
2110 connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
2111
QUICHE team9eed6702020-07-13 11:35:45 -07002112 {
2113 testing::InSequence s;
2114 EXPECT_CALL(
2115 *connection_,
2116 CloseConnection(QUIC_QPACK_DECOMPRESSION_FAILED,
2117 MatchesRegex("Error decoding headers on stream \\d+: "
2118 "Invalid relative index."),
2119 _))
2120 .WillOnce((
2121 Invoke([this](QuicErrorCode error, const std::string& error_details,
2122 ConnectionCloseBehavior connection_close_behavior) {
2123 connection_->ReallyCloseConnection(error, error_details,
2124 connection_close_behavior);
2125 })));
2126 EXPECT_CALL(*connection_, SendConnectionClosePacket(_, _));
2127 EXPECT_CALL(*session_, OnConnectionClosed(_, _))
2128 .WillOnce(Invoke([this](const QuicConnectionCloseFrame& frame,
2129 ConnectionCloseSource source) {
2130 session_->ReallyOnConnectionClosed(frame, source);
2131 }));
2132 }
renjietang9946bc02020-07-16 15:14:27 -07002133 EXPECT_CALL(*session_, SendRstStream(stream_->id(), _, _, _));
2134 EXPECT_CALL(*session_, SendRstStream(stream2_->id(), _, _, _));
bncf9ff46b2019-11-26 10:32:09 -08002135
2136 // Invalid headers: Required Insert Count is zero, but the header block
2137 // contains a dynamic table reference.
dmcardleba2fb7e2019-12-13 07:44:34 -08002138 std::string headers =
2139 HeadersFrame(quiche::QuicheTextUtils::HexDecode("000080"));
bncf9ff46b2019-11-26 10:32:09 -08002140 QuicStreamFrame frame(stream_->id(), false, 0, headers);
2141 stream_->OnStreamFrame(frame);
2142}
2143
bncbdd303e2019-07-09 05:33:17 -07002144TEST_P(QuicSpdyStreamTest, ImmediateHeaderDecodingWithDynamicTableEntries) {
renjietange47e15f2019-10-29 14:19:30 -07002145 if (!UsesHttp3()) {
bncbdd303e2019-07-09 05:33:17 -07002146 return;
2147 }
2148
2149 Initialize(kShouldProcessData);
fayang8790d292020-03-18 13:17:23 -07002150 testing::InSequence s;
bnc40e9a7b2019-08-30 05:27:08 -07002151 session_->qpack_decoder()->OnSetDynamicTableCapacity(1024);
bncb9d5e792020-03-20 17:43:41 -07002152 StrictMock<MockHttp3DebugVisitor> debug_visitor;
2153 session_->set_debug_visitor(&debug_visitor);
bncbdd303e2019-07-09 05:33:17 -07002154
renjietang87cd7de2019-08-16 08:35:10 -07002155 auto decoder_send_stream =
2156 QuicSpdySessionPeer::GetQpackDecoderSendStream(session_.get());
2157
bncbdd303e2019-07-09 05:33:17 -07002158 // Deliver dynamic table entry to decoder.
2159 session_->qpack_decoder()->OnInsertWithoutNameReference("foo", "bar");
2160
2161 // HEADERS frame referencing first dynamic table entry.
bnc6ab8c792020-03-27 16:15:03 -07002162 std::string encoded_headers = quiche::QuicheTextUtils::HexDecode("020080");
2163 std::string headers = HeadersFrame(encoded_headers);
2164 EXPECT_CALL(debug_visitor,
2165 OnHeadersFrameReceived(stream_->id(), encoded_headers.length()));
bnccbd4ea32020-04-04 16:34:42 -07002166 // Decoder stream type.
2167 EXPECT_CALL(*session_,
2168 WritevData(decoder_send_stream->id(), /* write_length = */ 1,
2169 /* offset = */ 0, _, _, _));
2170 // Header acknowledgement.
2171 EXPECT_CALL(*session_,
2172 WritevData(decoder_send_stream->id(), /* write_length = */ 1,
2173 /* offset = */ 1, _, _, _));
bncb9d5e792020-03-20 17:43:41 -07002174 EXPECT_CALL(debug_visitor, OnHeadersDecoded(stream_->id(), _));
bncbdd303e2019-07-09 05:33:17 -07002175 stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), false, 0, headers));
2176
2177 // Headers can be decoded immediately.
2178 EXPECT_TRUE(stream_->headers_decompressed());
2179
2180 // Verify headers.
2181 EXPECT_THAT(stream_->header_list(), ElementsAre(Pair("foo", "bar")));
2182 stream_->ConsumeHeaderList();
2183
2184 // DATA frame.
2185 std::string data = DataFrame(kDataFramePayload);
bncb9d5e792020-03-20 17:43:41 -07002186 EXPECT_CALL(debug_visitor,
bnc6ab8c792020-03-27 16:15:03 -07002187 OnDataFrameReceived(stream_->id(), strlen(kDataFramePayload)));
bncbdd303e2019-07-09 05:33:17 -07002188 stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), false, /* offset = */
2189 headers.length(), data));
2190 EXPECT_EQ(kDataFramePayload, stream_->data());
2191
2192 // Deliver second dynamic table entry to decoder.
2193 session_->qpack_decoder()->OnInsertWithoutNameReference("trailing", "foobar");
2194
2195 // Trailing HEADERS frame referencing second dynamic table entry.
bnc6ab8c792020-03-27 16:15:03 -07002196 std::string encoded_trailers = quiche::QuicheTextUtils::HexDecode("030080");
2197 std::string trailers = HeadersFrame(encoded_trailers);
2198 EXPECT_CALL(debug_visitor,
2199 OnHeadersFrameReceived(stream_->id(), encoded_trailers.length()));
bncb9d5e792020-03-20 17:43:41 -07002200 // Header acknowledgement.
2201 EXPECT_CALL(*session_, WritevData(decoder_send_stream->id(), _, _, _, _, _));
2202 EXPECT_CALL(debug_visitor, OnHeadersDecoded(stream_->id(), _));
bncbdd303e2019-07-09 05:33:17 -07002203 stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), true, /* offset = */
2204 headers.length() + data.length(),
2205 trailers));
2206
2207 // Trailers can be decoded immediately.
2208 EXPECT_TRUE(stream_->trailers_decompressed());
2209
2210 // Verify trailers.
2211 EXPECT_THAT(stream_->received_trailers(),
2212 ElementsAre(Pair("trailing", "foobar")));
2213 stream_->MarkTrailersConsumed();
2214}
2215
bncc057c012019-07-02 11:13:22 -07002216TEST_P(QuicSpdyStreamTest, BlockedHeaderDecoding) {
renjietange47e15f2019-10-29 14:19:30 -07002217 if (!UsesHttp3()) {
bncc057c012019-07-02 11:13:22 -07002218 return;
2219 }
2220
2221 Initialize(kShouldProcessData);
fayang8790d292020-03-18 13:17:23 -07002222 testing::InSequence s;
bnc40e9a7b2019-08-30 05:27:08 -07002223 session_->qpack_decoder()->OnSetDynamicTableCapacity(1024);
bncb9d5e792020-03-20 17:43:41 -07002224 StrictMock<MockHttp3DebugVisitor> debug_visitor;
2225 session_->set_debug_visitor(&debug_visitor);
bncc057c012019-07-02 11:13:22 -07002226
bncbdd303e2019-07-09 05:33:17 -07002227 // HEADERS frame referencing first dynamic table entry.
bnc6ab8c792020-03-27 16:15:03 -07002228 std::string encoded_headers = quiche::QuicheTextUtils::HexDecode("020080");
2229 std::string headers = HeadersFrame(encoded_headers);
2230 EXPECT_CALL(debug_visitor,
2231 OnHeadersFrameReceived(stream_->id(), encoded_headers.length()));
bncc057c012019-07-02 11:13:22 -07002232 stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), false, 0, headers));
2233
bncbdd303e2019-07-09 05:33:17 -07002234 // Decoding is blocked because dynamic table entry has not been received yet.
bncc057c012019-07-02 11:13:22 -07002235 EXPECT_FALSE(stream_->headers_decompressed());
2236
renjietang87cd7de2019-08-16 08:35:10 -07002237 auto decoder_send_stream =
2238 QuicSpdySessionPeer::GetQpackDecoderSendStream(session_.get());
2239
bnccbd4ea32020-04-04 16:34:42 -07002240 // Decoder stream type.
2241 EXPECT_CALL(*session_,
2242 WritevData(decoder_send_stream->id(), /* write_length = */ 1,
2243 /* offset = */ 0, _, _, _));
2244 // Header acknowledgement.
2245 EXPECT_CALL(*session_,
2246 WritevData(decoder_send_stream->id(), /* write_length = */ 1,
2247 /* offset = */ 1, _, _, _));
bncb9d5e792020-03-20 17:43:41 -07002248 EXPECT_CALL(debug_visitor, OnHeadersDecoded(stream_->id(), _));
bncbdd303e2019-07-09 05:33:17 -07002249 // Deliver dynamic table entry to decoder.
2250 session_->qpack_decoder()->OnInsertWithoutNameReference("foo", "bar");
bncc057c012019-07-02 11:13:22 -07002251 EXPECT_TRUE(stream_->headers_decompressed());
2252
bncbdd303e2019-07-09 05:33:17 -07002253 // Verify headers.
bncc057c012019-07-02 11:13:22 -07002254 EXPECT_THAT(stream_->header_list(), ElementsAre(Pair("foo", "bar")));
2255 stream_->ConsumeHeaderList();
2256
bncbdd303e2019-07-09 05:33:17 -07002257 // DATA frame.
bncc057c012019-07-02 11:13:22 -07002258 std::string data = DataFrame(kDataFramePayload);
bncb9d5e792020-03-20 17:43:41 -07002259 EXPECT_CALL(debug_visitor,
bnc6ab8c792020-03-27 16:15:03 -07002260 OnDataFrameReceived(stream_->id(), strlen(kDataFramePayload)));
bncc057c012019-07-02 11:13:22 -07002261 stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), false, /* offset = */
2262 headers.length(), data));
2263 EXPECT_EQ(kDataFramePayload, stream_->data());
2264
bncbdd303e2019-07-09 05:33:17 -07002265 // Trailing HEADERS frame referencing second dynamic table entry.
bnc6ab8c792020-03-27 16:15:03 -07002266 std::string encoded_trailers = quiche::QuicheTextUtils::HexDecode("030080");
2267 std::string trailers = HeadersFrame(encoded_trailers);
2268 EXPECT_CALL(debug_visitor,
2269 OnHeadersFrameReceived(stream_->id(), encoded_trailers.length()));
bncc057c012019-07-02 11:13:22 -07002270 stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), true, /* offset = */
2271 headers.length() + data.length(),
2272 trailers));
2273
bncbdd303e2019-07-09 05:33:17 -07002274 // Decoding is blocked because dynamic table entry has not been received yet.
bncc057c012019-07-02 11:13:22 -07002275 EXPECT_FALSE(stream_->trailers_decompressed());
2276
bnccbd4ea32020-04-04 16:34:42 -07002277 // Header acknowledgement.
renjietang41a1b412020-02-27 15:05:14 -08002278 EXPECT_CALL(*session_, WritevData(decoder_send_stream->id(), _, _, _, _, _));
bncb9d5e792020-03-20 17:43:41 -07002279 EXPECT_CALL(debug_visitor, OnHeadersDecoded(stream_->id(), _));
bncbdd303e2019-07-09 05:33:17 -07002280 // Deliver second dynamic table entry to decoder.
2281 session_->qpack_decoder()->OnInsertWithoutNameReference("trailing", "foobar");
bncc057c012019-07-02 11:13:22 -07002282 EXPECT_TRUE(stream_->trailers_decompressed());
2283
2284 // Verify trailers.
2285 EXPECT_THAT(stream_->received_trailers(),
bncbdd303e2019-07-09 05:33:17 -07002286 ElementsAre(Pair("trailing", "foobar")));
bncc057c012019-07-02 11:13:22 -07002287 stream_->MarkTrailersConsumed();
2288}
2289
2290TEST_P(QuicSpdyStreamTest, AsyncErrorDecodingHeaders) {
renjietange47e15f2019-10-29 14:19:30 -07002291 if (!UsesHttp3()) {
bncc057c012019-07-02 11:13:22 -07002292 return;
2293 }
2294
2295 Initialize(kShouldProcessData);
bnc40e9a7b2019-08-30 05:27:08 -07002296 session_->qpack_decoder()->OnSetDynamicTableCapacity(1024);
bncc057c012019-07-02 11:13:22 -07002297
bncbdd303e2019-07-09 05:33:17 -07002298 // HEADERS frame only referencing entry with absolute index 0 but with
2299 // Required Insert Count = 2, which is incorrect.
dmcardleba2fb7e2019-12-13 07:44:34 -08002300 std::string headers =
2301 HeadersFrame(quiche::QuicheTextUtils::HexDecode("030081"));
bncc057c012019-07-02 11:13:22 -07002302 stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), false, 0, headers));
2303
bncbdd303e2019-07-09 05:33:17 -07002304 // Even though entire header block is received and every referenced entry is
2305 // available, decoding is blocked until insert count reaches the Required
2306 // Insert Count value advertised in the header block prefix.
bncc057c012019-07-02 11:13:22 -07002307 EXPECT_FALSE(stream_->headers_decompressed());
2308
bncc057c012019-07-02 11:13:22 -07002309 EXPECT_CALL(
2310 *connection_,
bnc232ff9b2019-11-13 18:38:22 -08002311 CloseConnection(QUIC_QPACK_DECOMPRESSION_FAILED,
2312 MatchesRegex("Error decoding headers on stream \\d+: "
2313 "Required Insert Count too large."),
2314 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
bncbdd303e2019-07-09 05:33:17 -07002315
2316 // Deliver two dynamic table entries to decoder
2317 // to trigger decoding of header block.
2318 session_->qpack_decoder()->OnInsertWithoutNameReference("foo", "bar");
2319 session_->qpack_decoder()->OnInsertWithoutNameReference("foo", "bar");
bncc057c012019-07-02 11:13:22 -07002320}
2321
bncfb4f4fc2019-11-18 17:14:56 -08002322// Regression test for https://crbug.com/1024263 and for
2323// https://crbug.com/1025209#c11.
2324TEST_P(QuicSpdyStreamTest, BlockedHeaderDecodingUnblockedWithBufferedError) {
2325 if (!UsesHttp3()) {
2326 return;
2327 }
2328
2329 Initialize(kShouldProcessData);
2330 session_->qpack_decoder()->OnSetDynamicTableCapacity(1024);
2331
2332 // Relative index 2 is invalid because it is larger than or equal to the Base.
dmcardleba2fb7e2019-12-13 07:44:34 -08002333 std::string headers =
2334 HeadersFrame(quiche::QuicheTextUtils::HexDecode("020082"));
bncfb4f4fc2019-11-18 17:14:56 -08002335 stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), false, 0, headers));
2336
2337 // Decoding is blocked.
2338 EXPECT_FALSE(stream_->headers_decompressed());
2339
2340 EXPECT_CALL(
2341 *connection_,
2342 CloseConnection(QUIC_QPACK_DECOMPRESSION_FAILED,
2343 MatchesRegex("Error decoding headers on stream \\d+: "
2344 "Invalid relative index."),
2345 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
2346
2347 // Deliver one dynamic table entry to decoder
2348 // to trigger decoding of header block.
2349 session_->qpack_decoder()->OnInsertWithoutNameReference("foo", "bar");
2350}
2351
bncc057c012019-07-02 11:13:22 -07002352TEST_P(QuicSpdyStreamTest, AsyncErrorDecodingTrailers) {
renjietange47e15f2019-10-29 14:19:30 -07002353 if (!UsesHttp3()) {
bncc057c012019-07-02 11:13:22 -07002354 return;
2355 }
2356
2357 Initialize(kShouldProcessData);
fayang8790d292020-03-18 13:17:23 -07002358 testing::InSequence s;
bnc40e9a7b2019-08-30 05:27:08 -07002359 session_->qpack_decoder()->OnSetDynamicTableCapacity(1024);
bncc057c012019-07-02 11:13:22 -07002360
bncbdd303e2019-07-09 05:33:17 -07002361 // HEADERS frame referencing first dynamic table entry.
dmcardleba2fb7e2019-12-13 07:44:34 -08002362 std::string headers =
2363 HeadersFrame(quiche::QuicheTextUtils::HexDecode("020080"));
bncc057c012019-07-02 11:13:22 -07002364 stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), false, 0, headers));
2365
bncbdd303e2019-07-09 05:33:17 -07002366 // Decoding is blocked because dynamic table entry has not been received yet.
bncc057c012019-07-02 11:13:22 -07002367 EXPECT_FALSE(stream_->headers_decompressed());
2368
renjietang87cd7de2019-08-16 08:35:10 -07002369 auto decoder_send_stream =
2370 QuicSpdySessionPeer::GetQpackDecoderSendStream(session_.get());
2371
bnccbd4ea32020-04-04 16:34:42 -07002372 // Decoder stream type.
2373 EXPECT_CALL(*session_,
2374 WritevData(decoder_send_stream->id(), /* write_length = */ 1,
2375 /* offset = */ 0, _, _, _));
2376 // Header acknowledgement.
2377 EXPECT_CALL(*session_,
2378 WritevData(decoder_send_stream->id(), /* write_length = */ 1,
2379 /* offset = */ 1, _, _, _));
bncbdd303e2019-07-09 05:33:17 -07002380 // Deliver dynamic table entry to decoder.
2381 session_->qpack_decoder()->OnInsertWithoutNameReference("foo", "bar");
bncc057c012019-07-02 11:13:22 -07002382 EXPECT_TRUE(stream_->headers_decompressed());
2383
bncbdd303e2019-07-09 05:33:17 -07002384 // Verify headers.
bncc057c012019-07-02 11:13:22 -07002385 EXPECT_THAT(stream_->header_list(), ElementsAre(Pair("foo", "bar")));
2386 stream_->ConsumeHeaderList();
2387
bncbdd303e2019-07-09 05:33:17 -07002388 // DATA frame.
bncc057c012019-07-02 11:13:22 -07002389 std::string data = DataFrame(kDataFramePayload);
2390 stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), false, /* offset = */
2391 headers.length(), data));
2392 EXPECT_EQ(kDataFramePayload, stream_->data());
2393
bncbdd303e2019-07-09 05:33:17 -07002394 // Trailing HEADERS frame only referencing entry with absolute index 0 but
2395 // with Required Insert Count = 2, which is incorrect.
dmcardleba2fb7e2019-12-13 07:44:34 -08002396 std::string trailers =
2397 HeadersFrame(quiche::QuicheTextUtils::HexDecode("030081"));
bncc057c012019-07-02 11:13:22 -07002398 stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), true, /* offset = */
2399 headers.length() + data.length(),
2400 trailers));
2401
bncbdd303e2019-07-09 05:33:17 -07002402 // Even though entire header block is received and every referenced entry is
2403 // available, decoding is blocked until insert count reaches the Required
2404 // Insert Count value advertised in the header block prefix.
bncc057c012019-07-02 11:13:22 -07002405 EXPECT_FALSE(stream_->trailers_decompressed());
2406
bnc232ff9b2019-11-13 18:38:22 -08002407 EXPECT_CALL(
2408 *connection_,
2409 CloseConnection(QUIC_QPACK_DECOMPRESSION_FAILED,
2410 MatchesRegex("Error decoding trailers on stream \\d+: "
2411 "Required Insert Count too large."),
2412 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
bncbdd303e2019-07-09 05:33:17 -07002413
2414 // Deliver second dynamic table entry to decoder
2415 // to trigger decoding of trailing header block.
2416 session_->qpack_decoder()->OnInsertWithoutNameReference("trailing", "foobar");
bncc057c012019-07-02 11:13:22 -07002417}
2418
bnc8d041302019-06-10 10:19:04 -07002419class QuicSpdyStreamIncrementalConsumptionTest : public QuicSpdyStreamTest {
2420 protected:
2421 QuicSpdyStreamIncrementalConsumptionTest() : offset_(0), consumed_bytes_(0) {}
2422 ~QuicSpdyStreamIncrementalConsumptionTest() override = default;
2423
2424 // Create QuicStreamFrame with |payload|
2425 // and pass it to stream_->OnStreamFrame().
dmcardleba2fb7e2019-12-13 07:44:34 -08002426 void OnStreamFrame(quiche::QuicheStringPiece payload) {
bnc8d041302019-06-10 10:19:04 -07002427 QuicStreamFrame frame(stream_->id(), /* fin = */ false, offset_, payload);
2428 stream_->OnStreamFrame(frame);
2429 offset_ += payload.size();
2430 }
2431
2432 // Return number of bytes marked consumed with sequencer
2433 // since last NewlyConsumedBytes() call.
2434 QuicStreamOffset NewlyConsumedBytes() {
2435 QuicStreamOffset previously_consumed_bytes = consumed_bytes_;
2436 consumed_bytes_ = stream_->sequencer()->NumBytesConsumed();
2437 return consumed_bytes_ - previously_consumed_bytes;
2438 }
2439
2440 // Read |size| bytes from the stream.
2441 std::string ReadFromStream(QuicByteCount size) {
2442 std::string buffer;
2443 buffer.resize(size);
2444
2445 struct iovec vec;
2446 vec.iov_base = const_cast<char*>(buffer.data());
2447 vec.iov_len = size;
2448
2449 size_t bytes_read = stream_->Readv(&vec, 1);
2450 EXPECT_EQ(bytes_read, size);
2451
2452 return buffer;
2453 }
2454
2455 private:
2456 QuicStreamOffset offset_;
2457 QuicStreamOffset consumed_bytes_;
2458};
2459
2460INSTANTIATE_TEST_SUITE_P(Tests,
2461 QuicSpdyStreamIncrementalConsumptionTest,
dschinazi38cc1ee2020-02-28 14:33:58 -08002462 ::testing::ValuesIn(AllSupportedVersions()),
dschinazi142051a2019-09-18 18:17:29 -07002463 ::testing::PrintToStringParamName());
bnc8d041302019-06-10 10:19:04 -07002464
2465// Test that stream bytes are consumed (by calling
2466// sequencer()->MarkConsumed()) incrementally, as soon as possible.
bnc25827c42019-07-29 08:57:24 -07002467TEST_P(QuicSpdyStreamIncrementalConsumptionTest, OnlyKnownFrames) {
renjietange47e15f2019-10-29 14:19:30 -07002468 if (!UsesHttp3()) {
bnc8d041302019-06-10 10:19:04 -07002469 return;
2470 }
2471
2472 Initialize(!kShouldProcessData);
2473
fayang7e3c1a12019-08-02 08:07:13 -07002474 std::string headers = HeadersFrame({std::make_pair("foo", "bar")});
bnc8d041302019-06-10 10:19:04 -07002475
2476 // All HEADERS frame bytes are consumed even if the frame is not received
bnc7deaf372019-07-25 18:00:40 -07002477 // completely.
dmcardleba2fb7e2019-12-13 07:44:34 -08002478 OnStreamFrame(
2479 quiche::QuicheStringPiece(headers).substr(0, headers.size() - 1));
bnc8d041302019-06-10 10:19:04 -07002480 EXPECT_EQ(headers.size() - 1, NewlyConsumedBytes());
2481
2482 // The rest of the HEADERS frame is also consumed immediately.
dmcardleba2fb7e2019-12-13 07:44:34 -08002483 OnStreamFrame(quiche::QuicheStringPiece(headers).substr(headers.size() - 1));
bnc8d041302019-06-10 10:19:04 -07002484 EXPECT_EQ(1u, NewlyConsumedBytes());
2485
2486 // Verify headers.
2487 EXPECT_THAT(stream_->header_list(), ElementsAre(Pair("foo", "bar")));
2488 stream_->ConsumeHeaderList();
2489
2490 // DATA frame.
dmcardleba2fb7e2019-12-13 07:44:34 -08002491 quiche::QuicheStringPiece data_payload(kDataFramePayload);
bnc8d041302019-06-10 10:19:04 -07002492 std::string data_frame = DataFrame(data_payload);
bnce5f9c032019-07-25 11:30:40 -07002493 QuicByteCount data_frame_header_length =
2494 data_frame.size() - data_payload.size();
bnc8d041302019-06-10 10:19:04 -07002495
bnce5f9c032019-07-25 11:30:40 -07002496 // DATA frame header is consumed.
2497 // DATA frame payload is not consumed because payload has to be buffered.
bnc8d041302019-06-10 10:19:04 -07002498 OnStreamFrame(data_frame);
bnce5f9c032019-07-25 11:30:40 -07002499 EXPECT_EQ(data_frame_header_length, NewlyConsumedBytes());
bnc8d041302019-06-10 10:19:04 -07002500
2501 // Consume all but last byte of data.
2502 EXPECT_EQ(data_payload.substr(0, data_payload.size() - 1),
2503 ReadFromStream(data_payload.size() - 1));
bnce5f9c032019-07-25 11:30:40 -07002504 EXPECT_EQ(data_payload.size() - 1, NewlyConsumedBytes());
bnc8d041302019-06-10 10:19:04 -07002505
fayang7e3c1a12019-08-02 08:07:13 -07002506 std::string trailers =
2507 HeadersFrame({std::make_pair("custom-key", "custom-value")});
bnc8d041302019-06-10 10:19:04 -07002508
2509 // No bytes are consumed, because last byte of DATA payload is still buffered.
dmcardleba2fb7e2019-12-13 07:44:34 -08002510 OnStreamFrame(
2511 quiche::QuicheStringPiece(trailers).substr(0, trailers.size() - 1));
bnc8d041302019-06-10 10:19:04 -07002512 EXPECT_EQ(0u, NewlyConsumedBytes());
2513
2514 // Reading last byte of DATA payload triggers consumption of all data received
2515 // so far, even though last HEADERS frame has not been received completely.
2516 EXPECT_EQ(data_payload.substr(data_payload.size() - 1), ReadFromStream(1));
2517 EXPECT_EQ(1 + trailers.size() - 1, NewlyConsumedBytes());
2518
2519 // Last byte of trailers is immediately consumed.
dmcardleba2fb7e2019-12-13 07:44:34 -08002520 OnStreamFrame(
2521 quiche::QuicheStringPiece(trailers).substr(trailers.size() - 1));
bnc8d041302019-06-10 10:19:04 -07002522 EXPECT_EQ(1u, NewlyConsumedBytes());
2523
2524 // Verify trailers.
2525 EXPECT_THAT(stream_->received_trailers(),
2526 ElementsAre(Pair("custom-key", "custom-value")));
2527}
2528
bncb9d5e792020-03-20 17:43:41 -07002529TEST_P(QuicSpdyStreamIncrementalConsumptionTest, ReceiveUnknownFrame) {
2530 if (!UsesHttp3()) {
2531 return;
2532 }
2533
2534 Initialize(kShouldProcessData);
2535 StrictMock<MockHttp3DebugVisitor> debug_visitor;
2536 session_->set_debug_visitor(&debug_visitor);
2537
2538 EXPECT_CALL(debug_visitor,
bnc6ab8c792020-03-27 16:15:03 -07002539 OnUnknownFrameReceived(stream_->id(), /* frame_type = */ 0x21,
2540 /* payload_length = */ 3));
bncb9d5e792020-03-20 17:43:41 -07002541 std::string unknown_frame = UnknownFrame(0x21, "foo");
2542 OnStreamFrame(unknown_frame);
2543}
2544
bnc25827c42019-07-29 08:57:24 -07002545TEST_P(QuicSpdyStreamIncrementalConsumptionTest, UnknownFramesInterleaved) {
renjietange47e15f2019-10-29 14:19:30 -07002546 if (!UsesHttp3()) {
bnc25827c42019-07-29 08:57:24 -07002547 return;
2548 }
2549
2550 Initialize(!kShouldProcessData);
2551
2552 // Unknown frame of reserved type before HEADERS is consumed immediately.
2553 std::string unknown_frame1 = UnknownFrame(0x21, "foo");
2554 OnStreamFrame(unknown_frame1);
2555 EXPECT_EQ(unknown_frame1.size(), NewlyConsumedBytes());
2556
fayang7e3c1a12019-08-02 08:07:13 -07002557 std::string headers = HeadersFrame({std::make_pair("foo", "bar")});
bnc25827c42019-07-29 08:57:24 -07002558
2559 // All HEADERS frame bytes are consumed even if the frame is not received
2560 // completely.
dmcardleba2fb7e2019-12-13 07:44:34 -08002561 OnStreamFrame(
2562 quiche::QuicheStringPiece(headers).substr(0, headers.size() - 1));
bnc25827c42019-07-29 08:57:24 -07002563 EXPECT_EQ(headers.size() - 1, NewlyConsumedBytes());
2564
2565 // The rest of the HEADERS frame is also consumed immediately.
dmcardleba2fb7e2019-12-13 07:44:34 -08002566 OnStreamFrame(quiche::QuicheStringPiece(headers).substr(headers.size() - 1));
bnc25827c42019-07-29 08:57:24 -07002567 EXPECT_EQ(1u, NewlyConsumedBytes());
2568
2569 // Verify headers.
2570 EXPECT_THAT(stream_->header_list(), ElementsAre(Pair("foo", "bar")));
2571 stream_->ConsumeHeaderList();
2572
2573 // Frame of unknown, not reserved type between HEADERS and DATA is consumed
2574 // immediately.
2575 std::string unknown_frame2 = UnknownFrame(0x3a, "");
2576 OnStreamFrame(unknown_frame2);
2577 EXPECT_EQ(unknown_frame2.size(), NewlyConsumedBytes());
2578
2579 // DATA frame.
dmcardleba2fb7e2019-12-13 07:44:34 -08002580 quiche::QuicheStringPiece data_payload(kDataFramePayload);
bnc25827c42019-07-29 08:57:24 -07002581 std::string data_frame = DataFrame(data_payload);
2582 QuicByteCount data_frame_header_length =
2583 data_frame.size() - data_payload.size();
2584
2585 // DATA frame header is consumed.
2586 // DATA frame payload is not consumed because payload has to be buffered.
2587 OnStreamFrame(data_frame);
2588 EXPECT_EQ(data_frame_header_length, NewlyConsumedBytes());
2589
2590 // Frame of unknown, not reserved type is not consumed because DATA payload is
2591 // still buffered.
2592 std::string unknown_frame3 = UnknownFrame(0x39, "bar");
2593 OnStreamFrame(unknown_frame3);
2594 EXPECT_EQ(0u, NewlyConsumedBytes());
2595
2596 // Consume all but last byte of data.
2597 EXPECT_EQ(data_payload.substr(0, data_payload.size() - 1),
2598 ReadFromStream(data_payload.size() - 1));
2599 EXPECT_EQ(data_payload.size() - 1, NewlyConsumedBytes());
2600
fayang7e3c1a12019-08-02 08:07:13 -07002601 std::string trailers =
2602 HeadersFrame({std::make_pair("custom-key", "custom-value")});
bnc25827c42019-07-29 08:57:24 -07002603
2604 // No bytes are consumed, because last byte of DATA payload is still buffered.
dmcardleba2fb7e2019-12-13 07:44:34 -08002605 OnStreamFrame(
2606 quiche::QuicheStringPiece(trailers).substr(0, trailers.size() - 1));
bnc25827c42019-07-29 08:57:24 -07002607 EXPECT_EQ(0u, NewlyConsumedBytes());
2608
2609 // Reading last byte of DATA payload triggers consumption of all data received
2610 // so far, even though last HEADERS frame has not been received completely.
2611 EXPECT_EQ(data_payload.substr(data_payload.size() - 1), ReadFromStream(1));
2612 EXPECT_EQ(1 + unknown_frame3.size() + trailers.size() - 1,
2613 NewlyConsumedBytes());
2614
2615 // Last byte of trailers is immediately consumed.
dmcardleba2fb7e2019-12-13 07:44:34 -08002616 OnStreamFrame(
2617 quiche::QuicheStringPiece(trailers).substr(trailers.size() - 1));
bnc25827c42019-07-29 08:57:24 -07002618 EXPECT_EQ(1u, NewlyConsumedBytes());
2619
2620 // Verify trailers.
2621 EXPECT_THAT(stream_->received_trailers(),
2622 ElementsAre(Pair("custom-key", "custom-value")));
2623
2624 // Unknown frame of reserved type after trailers is consumed immediately.
2625 std::string unknown_frame4 = UnknownFrame(0x40, "");
2626 OnStreamFrame(unknown_frame4);
2627 EXPECT_EQ(unknown_frame4.size(), NewlyConsumedBytes());
2628}
2629
renjietang3c3dfb72019-07-26 11:55:52 -07002630TEST_P(QuicSpdyStreamTest, PushPromiseOnDataStream) {
QUICHE team6c579462019-06-21 14:06:09 -07002631 Initialize(kShouldProcessData);
renjietanga29a96a2019-10-10 12:47:50 -07002632 if (!UsesHttp3()) {
QUICHE team6c579462019-06-21 14:06:09 -07002633 return;
2634 }
renjietang3c3dfb72019-07-26 11:55:52 -07002635
bncb9d5e792020-03-20 17:43:41 -07002636 StrictMock<MockHttp3DebugVisitor> debug_visitor;
2637 session_->set_debug_visitor(&debug_visitor);
renjietang3c3dfb72019-07-26 11:55:52 -07002638
bncb9d5e792020-03-20 17:43:41 -07002639 SpdyHeaderBlock pushed_headers;
2640 pushed_headers["foo"] = "bar";
2641 std::string headers = EncodeQpackHeaders(pushed_headers);
2642
2643 const QuicStreamId push_id = 1;
bnc7ffadb82020-04-07 10:01:30 -07002644 std::string data = SerializePushPromiseFrame(push_id, headers);
renjietang3c3dfb72019-07-26 11:55:52 -07002645 QuicStreamFrame frame(stream_->id(), false, 0, data);
2646
bnc6ab8c792020-03-27 16:15:03 -07002647 EXPECT_CALL(debug_visitor, OnPushPromiseFrameReceived(stream_->id(), push_id,
2648 headers.length()));
bncb9d5e792020-03-20 17:43:41 -07002649 EXPECT_CALL(debug_visitor,
2650 OnPushPromiseDecoded(stream_->id(), push_id,
2651 AsHeaderList(pushed_headers)));
renjietang3c3dfb72019-07-26 11:55:52 -07002652 EXPECT_CALL(*session_,
bnc7ffadb82020-04-07 10:01:30 -07002653 OnPromiseHeaderList(stream_->id(), push_id, headers.length(), _));
QUICHE team6c579462019-06-21 14:06:09 -07002654 stream_->OnStreamFrame(frame);
2655}
2656
bnc7ffadb82020-04-07 10:01:30 -07002657// Regression test for b/152518220.
2658TEST_P(QuicSpdyStreamTest,
2659 OnStreamHeaderBlockArgumentDoesNotIncludePushedHeaderBlock) {
2660 Initialize(kShouldProcessData);
2661 if (!UsesHttp3()) {
2662 return;
2663 }
2664
2665 std::string pushed_headers = EncodeQpackHeaders({{"foo", "bar"}});
2666 const QuicStreamId push_id = 1;
2667 std::string push_promise_frame =
2668 SerializePushPromiseFrame(push_id, pushed_headers);
2669 QuicStreamOffset offset = 0;
2670 QuicStreamFrame frame1(stream_->id(), /* fin = */ false, offset,
2671 push_promise_frame);
2672 offset += push_promise_frame.length();
2673
2674 EXPECT_CALL(*session_, OnPromiseHeaderList(stream_->id(), push_id,
2675 pushed_headers.length(), _));
2676 stream_->OnStreamFrame(frame1);
2677
2678 std::string headers =
2679 EncodeQpackHeaders({{":method", "GET"}, {":path", "/"}});
2680 std::string headers_frame = HeadersFrame(headers);
2681 QuicStreamFrame frame2(stream_->id(), /* fin = */ false, offset,
2682 headers_frame);
2683 stream_->OnStreamFrame(frame2);
2684 EXPECT_EQ(headers.length(), stream_->headers_payload_length());
2685}
2686
bnc519216c2019-07-09 05:03:48 -07002687// Close connection if a DATA frame is received before a HEADERS frame.
2688TEST_P(QuicSpdyStreamTest, DataBeforeHeaders) {
renjietange47e15f2019-10-29 14:19:30 -07002689 if (!UsesHttp3()) {
bnc519216c2019-07-09 05:03:48 -07002690 return;
2691 }
2692
2693 Initialize(kShouldProcessData);
2694
2695 // Closing the connection is mocked out in tests. Instead, simply stop
2696 // reading data at the stream level to prevent QuicSpdyStream from blowing up.
bnc519216c2019-07-09 05:03:48 -07002697 EXPECT_CALL(
2698 *connection_,
bnc3e8fe7c2020-03-10 17:44:58 -07002699 CloseConnection(QUIC_HTTP_INVALID_FRAME_SEQUENCE_ON_SPDY_STREAM,
bnc519216c2019-07-09 05:03:48 -07002700 "Unexpected DATA frame received.",
2701 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET))
2702 .WillOnce(InvokeWithoutArgs([this]() { stream_->StopReading(); }));
2703
2704 std::string data = DataFrame(kDataFramePayload);
2705 stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), false, 0, data));
2706}
2707
2708// Close connection if a HEADERS frame is received after the trailing HEADERS.
2709TEST_P(QuicSpdyStreamTest, TrailersAfterTrailers) {
renjietange47e15f2019-10-29 14:19:30 -07002710 if (!UsesHttp3()) {
bnc519216c2019-07-09 05:03:48 -07002711 return;
2712 }
2713
2714 Initialize(kShouldProcessData);
2715
bnc2e963aa2019-07-31 18:03:17 -07002716 // Receive and consume headers.
fayang7e3c1a12019-08-02 08:07:13 -07002717 std::string headers = HeadersFrame({std::make_pair("foo", "bar")});
bnc519216c2019-07-09 05:03:48 -07002718 QuicStreamOffset offset = 0;
2719 stream_->OnStreamFrame(
2720 QuicStreamFrame(stream_->id(), false, offset, headers));
2721 offset += headers.size();
2722
2723 EXPECT_THAT(stream_->header_list(), ElementsAre(Pair("foo", "bar")));
2724 stream_->ConsumeHeaderList();
2725
2726 // Receive data. It is consumed by TestStream.
2727 std::string data = DataFrame(kDataFramePayload);
2728 stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), false, offset, data));
2729 offset += data.size();
2730
2731 EXPECT_EQ(kDataFramePayload, stream_->data());
2732
bnc2e963aa2019-07-31 18:03:17 -07002733 // Receive and consume trailers.
fayang7e3c1a12019-08-02 08:07:13 -07002734 std::string trailers1 =
2735 HeadersFrame({std::make_pair("custom-key", "custom-value")});
bnc519216c2019-07-09 05:03:48 -07002736 stream_->OnStreamFrame(
2737 QuicStreamFrame(stream_->id(), false, offset, trailers1));
2738 offset += trailers1.size();
2739
2740 EXPECT_TRUE(stream_->trailers_decompressed());
2741 EXPECT_THAT(stream_->received_trailers(),
2742 ElementsAre(Pair("custom-key", "custom-value")));
2743
2744 // Closing the connection is mocked out in tests. Instead, simply stop
2745 // reading data at the stream level to prevent QuicSpdyStream from blowing up.
bnc519216c2019-07-09 05:03:48 -07002746 EXPECT_CALL(
2747 *connection_,
bnc3e8fe7c2020-03-10 17:44:58 -07002748 CloseConnection(QUIC_HTTP_INVALID_FRAME_SEQUENCE_ON_SPDY_STREAM,
bnc519216c2019-07-09 05:03:48 -07002749 "HEADERS frame received after trailing HEADERS.",
2750 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET))
2751 .WillOnce(InvokeWithoutArgs([this]() { stream_->StopReading(); }));
2752
2753 // Receive another HEADERS frame, with no header fields.
bnc2e963aa2019-07-31 18:03:17 -07002754 std::string trailers2 = HeadersFrame(SpdyHeaderBlock());
bnc519216c2019-07-09 05:03:48 -07002755 stream_->OnStreamFrame(
2756 QuicStreamFrame(stream_->id(), false, offset, trailers2));
2757}
2758
2759// Regression test for https://crbug.com/978733.
2760// Close connection if a DATA frame is received after the trailing HEADERS.
2761TEST_P(QuicSpdyStreamTest, DataAfterTrailers) {
renjietange47e15f2019-10-29 14:19:30 -07002762 if (!UsesHttp3()) {
bnc519216c2019-07-09 05:03:48 -07002763 return;
2764 }
2765
2766 Initialize(kShouldProcessData);
2767
bnc2e963aa2019-07-31 18:03:17 -07002768 // Receive and consume headers.
fayang7e3c1a12019-08-02 08:07:13 -07002769 std::string headers = HeadersFrame({std::make_pair("foo", "bar")});
bnc519216c2019-07-09 05:03:48 -07002770 QuicStreamOffset offset = 0;
2771 stream_->OnStreamFrame(
2772 QuicStreamFrame(stream_->id(), false, offset, headers));
2773 offset += headers.size();
2774
2775 EXPECT_THAT(stream_->header_list(), ElementsAre(Pair("foo", "bar")));
2776 stream_->ConsumeHeaderList();
2777
2778 // Receive data. It is consumed by TestStream.
2779 std::string data1 = DataFrame(kDataFramePayload);
2780 stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), false, offset, data1));
2781 offset += data1.size();
2782 EXPECT_EQ(kDataFramePayload, stream_->data());
2783
2784 // Receive trailers, with single header field "custom-key: custom-value".
fayang7e3c1a12019-08-02 08:07:13 -07002785 std::string trailers =
2786 HeadersFrame({std::make_pair("custom-key", "custom-value")});
bnc519216c2019-07-09 05:03:48 -07002787 stream_->OnStreamFrame(
2788 QuicStreamFrame(stream_->id(), false, offset, trailers));
2789 offset += trailers.size();
2790
2791 EXPECT_THAT(stream_->received_trailers(),
2792 ElementsAre(Pair("custom-key", "custom-value")));
2793
2794 // Closing the connection is mocked out in tests. Instead, simply stop
2795 // reading data at the stream level to prevent QuicSpdyStream from blowing up.
bnc519216c2019-07-09 05:03:48 -07002796 EXPECT_CALL(
2797 *connection_,
bnc3e8fe7c2020-03-10 17:44:58 -07002798 CloseConnection(QUIC_HTTP_INVALID_FRAME_SEQUENCE_ON_SPDY_STREAM,
bnc519216c2019-07-09 05:03:48 -07002799 "Unexpected DATA frame received.",
2800 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET))
2801 .WillOnce(InvokeWithoutArgs([this]() { stream_->StopReading(); }));
2802
2803 // Receive more data.
2804 std::string data2 = DataFrame("This payload should not be proccessed.");
2805 stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), false, offset, data2));
2806}
2807
bncef518152019-07-18 05:36:44 -07002808// SETTINGS frames are invalid on bidirectional streams. If one is received,
2809// the connection is closed. No more data should be processed.
2810TEST_P(QuicSpdyStreamTest, StopProcessingIfConnectionClosed) {
renjietange47e15f2019-10-29 14:19:30 -07002811 if (!UsesHttp3()) {
bncef518152019-07-18 05:36:44 -07002812 return;
2813 }
2814
2815 Initialize(kShouldProcessData);
2816
2817 // SETTINGS frame with empty payload.
dmcardleba2fb7e2019-12-13 07:44:34 -08002818 std::string settings = quiche::QuicheTextUtils::HexDecode("0400");
bnc2e963aa2019-07-31 18:03:17 -07002819
2820 // HEADERS frame.
bncef518152019-07-18 05:36:44 -07002821 // Since it arrives after a SETTINGS frame, it should never be read.
fayang7e3c1a12019-08-02 08:07:13 -07002822 std::string headers = HeadersFrame({std::make_pair("foo", "bar")});
bncef518152019-07-18 05:36:44 -07002823
2824 // Combine the two frames to make sure they are processed in a single
2825 // QuicSpdyStream::OnDataAvailable() call.
dmcardleba2fb7e2019-12-13 07:44:34 -08002826 std::string frames = quiche::QuicheStrCat(settings, headers);
bncef518152019-07-18 05:36:44 -07002827
2828 EXPECT_EQ(0u, stream_->sequencer()->NumBytesConsumed());
2829
bncdfabdfb2020-01-17 17:46:40 -08002830 EXPECT_CALL(*connection_,
2831 CloseConnection(QUIC_HTTP_FRAME_UNEXPECTED_ON_SPDY_STREAM, _, _))
bncef518152019-07-18 05:36:44 -07002832 .WillOnce(
2833 Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
2834 EXPECT_CALL(*connection_, SendConnectionClosePacket(_, _));
2835 EXPECT_CALL(*session_, OnConnectionClosed(_, _));
2836
2837 stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), /* fin = */ false,
2838 /* offset = */ 0, frames));
2839
2840 EXPECT_EQ(0u, stream_->sequencer()->NumBytesConsumed());
2841}
2842
bnc6f18a822019-11-27 17:50:38 -08002843// Stream Cancellation instruction is sent on QPACK decoder stream
2844// when stream is reset.
bnc84aa7e52019-12-13 05:25:21 -08002845TEST_P(QuicSpdyStreamTest, StreamCancellationWhenStreamReset) {
bnc6f18a822019-11-27 17:50:38 -08002846 if (!UsesHttp3()) {
2847 return;
2848 }
2849
2850 Initialize(kShouldProcessData);
2851
2852 auto qpack_decoder_stream =
2853 QuicSpdySessionPeer::GetQpackDecoderSendStream(session_.get());
bnccbd4ea32020-04-04 16:34:42 -07002854 // Stream type.
2855 EXPECT_CALL(*session_,
2856 WritevData(qpack_decoder_stream->id(), /* write_length = */ 1,
2857 /* offset = */ 0, _, _, _));
2858 // Stream cancellation.
2859 EXPECT_CALL(*session_,
2860 WritevData(qpack_decoder_stream->id(), /* write_length = */ 1,
2861 /* offset = */ 1, _, _, _));
bnc6f18a822019-11-27 17:50:38 -08002862 EXPECT_CALL(*session_,
renjietang9946bc02020-07-16 15:14:27 -07002863 SendRstStream(stream_->id(), QUIC_STREAM_CANCELLED, 0, _));
bnc6f18a822019-11-27 17:50:38 -08002864
2865 stream_->Reset(QUIC_STREAM_CANCELLED);
2866}
2867
2868// Stream Cancellation instruction is sent on QPACK decoder stream
2869// when RESET_STREAM frame is received.
bnc84aa7e52019-12-13 05:25:21 -08002870TEST_P(QuicSpdyStreamTest, StreamCancellationOnResetReceived) {
bnc6f18a822019-11-27 17:50:38 -08002871 if (!UsesHttp3()) {
2872 return;
2873 }
2874
2875 Initialize(kShouldProcessData);
2876
2877 auto qpack_decoder_stream =
2878 QuicSpdySessionPeer::GetQpackDecoderSendStream(session_.get());
bnccbd4ea32020-04-04 16:34:42 -07002879 // Stream type.
2880 EXPECT_CALL(*session_,
2881 WritevData(qpack_decoder_stream->id(), /* write_length = */ 1,
2882 /* offset = */ 0, _, _, _));
2883 // Stream cancellation.
2884 EXPECT_CALL(*session_,
2885 WritevData(qpack_decoder_stream->id(), /* write_length = */ 1,
2886 /* offset = */ 1, _, _, _));
bnc6f18a822019-11-27 17:50:38 -08002887
2888 stream_->OnStreamReset(QuicRstStreamFrame(
2889 kInvalidControlFrameId, stream_->id(), QUIC_STREAM_CANCELLED, 0));
2890}
2891
bncf8623cc2020-04-27 11:06:31 -07002892TEST_P(QuicSpdyStreamTest, WriteHeadersReturnValue) {
2893 if (!UsesHttp3()) {
2894 return;
2895 }
2896
2897 Initialize(kShouldProcessData);
2898 testing::InSequence s;
2899
2900 // Enable QPACK dynamic table.
2901 session_->OnSetting(SETTINGS_QPACK_MAX_TABLE_CAPACITY, 1024);
2902 session_->OnSetting(SETTINGS_QPACK_BLOCKED_STREAMS, 1);
2903
2904 EXPECT_CALL(*stream_, WriteHeadersMock(true));
2905
2906 QpackSendStream* encoder_stream =
2907 QuicSpdySessionPeer::GetQpackEncoderSendStream(session_.get());
2908 EXPECT_CALL(*session_, WritevData(encoder_stream->id(), _, _, _, _, _))
2909 .Times(AnyNumber());
2910
2911 // HEADERS frame header.
2912 EXPECT_CALL(*session_,
2913 WritevData(stream_->id(), _, /* offset = */ 0, _, _, _));
2914 // HEADERS frame payload.
2915 size_t headers_frame_payload_length = 0;
2916 EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _, _))
2917 .WillOnce(
2918 DoAll(SaveArg<1>(&headers_frame_payload_length),
2919 Invoke(session_.get(), &MockQuicSpdySession::ConsumeData)));
2920
2921 SpdyHeaderBlock request_headers;
2922 request_headers["foo"] = "bar";
2923 size_t write_headers_return_value =
2924 stream_->WriteHeaders(std::move(request_headers), /*fin=*/true, nullptr);
2925 EXPECT_TRUE(stream_->fin_sent());
2926
bnc7a6f00f2020-04-27 13:10:18 -07002927 EXPECT_EQ(headers_frame_payload_length, write_headers_return_value);
bncf8623cc2020-04-27 11:06:31 -07002928}
2929
QUICHE teama6ef0a62019-03-07 20:34:33 -05002930} // namespace
2931} // namespace test
2932} // namespace quic