blob: 66100bb4ad90957a8ca114e6eccd55feb2d4fd4f [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
7#include <memory>
vasilvv872e7a32019-03-12 16:42:44 -07008#include <string>
QUICHE teama6ef0a62019-03-07 20:34:33 -05009#include <utility>
10
11#include "net/third_party/quiche/src/quic/core/http/http_encoder.h"
12#include "net/third_party/quiche/src/quic/core/http/spdy_utils.h"
13#include "net/third_party/quiche/src/quic/core/quic_connection.h"
14#include "net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer.h"
15#include "net/third_party/quiche/src/quic/core/quic_utils.h"
16#include "net/third_party/quiche/src/quic/core/quic_versions.h"
17#include "net/third_party/quiche/src/quic/core/quic_write_blocked_list.h"
18#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
19#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
20#include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
21#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050022#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
23#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
24#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
25#include "net/third_party/quiche/src/quic/test_tools/quic_flow_controller_peer.h"
26#include "net/third_party/quiche/src/quic/test_tools/quic_session_peer.h"
27#include "net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h"
28#include "net/third_party/quiche/src/quic/test_tools/quic_spdy_stream_peer.h"
29#include "net/third_party/quiche/src/quic/test_tools/quic_stream_peer.h"
30#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
31
32using spdy::kV3HighestPriority;
33using spdy::kV3LowestPriority;
34using spdy::SpdyHeaderBlock;
35using spdy::SpdyPriority;
36using testing::_;
37using testing::AtLeast;
bnc8d041302019-06-10 10:19:04 -070038using testing::ElementsAre;
QUICHE teama6ef0a62019-03-07 20:34:33 -050039using testing::Invoke;
bnc8d041302019-06-10 10:19:04 -070040using testing::Pair;
QUICHE teama6ef0a62019-03-07 20:34:33 -050041using testing::Return;
42using testing::StrictMock;
43
44namespace quic {
45namespace test {
46namespace {
47
48const bool kShouldProcessData = true;
bnc9f977e42019-06-07 11:36:34 -070049const char kDataFramePayload[] = "some data";
QUICHE teama6ef0a62019-03-07 20:34:33 -050050
51class TestStream : public QuicSpdyStream {
52 public:
53 TestStream(QuicStreamId id,
54 QuicSpdySession* session,
55 bool should_process_data)
56 : QuicSpdyStream(id, session, BIDIRECTIONAL),
57 should_process_data_(should_process_data) {}
58 ~TestStream() override = default;
59
60 using QuicSpdyStream::set_ack_listener;
61 using QuicStream::CloseWriteSide;
62 using QuicStream::WriteOrBufferData;
63
64 void OnBodyAvailable() override {
65 if (!should_process_data_) {
66 return;
67 }
68 char buffer[2048];
69 struct iovec vec;
70 vec.iov_base = buffer;
71 vec.iov_len = QUIC_ARRAYSIZE(buffer);
72 size_t bytes_read = Readv(&vec, 1);
vasilvvc48c8712019-03-11 13:38:16 -070073 data_ += std::string(buffer, bytes_read);
QUICHE teama6ef0a62019-03-07 20:34:33 -050074 }
75
76 MOCK_METHOD1(WriteHeadersMock, void(bool fin));
77
78 size_t WriteHeadersImpl(spdy::SpdyHeaderBlock header_block,
79 bool fin,
80 QuicReferenceCountedPointer<QuicAckListenerInterface>
81 ack_listener) override {
82 saved_headers_ = std::move(header_block);
83 WriteHeadersMock(fin);
renjietang2abedac2019-05-20 14:04:50 -070084 if (VersionUsesQpack(transport_version())) {
85 // In this case, call QuicSpdyStream::WriteHeadersImpl() that does the
86 // actual work of closing the stream.
87 QuicSpdyStream::WriteHeadersImpl(saved_headers_.Clone(), fin, nullptr);
88 }
QUICHE teama6ef0a62019-03-07 20:34:33 -050089 return 0;
90 }
91
vasilvvc48c8712019-03-11 13:38:16 -070092 const std::string& data() const { return data_; }
QUICHE teama6ef0a62019-03-07 20:34:33 -050093 const spdy::SpdyHeaderBlock& saved_headers() const { return saved_headers_; }
94
bnc8d041302019-06-10 10:19:04 -070095 // Expose protected accessor.
96 const QuicStreamSequencer* sequencer() const {
97 return QuicStream::sequencer();
98 }
99
QUICHE teama6ef0a62019-03-07 20:34:33 -0500100 private:
101 bool should_process_data_;
102 spdy::SpdyHeaderBlock saved_headers_;
vasilvvc48c8712019-03-11 13:38:16 -0700103 std::string data_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500104};
105
106class TestMockUpdateStreamSession : public MockQuicSpdySession {
107 public:
108 explicit TestMockUpdateStreamSession(QuicConnection* connection)
109 : MockQuicSpdySession(connection) {}
110
111 void UpdateStreamPriority(QuicStreamId id, SpdyPriority priority) override {
112 EXPECT_EQ(id, expected_stream_->id());
113 EXPECT_EQ(expected_priority_, priority);
114 EXPECT_EQ(expected_priority_, expected_stream_->priority());
115 }
116
117 void SetExpectedStream(QuicSpdyStream* stream) { expected_stream_ = stream; }
118 void SetExpectedPriority(SpdyPriority priority) {
119 expected_priority_ = priority;
120 }
121
122 private:
123 QuicSpdyStream* expected_stream_;
124 SpdyPriority expected_priority_;
125};
126
127class QuicSpdyStreamTest : public QuicTestWithParam<ParsedQuicVersion> {
bnc9f977e42019-06-07 11:36:34 -0700128 protected:
QUICHE teama6ef0a62019-03-07 20:34:33 -0500129 QuicSpdyStreamTest() {
130 headers_[":host"] = "www.google.com";
131 headers_[":path"] = "/index.hml";
132 headers_[":scheme"] = "https";
133 headers_["cookie"] =
134 "__utma=208381060.1228362404.1372200928.1372200928.1372200928.1; "
135 "__utmc=160408618; "
136 "GX=DQAAAOEAAACWJYdewdE9rIrW6qw3PtVi2-d729qaa-74KqOsM1NVQblK4VhX"
137 "hoALMsy6HOdDad2Sz0flUByv7etmo3mLMidGrBoljqO9hSVA40SLqpG_iuKKSHX"
138 "RW3Np4bq0F0SDGDNsW0DSmTS9ufMRrlpARJDS7qAI6M3bghqJp4eABKZiRqebHT"
139 "pMU-RXvTI5D5oCF1vYxYofH_l1Kviuiy3oQ1kS1enqWgbhJ2t61_SNdv-1XJIS0"
140 "O3YeHLmVCs62O6zp89QwakfAWK9d3IDQvVSJzCQsvxvNIvaZFa567MawWlXg0Rh"
141 "1zFMi5vzcns38-8_Sns; "
142 "GA=v*2%2Fmem*57968640*47239936%2Fmem*57968640*47114716%2Fno-nm-"
143 "yj*15%2Fno-cc-yj*5%2Fpc-ch*133685%2Fpc-s-cr*133947%2Fpc-s-t*1339"
144 "47%2Fno-nm-yj*4%2Fno-cc-yj*1%2Fceft-as*1%2Fceft-nqas*0%2Fad-ra-c"
145 "v_p%2Fad-nr-cv_p-f*1%2Fad-v-cv_p*859%2Fad-ns-cv_p-f*1%2Ffn-v-ad%"
146 "2Fpc-t*250%2Fpc-cm*461%2Fpc-s-cr*722%2Fpc-s-t*722%2Fau_p*4"
147 "SICAID=AJKiYcHdKgxum7KMXG0ei2t1-W4OD1uW-ecNsCqC0wDuAXiDGIcT_HA2o1"
148 "3Rs1UKCuBAF9g8rWNOFbxt8PSNSHFuIhOo2t6bJAVpCsMU5Laa6lewuTMYI8MzdQP"
149 "ARHKyW-koxuhMZHUnGBJAM1gJODe0cATO_KGoX4pbbFxxJ5IicRxOrWK_5rU3cdy6"
150 "edlR9FsEdH6iujMcHkbE5l18ehJDwTWmBKBzVD87naobhMMrF6VvnDGxQVGp9Ir_b"
151 "Rgj3RWUoPumQVCxtSOBdX0GlJOEcDTNCzQIm9BSfetog_eP_TfYubKudt5eMsXmN6"
152 "QnyXHeGeK2UINUzJ-D30AFcpqYgH9_1BvYSpi7fc7_ydBU8TaD8ZRxvtnzXqj0RfG"
153 "tuHghmv3aD-uzSYJ75XDdzKdizZ86IG6Fbn1XFhYZM-fbHhm3mVEXnyRW4ZuNOLFk"
154 "Fas6LMcVC6Q8QLlHYbXBpdNFuGbuZGUnav5C-2I_-46lL0NGg3GewxGKGHvHEfoyn"
155 "EFFlEYHsBQ98rXImL8ySDycdLEFvBPdtctPmWCfTxwmoSMLHU2SCVDhbqMWU5b0yr"
156 "JBCScs_ejbKaqBDoB7ZGxTvqlrB__2ZmnHHjCr8RgMRtKNtIeuZAo ";
157 }
158
bnc8d041302019-06-10 10:19:04 -0700159 ~QuicSpdyStreamTest() override = default;
160
renjietangbd1a0392019-05-31 11:36:24 -0700161 std::string EncodeQpackHeaders(QuicStreamId id, SpdyHeaderBlock* header) {
162 auto qpack_encoder =
163 QuicMakeUnique<QpackEncoder>(session_.get(), session_.get());
bnc9f977e42019-06-07 11:36:34 -0700164 auto progressive_encoder = qpack_encoder->EncodeHeaderList(id, header);
renjietangbd1a0392019-05-31 11:36:24 -0700165 std::string encoded_headers;
bnc9f977e42019-06-07 11:36:34 -0700166 while (progressive_encoder->HasNext()) {
167 progressive_encoder->Next(std::numeric_limits<size_t>::max(),
renjietangbd1a0392019-05-31 11:36:24 -0700168 &encoded_headers);
169 }
170 return encoded_headers;
171 }
172
QUICHE teama6ef0a62019-03-07 20:34:33 -0500173 void Initialize(bool stream_should_process_data) {
174 connection_ = new StrictMock<MockQuicConnection>(
175 &helper_, &alarm_factory_, Perspective::IS_SERVER,
176 SupportedVersions(GetParam()));
177 session_ = QuicMakeUnique<StrictMock<MockQuicSpdySession>>(connection_);
178 session_->Initialize();
179 ON_CALL(*session_, WritevData(_, _, _, _, _))
180 .WillByDefault(Invoke(MockQuicSession::ConsumeData));
181
182 stream_ =
183 new StrictMock<TestStream>(GetNthClientInitiatedBidirectionalId(0),
184 session_.get(), stream_should_process_data);
185 session_->ActivateStream(QuicWrapUnique(stream_));
186 stream2_ =
187 new StrictMock<TestStream>(GetNthClientInitiatedBidirectionalId(1),
188 session_.get(), stream_should_process_data);
189 session_->ActivateStream(QuicWrapUnique(stream2_));
190 }
191
192 QuicHeaderList ProcessHeaders(bool fin, const SpdyHeaderBlock& headers) {
193 QuicHeaderList h = AsHeaderList(headers);
194 stream_->OnStreamHeaderList(fin, h.uncompressed_header_bytes(), h);
195 return h;
196 }
197
198 QuicStreamId GetNthClientInitiatedBidirectionalId(int n) {
199 return GetNthClientInitiatedBidirectionalStreamId(
200 connection_->transport_version(), n);
201 }
202
203 bool HasFrameHeader() const {
bnc677451a2019-06-07 10:13:30 -0700204 return VersionHasDataFrameHeader(GetParam().transport_version);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500205 }
206
bnc9f977e42019-06-07 11:36:34 -0700207 std::string HeadersFrame(QuicStringPiece payload) {
208 std::unique_ptr<char[]> headers_buffer;
209 QuicByteCount headers_frame_header_length =
210 encoder_.SerializeHeadersFrameHeader(payload.length(), &headers_buffer);
211 QuicStringPiece headers_frame_header(headers_buffer.get(),
212 headers_frame_header_length);
213 return QuicStrCat(headers_frame_header, payload);
214 }
215
216 std::string DataFrame(QuicStringPiece payload) {
217 std::unique_ptr<char[]> data_buffer;
218 QuicByteCount data_frame_header_length =
219 encoder_.SerializeDataFrameHeader(payload.length(), &data_buffer);
220 QuicStringPiece data_frame_header(data_buffer.get(),
221 data_frame_header_length);
222 return QuicStrCat(data_frame_header, payload);
223 }
224
QUICHE teama6ef0a62019-03-07 20:34:33 -0500225 MockQuicConnectionHelper helper_;
226 MockAlarmFactory alarm_factory_;
227 MockQuicConnection* connection_;
228 std::unique_ptr<MockQuicSpdySession> session_;
229
230 // Owned by the |session_|.
231 TestStream* stream_;
232 TestStream* stream2_;
233
234 SpdyHeaderBlock headers_;
235
236 HttpEncoder encoder_;
237};
238
vasilvvc48c8712019-03-11 13:38:16 -0700239INSTANTIATE_TEST_SUITE_P(Tests,
240 QuicSpdyStreamTest,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500241 ::testing::ValuesIn(AllSupportedVersions()));
242
243TEST_P(QuicSpdyStreamTest, ProcessHeaderList) {
244 Initialize(kShouldProcessData);
245
246 stream_->OnStreamHeadersPriority(kV3HighestPriority);
247 ProcessHeaders(false, headers_);
248 EXPECT_EQ("", stream_->data());
249 EXPECT_FALSE(stream_->header_list().empty());
250 EXPECT_FALSE(stream_->IsDoneReading());
251}
252
253TEST_P(QuicSpdyStreamTest, ProcessTooLargeHeaderList) {
254 Initialize(kShouldProcessData);
255
256 QuicHeaderList headers;
257 stream_->OnStreamHeadersPriority(kV3HighestPriority);
258
renjietang2abedac2019-05-20 14:04:50 -0700259 const bool version_uses_qpack =
bnc677451a2019-06-07 10:13:30 -0700260 VersionUsesQpack(GetParam().transport_version);
renjietang2abedac2019-05-20 14:04:50 -0700261
262 if (version_uses_qpack) {
dschinazi552accc2019-06-17 17:07:34 -0700263 EXPECT_CALL(
264 *connection_,
265 CloseConnection(QUIC_HEADERS_STREAM_DATA_DECOMPRESS_FAILURE,
266 testing::MatchesRegex(
267 "Too large headers received on stream [0-9]+"),
268 _));
renjietang2abedac2019-05-20 14:04:50 -0700269 } else {
270 EXPECT_CALL(*session_,
271 SendRstStream(stream_->id(), QUIC_HEADERS_TOO_LARGE, 0));
272 }
273
QUICHE teama6ef0a62019-03-07 20:34:33 -0500274 stream_->OnStreamHeaderList(false, 1 << 20, headers);
renjietang2abedac2019-05-20 14:04:50 -0700275
276 if (!version_uses_qpack) {
277 EXPECT_EQ(QUIC_HEADERS_TOO_LARGE, stream_->stream_error());
278 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500279}
280
281TEST_P(QuicSpdyStreamTest, ProcessHeaderListWithFin) {
282 Initialize(kShouldProcessData);
283
284 size_t total_bytes = 0;
285 QuicHeaderList headers;
286 for (auto p : headers_) {
287 headers.OnHeader(p.first, p.second);
288 total_bytes += p.first.size() + p.second.size();
289 }
290 stream_->OnStreamHeadersPriority(kV3HighestPriority);
291 stream_->OnStreamHeaderList(true, total_bytes, headers);
292 EXPECT_EQ("", stream_->data());
293 EXPECT_FALSE(stream_->header_list().empty());
294 EXPECT_FALSE(stream_->IsDoneReading());
295 EXPECT_TRUE(stream_->HasFinalReceivedByteOffset());
296}
297
bnc677451a2019-06-07 10:13:30 -0700298// A valid status code should be 3-digit integer. The first digit should be in
299// the range of [1, 5]. All the others are invalid.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500300TEST_P(QuicSpdyStreamTest, ParseHeaderStatusCode) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500301 Initialize(kShouldProcessData);
302 int status_code = 0;
303
304 // Valid status codes.
305 headers_[":status"] = "404";
306 EXPECT_TRUE(stream_->ParseHeaderStatusCode(headers_, &status_code));
307 EXPECT_EQ(404, status_code);
308
309 headers_[":status"] = "100";
310 EXPECT_TRUE(stream_->ParseHeaderStatusCode(headers_, &status_code));
311 EXPECT_EQ(100, status_code);
312
313 headers_[":status"] = "599";
314 EXPECT_TRUE(stream_->ParseHeaderStatusCode(headers_, &status_code));
315 EXPECT_EQ(599, status_code);
316
317 // Invalid status codes.
318 headers_[":status"] = "010";
319 EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
320
321 headers_[":status"] = "600";
322 EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
323
324 headers_[":status"] = "200 ok";
325 EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
326
327 headers_[":status"] = "2000";
328 EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
329
330 headers_[":status"] = "+200";
331 EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
332
333 headers_[":status"] = "+20";
334 EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
335
336 headers_[":status"] = "-10";
337 EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
338
339 headers_[":status"] = "-100";
340 EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
341
342 // Leading or trailing spaces are also invalid.
343 headers_[":status"] = " 200";
344 EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
345
346 headers_[":status"] = "200 ";
347 EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
348
349 headers_[":status"] = " 200 ";
350 EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
351
352 headers_[":status"] = " ";
353 EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
354}
355
356TEST_P(QuicSpdyStreamTest, MarkHeadersConsumed) {
357 Initialize(kShouldProcessData);
358
vasilvvc48c8712019-03-11 13:38:16 -0700359 std::string body = "this is the body";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500360 QuicHeaderList headers = ProcessHeaders(false, headers_);
361 EXPECT_EQ(headers, stream_->header_list());
362
363 stream_->ConsumeHeaderList();
364 EXPECT_EQ(QuicHeaderList(), stream_->header_list());
365}
366
QUICHE team396d1092019-03-20 10:21:07 -0700367TEST_P(QuicSpdyStreamTest, ProcessWrongFramesOnSpdyStream) {
QUICHE team396d1092019-03-20 10:21:07 -0700368 if (!HasFrameHeader()) {
369 return;
370 }
bnc677451a2019-06-07 10:13:30 -0700371
372 testing::InSequence s;
373 Initialize(kShouldProcessData);
QUICHE team396d1092019-03-20 10:21:07 -0700374 connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
375 GoAwayFrame goaway;
376 goaway.stream_id = 0x1;
377 std::unique_ptr<char[]> buffer;
378 QuicByteCount header_length = encoder_.SerializeGoAwayFrame(goaway, &buffer);
379 std::string data = std::string(buffer.get(), header_length);
380
381 EXPECT_EQ("", stream_->data());
382 QuicHeaderList headers = ProcessHeaders(false, headers_);
383 EXPECT_EQ(headers, stream_->header_list());
384 stream_->ConsumeHeaderList();
385 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
386 QuicStringPiece(data));
387
388 EXPECT_CALL(*connection_, CloseConnection(QUIC_HTTP_DECODER_ERROR, _, _))
389 .WillOnce(
390 (Invoke([this](QuicErrorCode error, const std::string& error_details,
391 ConnectionCloseBehavior connection_close_behavior) {
392 connection_->ReallyCloseConnection(error, error_details,
393 connection_close_behavior);
394 })));
ianswettdc1e7ab2019-05-03 16:10:44 -0700395 EXPECT_CALL(*connection_, SendConnectionClosePacket(_, _));
QUICHE team396d1092019-03-20 10:21:07 -0700396 EXPECT_CALL(*session_, OnConnectionClosed(_, _, _))
397 .WillOnce(
398 Invoke([this](QuicErrorCode error, const std::string& error_details,
399 ConnectionCloseSource source) {
400 session_->ReallyOnConnectionClosed(error, error_details, source);
401 }));
402 EXPECT_CALL(*session_, SendRstStream(_, _, _));
403 EXPECT_CALL(*session_, SendRstStream(_, _, _));
404
405 stream_->OnStreamFrame(frame);
406}
407
QUICHE teama6ef0a62019-03-07 20:34:33 -0500408TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBody) {
409 Initialize(kShouldProcessData);
410
vasilvvc48c8712019-03-11 13:38:16 -0700411 std::string body = "this is the body";
bnc9f977e42019-06-07 11:36:34 -0700412 std::string data = HasFrameHeader() ? DataFrame(body) : body;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500413
414 EXPECT_EQ("", stream_->data());
415 QuicHeaderList headers = ProcessHeaders(false, headers_);
416 EXPECT_EQ(headers, stream_->header_list());
417 stream_->ConsumeHeaderList();
418 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
419 QuicStringPiece(data));
420 stream_->OnStreamFrame(frame);
421 EXPECT_EQ(QuicHeaderList(), stream_->header_list());
422 EXPECT_EQ(body, stream_->data());
423}
424
425TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBodyFragments) {
vasilvvc48c8712019-03-11 13:38:16 -0700426 std::string body = "this is the body";
bnc9f977e42019-06-07 11:36:34 -0700427 std::string data = HasFrameHeader() ? DataFrame(body) : body;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500428
429 for (size_t fragment_size = 1; fragment_size < data.size(); ++fragment_size) {
430 Initialize(kShouldProcessData);
431 QuicHeaderList headers = ProcessHeaders(false, headers_);
432 ASSERT_EQ(headers, stream_->header_list());
433 stream_->ConsumeHeaderList();
434 for (size_t offset = 0; offset < data.size(); offset += fragment_size) {
435 size_t remaining_data = data.size() - offset;
436 QuicStringPiece fragment(data.data() + offset,
437 std::min(fragment_size, remaining_data));
438 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false,
439 offset, QuicStringPiece(fragment));
440 stream_->OnStreamFrame(frame);
441 }
442 ASSERT_EQ(body, stream_->data()) << "fragment_size: " << fragment_size;
443 }
444}
445
446TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBodyFragmentsSplit) {
vasilvvc48c8712019-03-11 13:38:16 -0700447 std::string body = "this is the body";
bnc9f977e42019-06-07 11:36:34 -0700448 std::string data = HasFrameHeader() ? DataFrame(body) : body;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500449
450 for (size_t split_point = 1; split_point < data.size() - 1; ++split_point) {
451 Initialize(kShouldProcessData);
452 QuicHeaderList headers = ProcessHeaders(false, headers_);
453 ASSERT_EQ(headers, stream_->header_list());
454 stream_->ConsumeHeaderList();
455
456 QuicStringPiece fragment1(data.data(), split_point);
457 QuicStreamFrame frame1(GetNthClientInitiatedBidirectionalId(0), false, 0,
458 QuicStringPiece(fragment1));
459 stream_->OnStreamFrame(frame1);
460
461 QuicStringPiece fragment2(data.data() + split_point,
462 data.size() - split_point);
463 QuicStreamFrame frame2(GetNthClientInitiatedBidirectionalId(0), false,
464 split_point, QuicStringPiece(fragment2));
465 stream_->OnStreamFrame(frame2);
466
467 ASSERT_EQ(body, stream_->data()) << "split_point: " << split_point;
468 }
469}
470
471TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBodyReadv) {
472 Initialize(!kShouldProcessData);
473
vasilvvc48c8712019-03-11 13:38:16 -0700474 std::string body = "this is the body";
bnc9f977e42019-06-07 11:36:34 -0700475 std::string data = HasFrameHeader() ? DataFrame(body) : body;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500476
477 ProcessHeaders(false, headers_);
478 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
479 QuicStringPiece(data));
480 stream_->OnStreamFrame(frame);
481 stream_->ConsumeHeaderList();
482
483 char buffer[2048];
484 ASSERT_LT(data.length(), QUIC_ARRAYSIZE(buffer));
485 struct iovec vec;
486 vec.iov_base = buffer;
487 vec.iov_len = QUIC_ARRAYSIZE(buffer);
488
489 size_t bytes_read = stream_->Readv(&vec, 1);
QUICHE team396d1092019-03-20 10:21:07 -0700490 QuicStreamPeer::CloseReadSide(stream_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500491 EXPECT_EQ(body.length(), bytes_read);
vasilvvc48c8712019-03-11 13:38:16 -0700492 EXPECT_EQ(body, std::string(buffer, bytes_read));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500493}
494
495TEST_P(QuicSpdyStreamTest, ProcessHeadersAndLargeBodySmallReadv) {
496 Initialize(kShouldProcessData);
vasilvvc48c8712019-03-11 13:38:16 -0700497 std::string body(12 * 1024, 'a');
bnc9f977e42019-06-07 11:36:34 -0700498 std::string data = HasFrameHeader() ? DataFrame(body) : body;
499
QUICHE teama6ef0a62019-03-07 20:34:33 -0500500 ProcessHeaders(false, headers_);
501 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
502 QuicStringPiece(data));
503 stream_->OnStreamFrame(frame);
504 stream_->ConsumeHeaderList();
505 char buffer[2048];
506 char buffer2[2048];
507 struct iovec vec[2];
508 vec[0].iov_base = buffer;
509 vec[0].iov_len = QUIC_ARRAYSIZE(buffer);
510 vec[1].iov_base = buffer2;
511 vec[1].iov_len = QUIC_ARRAYSIZE(buffer2);
512 size_t bytes_read = stream_->Readv(vec, 2);
513 EXPECT_EQ(2048u * 2, bytes_read);
vasilvvc48c8712019-03-11 13:38:16 -0700514 EXPECT_EQ(body.substr(0, 2048), std::string(buffer, 2048));
515 EXPECT_EQ(body.substr(2048, 2048), std::string(buffer2, 2048));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500516}
517
518TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBodyMarkConsumed) {
519 Initialize(!kShouldProcessData);
520
vasilvvc48c8712019-03-11 13:38:16 -0700521 std::string body = "this is the body";
bnc9f977e42019-06-07 11:36:34 -0700522 std::string data = HasFrameHeader() ? DataFrame(body) : body;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500523
524 ProcessHeaders(false, headers_);
525 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
526 QuicStringPiece(data));
527 stream_->OnStreamFrame(frame);
528 stream_->ConsumeHeaderList();
529
530 struct iovec vec;
531
532 EXPECT_EQ(1, stream_->GetReadableRegions(&vec, 1));
533 EXPECT_EQ(body.length(), vec.iov_len);
vasilvvc48c8712019-03-11 13:38:16 -0700534 EXPECT_EQ(body, std::string(static_cast<char*>(vec.iov_base), vec.iov_len));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500535
536 stream_->MarkConsumed(body.length());
537 EXPECT_EQ(data.length(), stream_->flow_controller()->bytes_consumed());
538}
539
540TEST_P(QuicSpdyStreamTest, ProcessHeadersAndConsumeMultipleBody) {
541 Initialize(!kShouldProcessData);
vasilvvc48c8712019-03-11 13:38:16 -0700542 std::string body1 = "this is body 1";
bnc9f977e42019-06-07 11:36:34 -0700543 std::string data1 = HasFrameHeader() ? DataFrame(body1) : body1;
vasilvvc48c8712019-03-11 13:38:16 -0700544 std::string body2 = "body 2";
bnc9f977e42019-06-07 11:36:34 -0700545 std::string data2 = HasFrameHeader() ? DataFrame(body2) : body2;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500546
547 ProcessHeaders(false, headers_);
548 QuicStreamFrame frame1(GetNthClientInitiatedBidirectionalId(0), false, 0,
549 QuicStringPiece(data1));
550 QuicStreamFrame frame2(GetNthClientInitiatedBidirectionalId(0), false,
551 data1.length(), QuicStringPiece(data2));
552 stream_->OnStreamFrame(frame1);
553 stream_->OnStreamFrame(frame2);
554 stream_->ConsumeHeaderList();
555
556 stream_->MarkConsumed(body1.length() + body2.length());
557 EXPECT_EQ(data1.length() + data2.length(),
558 stream_->flow_controller()->bytes_consumed());
559}
560
561TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBodyIncrementalReadv) {
562 Initialize(!kShouldProcessData);
563
vasilvvc48c8712019-03-11 13:38:16 -0700564 std::string body = "this is the body";
bnc9f977e42019-06-07 11:36:34 -0700565 std::string data = HasFrameHeader() ? DataFrame(body) : body;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500566
567 ProcessHeaders(false, headers_);
568 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
569 QuicStringPiece(data));
570 stream_->OnStreamFrame(frame);
571 stream_->ConsumeHeaderList();
572
573 char buffer[1];
574 struct iovec vec;
575 vec.iov_base = buffer;
576 vec.iov_len = QUIC_ARRAYSIZE(buffer);
577
578 for (size_t i = 0; i < body.length(); ++i) {
579 size_t bytes_read = stream_->Readv(&vec, 1);
580 ASSERT_EQ(1u, bytes_read);
581 EXPECT_EQ(body.data()[i], buffer[0]);
582 }
583}
584
585TEST_P(QuicSpdyStreamTest, ProcessHeadersUsingReadvWithMultipleIovecs) {
586 Initialize(!kShouldProcessData);
587
vasilvvc48c8712019-03-11 13:38:16 -0700588 std::string body = "this is the body";
bnc9f977e42019-06-07 11:36:34 -0700589 std::string data = HasFrameHeader() ? DataFrame(body) : body;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500590
591 ProcessHeaders(false, headers_);
592 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
593 QuicStringPiece(data));
594 stream_->OnStreamFrame(frame);
595 stream_->ConsumeHeaderList();
596
597 char buffer1[1];
598 char buffer2[1];
599 struct iovec vec[2];
600 vec[0].iov_base = buffer1;
601 vec[0].iov_len = QUIC_ARRAYSIZE(buffer1);
602 vec[1].iov_base = buffer2;
603 vec[1].iov_len = QUIC_ARRAYSIZE(buffer2);
604
605 for (size_t i = 0; i < body.length(); i += 2) {
606 size_t bytes_read = stream_->Readv(vec, 2);
607 ASSERT_EQ(2u, bytes_read) << i;
608 ASSERT_EQ(body.data()[i], buffer1[0]) << i;
609 ASSERT_EQ(body.data()[i + 1], buffer2[0]) << i;
610 }
611}
612
bnc677451a2019-06-07 10:13:30 -0700613// Tests that we send a BLOCKED frame to the peer when we attempt to write, but
614// are flow control blocked.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500615TEST_P(QuicSpdyStreamTest, StreamFlowControlBlocked) {
nharperf5e68452019-05-29 17:24:18 -0700616 if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) {
617 // TODO(nharper, b/112643533): Figure out why this test fails when TLS is
618 // enabled and fix it.
619 return;
620 }
bnc677451a2019-06-07 10:13:30 -0700621
QUICHE teama6ef0a62019-03-07 20:34:33 -0500622 testing::InSequence seq;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500623 Initialize(kShouldProcessData);
624
625 // Set a small flow control limit.
626 const uint64_t kWindow = 36;
627 QuicFlowControllerPeer::SetSendWindowOffset(stream_->flow_controller(),
628 kWindow);
629 EXPECT_EQ(kWindow, QuicFlowControllerPeer::SendWindowOffset(
630 stream_->flow_controller()));
631
632 // Try to send more data than the flow control limit allows.
633 const uint64_t kOverflow = 15;
vasilvvc48c8712019-03-11 13:38:16 -0700634 std::string body(kWindow + kOverflow, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500635
636 const uint64_t kHeaderLength = HasFrameHeader() ? 2 : 0;
637 if (HasFrameHeader()) {
638 EXPECT_CALL(*session_, WritevData(_, _, kHeaderLength, _, NO_FIN));
639 }
640 EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
641 .WillOnce(Return(QuicConsumedData(kWindow - kHeaderLength, true)));
642 EXPECT_CALL(*connection_, SendControlFrame(_));
643 stream_->WriteOrBufferBody(body, false);
644
645 // Should have sent as much as possible, resulting in no send window left.
646 EXPECT_EQ(0u,
647 QuicFlowControllerPeer::SendWindowSize(stream_->flow_controller()));
648
649 // And we should have queued the overflowed data.
bncc7d9e0c2019-04-16 10:22:15 -0700650 EXPECT_EQ(kOverflow + kHeaderLength, stream_->BufferedDataBytes());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500651}
652
bnc677451a2019-06-07 10:13:30 -0700653// The flow control receive window decreases whenever we add new bytes to the
654// sequencer, whether they are consumed immediately or buffered. However we only
655// send WINDOW_UPDATE frames based on increasing number of bytes consumed.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500656TEST_P(QuicSpdyStreamTest, StreamFlowControlNoWindowUpdateIfNotConsumed) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500657 // Don't process data - it will be buffered instead.
658 Initialize(!kShouldProcessData);
659
660 // Expect no WINDOW_UPDATE frames to be sent.
661 EXPECT_CALL(*connection_, SendWindowUpdate(_, _)).Times(0);
662
663 // Set a small flow control receive window.
664 const uint64_t kWindow = 36;
665 QuicFlowControllerPeer::SetReceiveWindowOffset(stream_->flow_controller(),
666 kWindow);
667 QuicFlowControllerPeer::SetMaxReceiveWindow(stream_->flow_controller(),
668 kWindow);
669 EXPECT_EQ(kWindow, QuicFlowControllerPeer::ReceiveWindowOffset(
670 stream_->flow_controller()));
671
672 // Stream receives enough data to fill a fraction of the receive window.
vasilvvc48c8712019-03-11 13:38:16 -0700673 std::string body(kWindow / 3, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500674 QuicByteCount header_length = 0;
vasilvvc48c8712019-03-11 13:38:16 -0700675 std::string data;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500676
677 if (HasFrameHeader()) {
678 std::unique_ptr<char[]> buffer;
679 header_length = encoder_.SerializeDataFrameHeader(body.length(), &buffer);
vasilvvc48c8712019-03-11 13:38:16 -0700680 std::string header = std::string(buffer.get(), header_length);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500681 data = header + body;
682 } else {
683 data = body;
684 }
685
686 ProcessHeaders(false, headers_);
687
688 QuicStreamFrame frame1(GetNthClientInitiatedBidirectionalId(0), false, 0,
689 QuicStringPiece(data));
690 stream_->OnStreamFrame(frame1);
691 EXPECT_EQ(
692 kWindow - (kWindow / 3) - header_length,
693 QuicFlowControllerPeer::ReceiveWindowSize(stream_->flow_controller()));
694
695 // Now receive another frame which results in the receive window being over
696 // half full. This should all be buffered, decreasing the receive window but
697 // not sending WINDOW_UPDATE.
698 QuicStreamFrame frame2(GetNthClientInitiatedBidirectionalId(0), false,
699 kWindow / 3 + header_length, QuicStringPiece(data));
700 stream_->OnStreamFrame(frame2);
701 EXPECT_EQ(
702 kWindow - (2 * kWindow / 3) - 2 * header_length,
703 QuicFlowControllerPeer::ReceiveWindowSize(stream_->flow_controller()));
704}
705
bnc677451a2019-06-07 10:13:30 -0700706// Tests that on receipt of data, the stream updates its receive window offset
707// appropriately, and sends WINDOW_UPDATE frames when its receive window drops
708// too low.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500709TEST_P(QuicSpdyStreamTest, StreamFlowControlWindowUpdate) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500710 Initialize(kShouldProcessData);
711
712 // Set a small flow control limit.
713 const uint64_t kWindow = 36;
714 QuicFlowControllerPeer::SetReceiveWindowOffset(stream_->flow_controller(),
715 kWindow);
716 QuicFlowControllerPeer::SetMaxReceiveWindow(stream_->flow_controller(),
717 kWindow);
718 EXPECT_EQ(kWindow, QuicFlowControllerPeer::ReceiveWindowOffset(
719 stream_->flow_controller()));
720
721 // Stream receives enough data to fill a fraction of the receive window.
vasilvvc48c8712019-03-11 13:38:16 -0700722 std::string body(kWindow / 3, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500723 QuicByteCount header_length = 0;
vasilvvc48c8712019-03-11 13:38:16 -0700724 std::string data;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500725
726 if (HasFrameHeader()) {
727 std::unique_ptr<char[]> buffer;
728 header_length = encoder_.SerializeDataFrameHeader(body.length(), &buffer);
vasilvvc48c8712019-03-11 13:38:16 -0700729 std::string header = std::string(buffer.get(), header_length);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500730 data = header + body;
731 } else {
732 data = body;
733 }
734
735 ProcessHeaders(false, headers_);
736 stream_->ConsumeHeaderList();
737
738 QuicStreamFrame frame1(GetNthClientInitiatedBidirectionalId(0), false, 0,
739 QuicStringPiece(data));
740 stream_->OnStreamFrame(frame1);
741 EXPECT_EQ(
742 kWindow - (kWindow / 3) - header_length,
743 QuicFlowControllerPeer::ReceiveWindowSize(stream_->flow_controller()));
744
745 // Now receive another frame which results in the receive window being over
746 // half full. This will trigger the stream to increase its receive window
747 // offset and send a WINDOW_UPDATE. The result will be again an available
748 // window of kWindow bytes.
749 QuicStreamFrame frame2(GetNthClientInitiatedBidirectionalId(0), false,
750 kWindow / 3 + header_length, QuicStringPiece(data));
751 EXPECT_CALL(*connection_, SendControlFrame(_));
752 stream_->OnStreamFrame(frame2);
753 EXPECT_EQ(kWindow, QuicFlowControllerPeer::ReceiveWindowSize(
754 stream_->flow_controller()));
755}
756
bnc677451a2019-06-07 10:13:30 -0700757// Tests that on receipt of data, the connection updates its receive window
758// offset appropriately, and sends WINDOW_UPDATE frames when its receive window
759// drops too low.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500760TEST_P(QuicSpdyStreamTest, ConnectionFlowControlWindowUpdate) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500761 Initialize(kShouldProcessData);
762
763 // Set a small flow control limit for streams and connection.
764 const uint64_t kWindow = 36;
765 QuicFlowControllerPeer::SetReceiveWindowOffset(stream_->flow_controller(),
766 kWindow);
767 QuicFlowControllerPeer::SetMaxReceiveWindow(stream_->flow_controller(),
768 kWindow);
769 QuicFlowControllerPeer::SetReceiveWindowOffset(stream2_->flow_controller(),
770 kWindow);
771 QuicFlowControllerPeer::SetMaxReceiveWindow(stream2_->flow_controller(),
772 kWindow);
773 QuicFlowControllerPeer::SetReceiveWindowOffset(session_->flow_controller(),
774 kWindow);
775 QuicFlowControllerPeer::SetMaxReceiveWindow(session_->flow_controller(),
776 kWindow);
777
778 // Supply headers to both streams so that they are happy to receive data.
779 auto headers = AsHeaderList(headers_);
780 stream_->OnStreamHeaderList(false, headers.uncompressed_header_bytes(),
781 headers);
782 stream_->ConsumeHeaderList();
783 stream2_->OnStreamHeaderList(false, headers.uncompressed_header_bytes(),
784 headers);
785 stream2_->ConsumeHeaderList();
786
787 // Each stream gets a quarter window of data. This should not trigger a
788 // WINDOW_UPDATE for either stream, nor for the connection.
789 QuicByteCount header_length = 0;
vasilvvc48c8712019-03-11 13:38:16 -0700790 std::string body;
791 std::string data;
792 std::string data2;
793 std::string body2(1, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500794
795 if (HasFrameHeader()) {
vasilvvc48c8712019-03-11 13:38:16 -0700796 body = std::string(kWindow / 4 - 2, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500797 std::unique_ptr<char[]> buffer;
798 header_length = encoder_.SerializeDataFrameHeader(body.length(), &buffer);
vasilvvc48c8712019-03-11 13:38:16 -0700799 std::string header = std::string(buffer.get(), header_length);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500800 data = header + body;
801 std::unique_ptr<char[]> buffer2;
802 QuicByteCount header_length2 =
803 encoder_.SerializeDataFrameHeader(body2.length(), &buffer2);
vasilvvc48c8712019-03-11 13:38:16 -0700804 std::string header2 = std::string(buffer2.get(), header_length2);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500805 data2 = header2 + body2;
806 } else {
vasilvvc48c8712019-03-11 13:38:16 -0700807 body = std::string(kWindow / 4, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500808 data = body;
809 data2 = body2;
810 }
811
812 QuicStreamFrame frame1(GetNthClientInitiatedBidirectionalId(0), false, 0,
813 QuicStringPiece(data));
814 stream_->OnStreamFrame(frame1);
815 QuicStreamFrame frame2(GetNthClientInitiatedBidirectionalId(1), false, 0,
816 QuicStringPiece(data));
817 stream2_->OnStreamFrame(frame2);
818
819 // Now receive a further single byte on one stream - again this does not
820 // trigger a stream WINDOW_UPDATE, but now the connection flow control window
821 // is over half full and thus a connection WINDOW_UPDATE is sent.
822 EXPECT_CALL(*connection_, SendControlFrame(_));
823 QuicStreamFrame frame3(GetNthClientInitiatedBidirectionalId(0), false,
824 body.length() + header_length, QuicStringPiece(data2));
825 stream_->OnStreamFrame(frame3);
826}
827
bnc677451a2019-06-07 10:13:30 -0700828// Tests that on if the peer sends too much data (i.e. violates the flow control
829// protocol), then we terminate the connection.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500830TEST_P(QuicSpdyStreamTest, StreamFlowControlViolation) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500831 // Stream should not process data, so that data gets buffered in the
832 // sequencer, triggering flow control limits.
833 Initialize(!kShouldProcessData);
834
835 // Set a small flow control limit.
836 const uint64_t kWindow = 50;
837 QuicFlowControllerPeer::SetReceiveWindowOffset(stream_->flow_controller(),
838 kWindow);
839
840 ProcessHeaders(false, headers_);
841
842 // Receive data to overflow the window, violating flow control.
vasilvvc48c8712019-03-11 13:38:16 -0700843 std::string body(kWindow + 1, 'a');
bnc9f977e42019-06-07 11:36:34 -0700844 std::string data = HasFrameHeader() ? DataFrame(body) : body;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500845 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
846 QuicStringPiece(data));
847 EXPECT_CALL(*connection_,
848 CloseConnection(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA, _, _));
849 stream_->OnStreamFrame(frame);
850}
851
852TEST_P(QuicSpdyStreamTest, TestHandlingQuicRstStreamNoError) {
853 Initialize(kShouldProcessData);
854 ProcessHeaders(false, headers_);
855
856 stream_->OnStreamReset(QuicRstStreamFrame(
857 kInvalidControlFrameId, stream_->id(), QUIC_STREAM_NO_ERROR, 0));
858 EXPECT_TRUE(stream_->write_side_closed());
859 EXPECT_FALSE(stream_->reading_stopped());
860}
861
bnc677451a2019-06-07 10:13:30 -0700862// Tests that on if the peer sends too much data (i.e. violates the flow control
863// protocol), at the connection level (rather than the stream level) then we
864// terminate the connection.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500865TEST_P(QuicSpdyStreamTest, ConnectionFlowControlViolation) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500866 // Stream should not process data, so that data gets buffered in the
867 // sequencer, triggering flow control limits.
868 Initialize(!kShouldProcessData);
869
870 // Set a small flow control window on streams, and connection.
871 const uint64_t kStreamWindow = 50;
872 const uint64_t kConnectionWindow = 10;
873 QuicFlowControllerPeer::SetReceiveWindowOffset(stream_->flow_controller(),
874 kStreamWindow);
875 QuicFlowControllerPeer::SetReceiveWindowOffset(session_->flow_controller(),
876 kConnectionWindow);
877
878 ProcessHeaders(false, headers_);
879
880 // Send enough data to overflow the connection level flow control window.
vasilvvc48c8712019-03-11 13:38:16 -0700881 std::string body(kConnectionWindow + 1, 'a');
bnc9f977e42019-06-07 11:36:34 -0700882 std::string data = HasFrameHeader() ? DataFrame(body) : body;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500883
884 EXPECT_LT(data.size(), kStreamWindow);
885 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
886 QuicStringPiece(data));
887
888 EXPECT_CALL(*connection_,
889 CloseConnection(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA, _, _));
890 stream_->OnStreamFrame(frame);
891}
892
bnc677451a2019-06-07 10:13:30 -0700893// An attempt to write a FIN with no data should not be flow control blocked,
894// even if the send window is 0.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500895TEST_P(QuicSpdyStreamTest, StreamFlowControlFinNotBlocked) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500896 Initialize(kShouldProcessData);
897
898 // Set a flow control limit of zero.
899 QuicFlowControllerPeer::SetReceiveWindowOffset(stream_->flow_controller(), 0);
900 EXPECT_EQ(0u, QuicFlowControllerPeer::ReceiveWindowOffset(
901 stream_->flow_controller()));
902
903 // Send a frame with a FIN but no data. This should not be blocked.
vasilvvc48c8712019-03-11 13:38:16 -0700904 std::string body = "";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500905 bool fin = true;
906
907 EXPECT_CALL(*connection_,
908 SendBlocked(GetNthClientInitiatedBidirectionalId(0)))
909 .Times(0);
910 EXPECT_CALL(*session_, WritevData(_, _, 0, _, FIN));
911
912 stream_->WriteOrBufferBody(body, fin);
913}
914
bnc677451a2019-06-07 10:13:30 -0700915// Test that receiving trailing headers from the peer via OnStreamHeaderList()
916// works, and can be read from the stream and consumed.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500917TEST_P(QuicSpdyStreamTest, ReceivingTrailersViaHeaderList) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500918 Initialize(kShouldProcessData);
919
920 // Receive initial headers.
921 size_t total_bytes = 0;
922 QuicHeaderList headers;
923 for (const auto& p : headers_) {
924 headers.OnHeader(p.first, p.second);
925 total_bytes += p.first.size() + p.second.size();
926 }
927
928 stream_->OnStreamHeadersPriority(kV3HighestPriority);
929 stream_->OnStreamHeaderList(/*fin=*/false, total_bytes, headers);
930 stream_->ConsumeHeaderList();
931
932 // Receive trailing headers.
933 SpdyHeaderBlock trailers_block;
934 trailers_block["key1"] = "value1";
935 trailers_block["key2"] = "value2";
936 trailers_block["key3"] = "value3";
937 SpdyHeaderBlock trailers_block_with_final_offset = trailers_block.Clone();
renjietang2abedac2019-05-20 14:04:50 -0700938 if (!VersionUsesQpack(GetParam().transport_version)) {
939 // :final-offset pseudo-header is only added if trailers are sent
940 // on the headers stream.
941 trailers_block_with_final_offset[kFinalOffsetHeaderKey] = "0";
942 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500943 total_bytes = 0;
944 QuicHeaderList trailers;
945 for (const auto& p : trailers_block_with_final_offset) {
946 trailers.OnHeader(p.first, p.second);
947 total_bytes += p.first.size() + p.second.size();
948 }
949 stream_->OnStreamHeaderList(/*fin=*/true, total_bytes, trailers);
950
951 // The trailers should be decompressed, and readable from the stream.
952 EXPECT_TRUE(stream_->trailers_decompressed());
953 EXPECT_EQ(trailers_block, stream_->received_trailers());
954
955 // IsDoneReading() returns false until trailers marked consumed.
956 EXPECT_FALSE(stream_->IsDoneReading());
957 stream_->MarkTrailersConsumed();
958 EXPECT_TRUE(stream_->IsDoneReading());
959}
960
bnc677451a2019-06-07 10:13:30 -0700961// Test that when receiving trailing headers with an offset before response
962// body, stream is closed at the right offset.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500963TEST_P(QuicSpdyStreamTest, ReceivingTrailersWithOffset) {
renjietang2abedac2019-05-20 14:04:50 -0700964 // kFinalOffsetHeaderKey is not used when HEADERS are sent on the
965 // request/response stream.
966 if (VersionUsesQpack(GetParam().transport_version)) {
967 return;
968 }
969
bnc677451a2019-06-07 10:13:30 -0700970 Initialize(kShouldProcessData);
971
QUICHE teama6ef0a62019-03-07 20:34:33 -0500972 // Receive initial headers.
973 QuicHeaderList headers = ProcessHeaders(false, headers_);
974 stream_->ConsumeHeaderList();
975
vasilvvc48c8712019-03-11 13:38:16 -0700976 const std::string body = "this is the body";
bnc9f977e42019-06-07 11:36:34 -0700977 std::string data = HasFrameHeader() ? DataFrame(body) : body;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500978
979 // Receive trailing headers.
980 SpdyHeaderBlock trailers_block;
981 trailers_block["key1"] = "value1";
982 trailers_block["key2"] = "value2";
983 trailers_block["key3"] = "value3";
984 trailers_block[kFinalOffsetHeaderKey] =
985 QuicTextUtils::Uint64ToString(data.size());
986
987 QuicHeaderList trailers = ProcessHeaders(true, trailers_block);
988
989 // The trailers should be decompressed, and readable from the stream.
990 EXPECT_TRUE(stream_->trailers_decompressed());
991
992 // The final offset trailer will be consumed by QUIC.
993 trailers_block.erase(kFinalOffsetHeaderKey);
994 EXPECT_EQ(trailers_block, stream_->received_trailers());
995
996 // Consuming the trailers erases them from the stream.
997 stream_->MarkTrailersConsumed();
998 EXPECT_TRUE(stream_->FinishedReadingTrailers());
999
1000 EXPECT_FALSE(stream_->IsDoneReading());
1001 // Receive and consume body.
1002 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), /*fin=*/false,
1003 0, data);
1004 stream_->OnStreamFrame(frame);
1005 EXPECT_EQ(body, stream_->data());
1006 EXPECT_TRUE(stream_->IsDoneReading());
1007}
1008
bnc677451a2019-06-07 10:13:30 -07001009// Test that receiving trailers without a final offset field is an error.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001010TEST_P(QuicSpdyStreamTest, ReceivingTrailersWithoutOffset) {
renjietang2abedac2019-05-20 14:04:50 -07001011 // kFinalOffsetHeaderKey is not used when HEADERS are sent on the
1012 // request/response stream.
1013 if (VersionUsesQpack(GetParam().transport_version)) {
1014 return;
1015 }
1016
bnc677451a2019-06-07 10:13:30 -07001017 Initialize(kShouldProcessData);
1018
QUICHE teama6ef0a62019-03-07 20:34:33 -05001019 // Receive initial headers.
1020 ProcessHeaders(false, headers_);
1021 stream_->ConsumeHeaderList();
1022
1023 // Receive trailing headers, without kFinalOffsetHeaderKey.
1024 SpdyHeaderBlock trailers_block;
1025 trailers_block["key1"] = "value1";
1026 trailers_block["key2"] = "value2";
1027 trailers_block["key3"] = "value3";
1028 auto trailers = AsHeaderList(trailers_block);
1029
1030 // Verify that the trailers block didn't contain a final offset.
1031 EXPECT_EQ("", trailers_block[kFinalOffsetHeaderKey].as_string());
1032
1033 // Receipt of the malformed trailers will close the connection.
1034 EXPECT_CALL(*connection_,
1035 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA, _, _))
1036 .Times(1);
1037 stream_->OnStreamHeaderList(/*fin=*/true,
1038 trailers.uncompressed_header_bytes(), trailers);
1039}
1040
renjietang2abedac2019-05-20 14:04:50 -07001041TEST_P(QuicSpdyStreamTest, ReceivingTrailersOnRequestStream) {
renjietang2abedac2019-05-20 14:04:50 -07001042 if (!VersionUsesQpack(GetParam().transport_version)) {
1043 return;
1044 }
1045
bnc677451a2019-06-07 10:13:30 -07001046 Initialize(kShouldProcessData);
1047
renjietang2abedac2019-05-20 14:04:50 -07001048 // Receive initial headers.
1049 QuicHeaderList headers = ProcessHeaders(false, headers_);
1050 stream_->ConsumeHeaderList();
1051
1052 const std::string body = "this is the body";
bnc9f977e42019-06-07 11:36:34 -07001053 std::string data = HasFrameHeader() ? DataFrame(body) : body;
renjietang2abedac2019-05-20 14:04:50 -07001054
1055 // Receive trailing headers.
1056 SpdyHeaderBlock trailers_block;
1057 trailers_block["key1"] = "value1";
1058 trailers_block["key2"] = "value2";
1059 trailers_block["key3"] = "value3";
1060
1061 QuicHeaderList trailers = ProcessHeaders(true, trailers_block);
1062
1063 // The trailers should be decompressed, and readable from the stream.
1064 EXPECT_TRUE(stream_->trailers_decompressed());
1065
1066 EXPECT_EQ(trailers_block, stream_->received_trailers());
1067
1068 // Consuming the trailers erases them from the stream.
1069 stream_->MarkTrailersConsumed();
1070 EXPECT_TRUE(stream_->FinishedReadingTrailers());
1071 EXPECT_TRUE(stream_->IsDoneReading());
1072
1073 // Receive and consume body.
1074 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), /*fin=*/false,
1075 0, data);
1076 stream_->OnStreamFrame(frame);
1077 EXPECT_EQ(body, stream_->data());
1078 EXPECT_TRUE(stream_->IsDoneReading());
1079}
1080
bnc677451a2019-06-07 10:13:30 -07001081// Test that received Trailers must always have the FIN set.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001082TEST_P(QuicSpdyStreamTest, ReceivingTrailersWithoutFin) {
renjietang2abedac2019-05-20 14:04:50 -07001083 // In IETF QUIC, there is no such thing as FIN flag on HTTP/3 frames like the
1084 // HEADERS frame.
1085 if (VersionUsesQpack(GetParam().transport_version)) {
1086 return;
1087 }
1088
bnc677451a2019-06-07 10:13:30 -07001089 Initialize(kShouldProcessData);
1090
QUICHE teama6ef0a62019-03-07 20:34:33 -05001091 // Receive initial headers.
1092 auto headers = AsHeaderList(headers_);
1093 stream_->OnStreamHeaderList(/*fin=*/false,
1094 headers.uncompressed_header_bytes(), headers);
1095 stream_->ConsumeHeaderList();
1096
1097 // Receive trailing headers with FIN deliberately set to false.
1098 SpdyHeaderBlock trailers_block;
1099 trailers_block["foo"] = "bar";
1100 auto trailers = AsHeaderList(trailers_block);
1101
1102 EXPECT_CALL(*connection_,
1103 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA, _, _))
1104 .Times(1);
1105 stream_->OnStreamHeaderList(/*fin=*/false,
1106 trailers.uncompressed_header_bytes(), trailers);
1107}
1108
1109TEST_P(QuicSpdyStreamTest, ReceivingTrailersAfterHeadersWithFin) {
1110 // If headers are received with a FIN, no trailers should then arrive.
1111 Initialize(kShouldProcessData);
1112
bnc8d041302019-06-10 10:19:04 -07001113 // If HEADERS frames are sent on the request/response stream, then the
1114 // sequencer will signal an error if any stream data arrives after a FIN,
1115 // so QuicSpdyStream does not need to.
1116 if (VersionUsesQpack(GetParam().transport_version)) {
1117 return;
1118 }
1119
QUICHE teama6ef0a62019-03-07 20:34:33 -05001120 // Receive initial headers with FIN set.
1121 ProcessHeaders(true, headers_);
1122 stream_->ConsumeHeaderList();
1123
1124 // Receive trailing headers after FIN already received.
1125 SpdyHeaderBlock trailers_block;
1126 trailers_block["foo"] = "bar";
1127 EXPECT_CALL(*connection_,
1128 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA, _, _))
1129 .Times(1);
1130 ProcessHeaders(true, trailers_block);
1131}
1132
bnc677451a2019-06-07 10:13:30 -07001133// If body data are received with a FIN, no trailers should then arrive.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001134TEST_P(QuicSpdyStreamTest, ReceivingTrailersAfterBodyWithFin) {
renjietang2abedac2019-05-20 14:04:50 -07001135 // If HEADERS frames are sent on the request/response stream,
1136 // then the sequencer will block them from reaching QuicSpdyStream
1137 // after the stream is closed.
1138 if (VersionUsesQpack(GetParam().transport_version)) {
1139 return;
1140 }
1141
bnc677451a2019-06-07 10:13:30 -07001142 Initialize(kShouldProcessData);
1143
QUICHE teama6ef0a62019-03-07 20:34:33 -05001144 // Receive initial headers without FIN set.
1145 ProcessHeaders(false, headers_);
1146 stream_->ConsumeHeaderList();
1147
1148 // Receive body data, with FIN.
1149 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), /*fin=*/true,
1150 0, "body");
1151 stream_->OnStreamFrame(frame);
1152
1153 // Receive trailing headers after FIN already received.
1154 SpdyHeaderBlock trailers_block;
1155 trailers_block["foo"] = "bar";
1156 EXPECT_CALL(*connection_,
1157 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA, _, _))
1158 .Times(1);
1159 ProcessHeaders(true, trailers_block);
1160}
1161
1162TEST_P(QuicSpdyStreamTest, ClosingStreamWithNoTrailers) {
1163 // Verify that a stream receiving headers, body, and no trailers is correctly
1164 // marked as done reading on consumption of headers and body.
1165 Initialize(kShouldProcessData);
1166
1167 // Receive and consume initial headers with FIN not set.
1168 auto h = AsHeaderList(headers_);
1169 stream_->OnStreamHeaderList(/*fin=*/false, h.uncompressed_header_bytes(), h);
1170 stream_->ConsumeHeaderList();
1171
1172 // Receive and consume body with FIN set, and no trailers.
vasilvvc48c8712019-03-11 13:38:16 -07001173 std::string body(1024, 'x');
bnc9f977e42019-06-07 11:36:34 -07001174 std::string data = HasFrameHeader() ? DataFrame(body) : body;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001175
1176 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), /*fin=*/true,
1177 0, data);
1178 stream_->OnStreamFrame(frame);
1179
1180 EXPECT_TRUE(stream_->IsDoneReading());
1181}
1182
bnc677451a2019-06-07 10:13:30 -07001183// Test that writing trailers will send a FIN, as Trailers are the last thing to
1184// be sent on a stream.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001185TEST_P(QuicSpdyStreamTest, WritingTrailersSendsAFin) {
nharperf5e68452019-05-29 17:24:18 -07001186 if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) {
1187 // TODO(nharper, b/112643533): Figure out why this test fails when TLS is
1188 // enabled and fix it.
1189 return;
1190 }
bnc677451a2019-06-07 10:13:30 -07001191
QUICHE teama6ef0a62019-03-07 20:34:33 -05001192 Initialize(kShouldProcessData);
1193
renjietang2abedac2019-05-20 14:04:50 -07001194 if (VersionUsesQpack(GetParam().transport_version)) {
1195 // In this case, TestStream::WriteHeadersImpl() does not prevent writes.
1196 EXPECT_CALL(*session_, WritevData(stream_, stream_->id(), _, _, _))
1197 .Times(AtLeast(1));
1198 }
1199
QUICHE teama6ef0a62019-03-07 20:34:33 -05001200 // Write the initial headers, without a FIN.
1201 EXPECT_CALL(*stream_, WriteHeadersMock(false));
1202 stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/false, nullptr);
1203
1204 // Writing trailers implicitly sends a FIN.
1205 SpdyHeaderBlock trailers;
1206 trailers["trailer key"] = "trailer value";
1207 EXPECT_CALL(*stream_, WriteHeadersMock(true));
1208 stream_->WriteTrailers(std::move(trailers), nullptr);
1209 EXPECT_TRUE(stream_->fin_sent());
1210}
1211
bnc677451a2019-06-07 10:13:30 -07001212// Test that when writing trailers, the trailers that are actually sent to the
1213// peer contain the final offset field indicating last byte of data.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001214TEST_P(QuicSpdyStreamTest, WritingTrailersFinalOffset) {
nharperf5e68452019-05-29 17:24:18 -07001215 if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) {
1216 // TODO(nharper, b/112643533): Figure out why this test fails when TLS is
1217 // enabled and fix it.
1218 return;
1219 }
bnc677451a2019-06-07 10:13:30 -07001220
QUICHE teama6ef0a62019-03-07 20:34:33 -05001221 Initialize(kShouldProcessData);
1222
renjietang2abedac2019-05-20 14:04:50 -07001223 if (VersionUsesQpack(GetParam().transport_version)) {
1224 // In this case, TestStream::WriteHeadersImpl() does not prevent writes.
1225 EXPECT_CALL(*session_, WritevData(stream_, stream_->id(), _, _, _))
1226 .Times(AtLeast(1));
1227 }
1228
QUICHE teama6ef0a62019-03-07 20:34:33 -05001229 // Write the initial headers.
1230 EXPECT_CALL(*stream_, WriteHeadersMock(false));
1231 stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/false, nullptr);
1232
1233 // Write non-zero body data to force a non-zero final offset.
1234 EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(AtLeast(1));
vasilvvc48c8712019-03-11 13:38:16 -07001235 std::string body(1024, 'x'); // 1 kB
QUICHE teama6ef0a62019-03-07 20:34:33 -05001236 QuicByteCount header_length = 0;
1237 if (HasFrameHeader()) {
1238 std::unique_ptr<char[]> buf;
1239 header_length = encoder_.SerializeDataFrameHeader(body.length(), &buf);
1240 }
1241
1242 stream_->WriteOrBufferBody(body, false);
1243
1244 // The final offset field in the trailing headers is populated with the
1245 // number of body bytes written (including queued bytes).
1246 SpdyHeaderBlock trailers;
1247 trailers["trailer key"] = "trailer value";
renjietang2abedac2019-05-20 14:04:50 -07001248
1249 SpdyHeaderBlock expected_trailers(trailers.Clone());
1250 // :final-offset pseudo-header is only added if trailers are sent
1251 // on the headers stream.
1252 if (!VersionUsesQpack(GetParam().transport_version)) {
1253 expected_trailers[kFinalOffsetHeaderKey] =
1254 QuicTextUtils::Uint64ToString(body.length() + header_length);
1255 }
1256
QUICHE teama6ef0a62019-03-07 20:34:33 -05001257 EXPECT_CALL(*stream_, WriteHeadersMock(true));
1258 stream_->WriteTrailers(std::move(trailers), nullptr);
renjietang2abedac2019-05-20 14:04:50 -07001259 EXPECT_EQ(expected_trailers, stream_->saved_headers());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001260}
1261
bnc677451a2019-06-07 10:13:30 -07001262// Test that if trailers are written after all other data has been written
1263// (headers and body), that this closes the stream for writing.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001264TEST_P(QuicSpdyStreamTest, WritingTrailersClosesWriteSide) {
nharperf5e68452019-05-29 17:24:18 -07001265 if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) {
1266 // TODO(nharper, b/112643533): Figure out why this test fails when TLS is
1267 // enabled and fix it.
1268 return;
1269 }
bnc677451a2019-06-07 10:13:30 -07001270
QUICHE teama6ef0a62019-03-07 20:34:33 -05001271 Initialize(kShouldProcessData);
1272
renjietang2abedac2019-05-20 14:04:50 -07001273 // Expect data being written on the stream. In addition to that, headers are
1274 // also written on the stream in case of IETF QUIC.
1275 EXPECT_CALL(*session_, WritevData(stream_, stream_->id(), _, _, _))
1276 .Times(AtLeast(1));
1277
QUICHE teama6ef0a62019-03-07 20:34:33 -05001278 // Write the initial headers.
1279 EXPECT_CALL(*stream_, WriteHeadersMock(false));
1280 stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/false, nullptr);
1281
1282 // Write non-zero body data.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001283 const int kBodySize = 1 * 1024; // 1 kB
vasilvvc48c8712019-03-11 13:38:16 -07001284 stream_->WriteOrBufferBody(std::string(kBodySize, 'x'), false);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001285 EXPECT_EQ(0u, stream_->BufferedDataBytes());
1286
1287 // Headers and body have been fully written, there is no queued data. Writing
1288 // trailers marks the end of this stream, and thus the write side is closed.
1289 EXPECT_CALL(*stream_, WriteHeadersMock(true));
1290 stream_->WriteTrailers(SpdyHeaderBlock(), nullptr);
1291 EXPECT_TRUE(stream_->write_side_closed());
1292}
1293
bnc677451a2019-06-07 10:13:30 -07001294// Test that the stream is not closed for writing when trailers are sent while
1295// there are still body bytes queued.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001296TEST_P(QuicSpdyStreamTest, WritingTrailersWithQueuedBytes) {
renjietang2abedac2019-05-20 14:04:50 -07001297 // This test exercises sending trailers on the headers stream while data is
1298 // still queued on the response/request stream. In IETF QUIC, data and
1299 // trailers are sent on the same stream, so this test does not apply.
1300 if (VersionUsesQpack(GetParam().transport_version)) {
1301 return;
1302 }
1303
QUICHE teama6ef0a62019-03-07 20:34:33 -05001304 testing::InSequence seq;
1305 Initialize(kShouldProcessData);
1306
1307 // Write the initial headers.
1308 EXPECT_CALL(*stream_, WriteHeadersMock(false));
1309 stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/false, nullptr);
1310
1311 // Write non-zero body data, but only consume partially, ensuring queueing.
1312 const int kBodySize = 1 * 1024; // 1 kB
1313 if (HasFrameHeader()) {
1314 EXPECT_CALL(*session_, WritevData(_, _, 3, _, NO_FIN));
1315 }
1316 EXPECT_CALL(*session_, WritevData(_, _, kBodySize, _, NO_FIN))
1317 .WillOnce(Return(QuicConsumedData(kBodySize - 1, false)));
vasilvvc48c8712019-03-11 13:38:16 -07001318 stream_->WriteOrBufferBody(std::string(kBodySize, 'x'), false);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001319 EXPECT_EQ(1u, stream_->BufferedDataBytes());
1320
1321 // Writing trailers will send a FIN, but not close the write side of the
1322 // stream as there are queued bytes.
1323 EXPECT_CALL(*stream_, WriteHeadersMock(true));
1324 stream_->WriteTrailers(SpdyHeaderBlock(), nullptr);
1325 EXPECT_TRUE(stream_->fin_sent());
1326 EXPECT_FALSE(stream_->write_side_closed());
1327
1328 // Writing the queued bytes will close the write side of the stream.
1329 EXPECT_CALL(*session_, WritevData(_, _, 1, _, NO_FIN));
1330 stream_->OnCanWrite();
1331 EXPECT_TRUE(stream_->write_side_closed());
1332}
1333
bnc677451a2019-06-07 10:13:30 -07001334// Test that it is not possible to write Trailers after a FIN has been sent.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001335TEST_P(QuicSpdyStreamTest, WritingTrailersAfterFIN) {
1336 // EXPECT_QUIC_BUG tests are expensive so only run one instance of them.
renjietang2abedac2019-05-20 14:04:50 -07001337 // In IETF QUIC, there is no such thing as FIN flag on HTTP/3 frames like the
1338 // HEADERS frame. That is version 99, which is element 0 of the array, so
1339 // pick another element.
1340 if (GetParam() != AllSupportedVersions()[1]) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001341 return;
1342 }
1343
QUICHE teama6ef0a62019-03-07 20:34:33 -05001344 Initialize(kShouldProcessData);
1345
1346 // Write the initial headers, with a FIN.
1347 EXPECT_CALL(*stream_, WriteHeadersMock(true));
1348 stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/true, nullptr);
1349 EXPECT_TRUE(stream_->fin_sent());
1350
1351 // Writing Trailers should fail, as the FIN has already been sent.
1352 // populated with the number of body bytes written.
1353 EXPECT_QUIC_BUG(stream_->WriteTrailers(SpdyHeaderBlock(), nullptr),
1354 "Trailers cannot be sent after a FIN");
1355}
1356
1357TEST_P(QuicSpdyStreamTest, HeaderStreamNotiferCorrespondingSpdyStream) {
bnc9f977e42019-06-07 11:36:34 -07001358 // There is no headers stream if QPACK is used.
1359 if (!VersionUsesQpack(GetParam().transport_version)) {
1360 return;
1361 }
1362
nharperf5e68452019-05-29 17:24:18 -07001363 if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) {
1364 // TODO(nharper, b/112643533): Figure out why this test fails when TLS is
1365 // enabled and fix it.
1366 return;
1367 }
bnc677451a2019-06-07 10:13:30 -07001368
bnc9f977e42019-06-07 11:36:34 -07001369 const char kHeader1[] = "Header1";
1370 const char kHeader2[] = "Header2";
1371 const char kBody1[] = "Test1";
1372 const char kBody2[] = "Test2";
1373
QUICHE teama6ef0a62019-03-07 20:34:33 -05001374 Initialize(kShouldProcessData);
1375 EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(AtLeast(1));
1376 testing::InSequence s;
1377 QuicReferenceCountedPointer<MockAckListener> ack_listener1(
1378 new MockAckListener());
1379 QuicReferenceCountedPointer<MockAckListener> ack_listener2(
1380 new MockAckListener());
1381 stream_->set_ack_listener(ack_listener1);
1382 stream2_->set_ack_listener(ack_listener2);
1383
bnc9f977e42019-06-07 11:36:34 -07001384 session_->headers_stream()->WriteOrBufferData(kHeader1, false, ack_listener1);
1385 stream_->WriteOrBufferBody(kBody1, true);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001386
bnc9f977e42019-06-07 11:36:34 -07001387 session_->headers_stream()->WriteOrBufferData(kHeader2, false, ack_listener2);
1388 stream2_->WriteOrBufferBody(kBody2, false);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001389
1390 QuicStreamFrame frame1(
1391 QuicUtils::GetHeadersStreamId(connection_->transport_version()), false, 0,
bnc9f977e42019-06-07 11:36:34 -07001392 kHeader1);
1393
1394 std::string data1 = HasFrameHeader() ? DataFrame(kBody1) : kBody1;
1395 QuicStreamFrame frame2(stream_->id(), true, 0, data1);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001396 QuicStreamFrame frame3(
1397 QuicUtils::GetHeadersStreamId(connection_->transport_version()), false, 7,
bnc9f977e42019-06-07 11:36:34 -07001398 kHeader2);
1399 std::string data2 = HasFrameHeader() ? DataFrame(kBody2) : kBody2;
1400 QuicStreamFrame frame4(stream2_->id(), false, 0, data2);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001401
1402 EXPECT_CALL(*ack_listener1, OnPacketRetransmitted(7));
1403 session_->OnStreamFrameRetransmitted(frame1);
1404
1405 EXPECT_CALL(*ack_listener1, OnPacketAcked(7, _));
QUICHE team9467db02019-05-30 09:38:45 -07001406 EXPECT_TRUE(session_->OnFrameAcked(QuicFrame(frame1), QuicTime::Delta::Zero(),
1407 QuicTime::Zero()));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001408 EXPECT_CALL(*ack_listener1, OnPacketAcked(5, _));
QUICHE team9467db02019-05-30 09:38:45 -07001409 EXPECT_TRUE(session_->OnFrameAcked(QuicFrame(frame2), QuicTime::Delta::Zero(),
1410 QuicTime::Zero()));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001411 EXPECT_CALL(*ack_listener2, OnPacketAcked(7, _));
QUICHE team9467db02019-05-30 09:38:45 -07001412 EXPECT_TRUE(session_->OnFrameAcked(QuicFrame(frame3), QuicTime::Delta::Zero(),
1413 QuicTime::Zero()));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001414 EXPECT_CALL(*ack_listener2, OnPacketAcked(5, _));
QUICHE team9467db02019-05-30 09:38:45 -07001415 EXPECT_TRUE(session_->OnFrameAcked(QuicFrame(frame4), QuicTime::Delta::Zero(),
1416 QuicTime::Zero()));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001417}
1418
1419TEST_P(QuicSpdyStreamTest, StreamBecomesZombieWithWriteThatCloses) {
nharperf5e68452019-05-29 17:24:18 -07001420 if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) {
1421 // TODO(nharper, b/112643533): Figure out why this test fails when TLS is
1422 // enabled and fix it.
1423 return;
1424 }
bnc677451a2019-06-07 10:13:30 -07001425
QUICHE teama6ef0a62019-03-07 20:34:33 -05001426 Initialize(kShouldProcessData);
1427 EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(AtLeast(1));
1428 QuicStreamPeer::CloseReadSide(stream_);
1429 // This write causes stream to be closed.
1430 stream_->WriteOrBufferBody("Test1", true);
1431 // stream_ has unacked data and should become zombie.
1432 EXPECT_TRUE(QuicContainsKey(QuicSessionPeer::zombie_streams(session_.get()),
1433 stream_->id()));
1434 EXPECT_TRUE(QuicSessionPeer::closed_streams(session_.get()).empty());
1435}
1436
1437TEST_P(QuicSpdyStreamTest, OnPriorityFrame) {
1438 Initialize(kShouldProcessData);
1439 stream_->OnPriorityFrame(kV3HighestPriority);
1440 EXPECT_EQ(kV3HighestPriority, stream_->priority());
1441}
1442
1443TEST_P(QuicSpdyStreamTest, OnPriorityFrameAfterSendingData) {
nharperf5e68452019-05-29 17:24:18 -07001444 if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) {
1445 // TODO(nharper, b/112643533): Figure out why this test fails when TLS is
1446 // enabled and fix it.
1447 return;
1448 }
bnc677451a2019-06-07 10:13:30 -07001449
QUICHE teama6ef0a62019-03-07 20:34:33 -05001450 testing::InSequence seq;
1451 Initialize(kShouldProcessData);
1452
1453 if (HasFrameHeader()) {
1454 EXPECT_CALL(*session_, WritevData(_, _, 2, _, NO_FIN));
1455 }
1456 EXPECT_CALL(*session_, WritevData(_, _, 4, _, FIN));
1457 stream_->WriteOrBufferBody("data", true);
1458 stream_->OnPriorityFrame(kV3HighestPriority);
1459 EXPECT_EQ(kV3HighestPriority, stream_->priority());
1460}
1461
1462TEST_P(QuicSpdyStreamTest, SetPriorityBeforeUpdateStreamPriority) {
1463 MockQuicConnection* connection = new StrictMock<MockQuicConnection>(
1464 &helper_, &alarm_factory_, Perspective::IS_SERVER,
1465 SupportedVersions(GetParam()));
1466 std::unique_ptr<TestMockUpdateStreamSession> session(
1467 new StrictMock<TestMockUpdateStreamSession>(connection));
1468 auto stream = new StrictMock<TestStream>(
1469 GetNthClientInitiatedBidirectionalStreamId(
1470 session->connection()->transport_version(), 0),
1471 session.get(),
1472 /*should_process_data=*/true);
1473 session->ActivateStream(QuicWrapUnique(stream));
1474
1475 // QuicSpdyStream::SetPriority() should eventually call UpdateStreamPriority()
1476 // on the session. Make sure stream->priority() returns the updated priority
1477 // if called within UpdateStreamPriority(). This expectation is enforced in
1478 // TestMockUpdateStreamSession::UpdateStreamPriority().
1479 session->SetExpectedStream(stream);
1480 session->SetExpectedPriority(kV3HighestPriority);
1481 stream->SetPriority(kV3HighestPriority);
1482
1483 session->SetExpectedPriority(kV3LowestPriority);
1484 stream->SetPriority(kV3LowestPriority);
1485}
1486
1487TEST_P(QuicSpdyStreamTest, StreamWaitsForAcks) {
nharperf5e68452019-05-29 17:24:18 -07001488 if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) {
1489 // TODO(nharper, b/112643533): Figure out why this test fails when TLS is
1490 // enabled and fix it.
1491 return;
1492 }
bnc677451a2019-06-07 10:13:30 -07001493
QUICHE teama6ef0a62019-03-07 20:34:33 -05001494 Initialize(kShouldProcessData);
1495 QuicReferenceCountedPointer<MockAckListener> mock_ack_listener(
1496 new StrictMock<MockAckListener>);
1497 stream_->set_ack_listener(mock_ack_listener);
1498 EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(AtLeast(1));
1499 // Stream is not waiting for acks initially.
1500 EXPECT_FALSE(stream_->IsWaitingForAcks());
1501 EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
1502
1503 // Send kData1.
1504 stream_->WriteOrBufferData("FooAndBar", false, nullptr);
1505 EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
1506 EXPECT_TRUE(stream_->IsWaitingForAcks());
1507 EXPECT_CALL(*mock_ack_listener, OnPacketAcked(9, _));
1508 QuicByteCount newly_acked_length = 0;
1509 EXPECT_TRUE(stream_->OnStreamFrameAcked(0, 9, false, QuicTime::Delta::Zero(),
1510 &newly_acked_length));
1511 // Stream is not waiting for acks as all sent data is acked.
1512 EXPECT_FALSE(stream_->IsWaitingForAcks());
1513 EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
1514
1515 // Send kData2.
1516 stream_->WriteOrBufferData("FooAndBar", false, nullptr);
1517 EXPECT_TRUE(stream_->IsWaitingForAcks());
1518 EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
1519 // Send FIN.
1520 stream_->WriteOrBufferData("", true, nullptr);
1521 // Fin only frame is not stored in send buffer.
1522 EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
1523
1524 // kData2 is retransmitted.
1525 EXPECT_CALL(*mock_ack_listener, OnPacketRetransmitted(9));
1526 stream_->OnStreamFrameRetransmitted(9, 9, false);
1527
1528 // kData2 is acked.
1529 EXPECT_CALL(*mock_ack_listener, OnPacketAcked(9, _));
1530 EXPECT_TRUE(stream_->OnStreamFrameAcked(9, 9, false, QuicTime::Delta::Zero(),
1531 &newly_acked_length));
1532 // Stream is waiting for acks as FIN is not acked.
1533 EXPECT_TRUE(stream_->IsWaitingForAcks());
1534 EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
1535
1536 // FIN is acked.
1537 EXPECT_CALL(*mock_ack_listener, OnPacketAcked(0, _));
1538 EXPECT_TRUE(stream_->OnStreamFrameAcked(18, 0, true, QuicTime::Delta::Zero(),
1539 &newly_acked_length));
1540 EXPECT_FALSE(stream_->IsWaitingForAcks());
1541 EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
1542}
1543
1544TEST_P(QuicSpdyStreamTest, StreamDataGetAckedMultipleTimes) {
nharperf5e68452019-05-29 17:24:18 -07001545 if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) {
1546 // TODO(nharper, b/112643533): Figure out why this test fails when TLS is
1547 // enabled and fix it.
1548 return;
1549 }
bnc677451a2019-06-07 10:13:30 -07001550
QUICHE teama6ef0a62019-03-07 20:34:33 -05001551 Initialize(kShouldProcessData);
1552 QuicReferenceCountedPointer<MockAckListener> mock_ack_listener(
1553 new StrictMock<MockAckListener>);
1554 stream_->set_ack_listener(mock_ack_listener);
1555 EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(AtLeast(1));
1556 // Send [0, 27) and fin.
1557 stream_->WriteOrBufferData("FooAndBar", false, nullptr);
1558 stream_->WriteOrBufferData("FooAndBar", false, nullptr);
1559 stream_->WriteOrBufferData("FooAndBar", true, nullptr);
1560
1561 // Ack [0, 9), [5, 22) and [18, 26)
1562 // Verify [0, 9) 9 bytes are acked.
1563 QuicByteCount newly_acked_length = 0;
1564 EXPECT_CALL(*mock_ack_listener, OnPacketAcked(9, _));
1565 EXPECT_TRUE(stream_->OnStreamFrameAcked(0, 9, false, QuicTime::Delta::Zero(),
1566 &newly_acked_length));
1567 EXPECT_EQ(2u, QuicStreamPeer::SendBuffer(stream_).size());
1568 // Verify [9, 22) 13 bytes are acked.
1569 EXPECT_CALL(*mock_ack_listener, OnPacketAcked(13, _));
1570 EXPECT_TRUE(stream_->OnStreamFrameAcked(5, 17, false, QuicTime::Delta::Zero(),
1571 &newly_acked_length));
1572 EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
1573 // Verify [22, 26) 4 bytes are acked.
1574 EXPECT_CALL(*mock_ack_listener, OnPacketAcked(4, _));
1575 EXPECT_TRUE(stream_->OnStreamFrameAcked(18, 8, false, QuicTime::Delta::Zero(),
1576 &newly_acked_length));
1577 EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
1578 EXPECT_TRUE(stream_->IsWaitingForAcks());
1579
1580 // Ack [0, 27).
1581 // Verify [26, 27) 1 byte is acked.
1582 EXPECT_CALL(*mock_ack_listener, OnPacketAcked(1, _));
1583 EXPECT_TRUE(stream_->OnStreamFrameAcked(26, 1, false, QuicTime::Delta::Zero(),
1584 &newly_acked_length));
1585 EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
1586 EXPECT_TRUE(stream_->IsWaitingForAcks());
1587
1588 // Ack Fin. Verify OnPacketAcked is called.
1589 EXPECT_CALL(*mock_ack_listener, OnPacketAcked(0, _));
1590 EXPECT_TRUE(stream_->OnStreamFrameAcked(27, 0, true, QuicTime::Delta::Zero(),
1591 &newly_acked_length));
1592 EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
1593 EXPECT_FALSE(stream_->IsWaitingForAcks());
1594
1595 // Ack [10, 27) and fin.
1596 // No new data is acked, verify OnPacketAcked is not called.
1597 EXPECT_CALL(*mock_ack_listener, OnPacketAcked(_, _)).Times(0);
1598 EXPECT_FALSE(stream_->OnStreamFrameAcked(
1599 10, 17, true, QuicTime::Delta::Zero(), &newly_acked_length));
1600 EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
1601 EXPECT_FALSE(stream_->IsWaitingForAcks());
1602}
1603
1604// HTTP/3 only.
1605TEST_P(QuicSpdyStreamTest, HeadersAckNotReportedWriteOrBufferBody) {
nharperf5e68452019-05-29 17:24:18 -07001606 if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) {
1607 // TODO(nharper, b/112643533): Figure out why this test fails when TLS is
1608 // enabled and fix it.
1609 return;
1610 }
bnc677451a2019-06-07 10:13:30 -07001611
QUICHE teama6ef0a62019-03-07 20:34:33 -05001612 if (!HasFrameHeader()) {
1613 return;
1614 }
bnc677451a2019-06-07 10:13:30 -07001615
1616 Initialize(kShouldProcessData);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001617 QuicReferenceCountedPointer<MockAckListener> mock_ack_listener(
1618 new StrictMock<MockAckListener>);
1619 stream_->set_ack_listener(mock_ack_listener);
vasilvvc48c8712019-03-11 13:38:16 -07001620 std::string body = "Test1";
1621 std::string body2(100, 'x');
QUICHE teama6ef0a62019-03-07 20:34:33 -05001622
1623 EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(AtLeast(1));
1624 stream_->WriteOrBufferBody(body, false);
1625 stream_->WriteOrBufferBody(body2, true);
1626
1627 std::unique_ptr<char[]> buffer;
1628 QuicByteCount header_length =
1629 encoder_.SerializeDataFrameHeader(body.length(), &buffer);
vasilvvc48c8712019-03-11 13:38:16 -07001630 std::string header = std::string(buffer.get(), header_length);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001631
1632 header_length = encoder_.SerializeDataFrameHeader(body2.length(), &buffer);
vasilvvc48c8712019-03-11 13:38:16 -07001633 std::string header2 = std::string(buffer.get(), header_length);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001634
1635 EXPECT_CALL(*mock_ack_listener, OnPacketAcked(body.length(), _));
1636 QuicStreamFrame frame(stream_->id(), false, 0, header + body);
QUICHE team9467db02019-05-30 09:38:45 -07001637 EXPECT_TRUE(session_->OnFrameAcked(QuicFrame(frame), QuicTime::Delta::Zero(),
1638 QuicTime::Zero()));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001639
1640 EXPECT_CALL(*mock_ack_listener, OnPacketAcked(0, _));
bnc9f977e42019-06-07 11:36:34 -07001641 QuicStreamFrame frame2(stream_->id(), false, header.length() + body.length(),
QUICHE teama6ef0a62019-03-07 20:34:33 -05001642 header2);
QUICHE team9467db02019-05-30 09:38:45 -07001643 EXPECT_TRUE(session_->OnFrameAcked(QuicFrame(frame2), QuicTime::Delta::Zero(),
1644 QuicTime::Zero()));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001645
1646 EXPECT_CALL(*mock_ack_listener, OnPacketAcked(body2.length(), _));
1647 QuicStreamFrame frame3(stream_->id(), true,
bnc9f977e42019-06-07 11:36:34 -07001648 header.length() + body.length() + header2.length(),
1649 body2);
QUICHE team9467db02019-05-30 09:38:45 -07001650 EXPECT_TRUE(session_->OnFrameAcked(QuicFrame(frame3), QuicTime::Delta::Zero(),
1651 QuicTime::Zero()));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001652
1653 EXPECT_TRUE(
1654 QuicSpdyStreamPeer::unacked_frame_headers_offsets(stream_).Empty());
1655}
1656
1657// HTTP/3 only.
1658TEST_P(QuicSpdyStreamTest, HeadersAckNotReportedWriteBodySlices) {
nharperf5e68452019-05-29 17:24:18 -07001659 if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) {
1660 // TODO(nharper, b/112643533): Figure out why this test fails when TLS is
1661 // enabled and fix it.
1662 return;
1663 }
bnc677451a2019-06-07 10:13:30 -07001664
QUICHE teama6ef0a62019-03-07 20:34:33 -05001665 if (!HasFrameHeader()) {
1666 return;
1667 }
bnc677451a2019-06-07 10:13:30 -07001668
1669 Initialize(kShouldProcessData);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001670 QuicReferenceCountedPointer<MockAckListener> mock_ack_listener(
1671 new StrictMock<MockAckListener>);
1672 stream_->set_ack_listener(mock_ack_listener);
bnc9f977e42019-06-07 11:36:34 -07001673 std::string body1 = "Test1";
vasilvvc48c8712019-03-11 13:38:16 -07001674 std::string body2(100, 'x');
bnc9f977e42019-06-07 11:36:34 -07001675 struct iovec body1_iov = {const_cast<char*>(body1.data()), body1.length()};
QUICHE teama6ef0a62019-03-07 20:34:33 -05001676 struct iovec body2_iov = {const_cast<char*>(body2.data()), body2.length()};
1677 QuicMemSliceStorage storage(&body1_iov, 1,
1678 helper_.GetStreamSendBufferAllocator(), 1024);
1679 QuicMemSliceStorage storage2(&body2_iov, 1,
1680 helper_.GetStreamSendBufferAllocator(), 1024);
1681 EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(AtLeast(1));
1682 stream_->WriteBodySlices(storage.ToSpan(), false);
1683 stream_->WriteBodySlices(storage2.ToSpan(), true);
1684
bnc9f977e42019-06-07 11:36:34 -07001685 std::string data1 = DataFrame(body1);
1686 std::string data2 = DataFrame(body2);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001687
1688 EXPECT_CALL(*mock_ack_listener,
bnc9f977e42019-06-07 11:36:34 -07001689 OnPacketAcked(body1.length() + body2.length(), _));
1690 QuicStreamFrame frame(stream_->id(), true, 0, data1 + data2);
QUICHE team9467db02019-05-30 09:38:45 -07001691 EXPECT_TRUE(session_->OnFrameAcked(QuicFrame(frame), QuicTime::Delta::Zero(),
1692 QuicTime::Zero()));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001693
1694 EXPECT_TRUE(
1695 QuicSpdyStreamPeer::unacked_frame_headers_offsets(stream_).Empty());
1696}
1697
1698// HTTP/3 only.
1699TEST_P(QuicSpdyStreamTest, HeaderBytesNotReportedOnRetransmission) {
nharperf5e68452019-05-29 17:24:18 -07001700 if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) {
1701 // TODO(nharper, b/112643533): Figure out why this test fails when TLS is
1702 // enabled and fix it.
1703 return;
1704 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001705 if (!HasFrameHeader()) {
1706 return;
1707 }
bnc677451a2019-06-07 10:13:30 -07001708
1709 Initialize(kShouldProcessData);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001710 QuicReferenceCountedPointer<MockAckListener> mock_ack_listener(
1711 new StrictMock<MockAckListener>);
1712 stream_->set_ack_listener(mock_ack_listener);
bnc9f977e42019-06-07 11:36:34 -07001713 std::string body1 = "Test1";
vasilvvc48c8712019-03-11 13:38:16 -07001714 std::string body2(100, 'x');
QUICHE teama6ef0a62019-03-07 20:34:33 -05001715
1716 EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(AtLeast(1));
bnc9f977e42019-06-07 11:36:34 -07001717 stream_->WriteOrBufferBody(body1, false);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001718 stream_->WriteOrBufferBody(body2, true);
1719
bnc9f977e42019-06-07 11:36:34 -07001720 std::string data1 = DataFrame(body1);
1721 std::string data2 = DataFrame(body2);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001722
bnc9f977e42019-06-07 11:36:34 -07001723 EXPECT_CALL(*mock_ack_listener, OnPacketRetransmitted(body1.length()));
1724 QuicStreamFrame frame(stream_->id(), false, 0, data1);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001725 session_->OnStreamFrameRetransmitted(frame);
1726
1727 EXPECT_CALL(*mock_ack_listener, OnPacketRetransmitted(body2.length()));
bnc9f977e42019-06-07 11:36:34 -07001728 QuicStreamFrame frame2(stream_->id(), true, data1.length(), data2);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001729 session_->OnStreamFrameRetransmitted(frame2);
1730
1731 EXPECT_FALSE(
1732 QuicSpdyStreamPeer::unacked_frame_headers_offsets(stream_).Empty());
1733}
1734
renjietang2abedac2019-05-20 14:04:50 -07001735TEST_P(QuicSpdyStreamTest, HeadersFrameOnRequestStream) {
1736 if (!VersionUsesQpack(GetParam().transport_version)) {
1737 return;
1738 }
1739
1740 Initialize(kShouldProcessData);
1741
bnc9f977e42019-06-07 11:36:34 -07001742 // HEADERS frame with QPACK encoded single header field "foo: bar".
1743 std::string headers =
1744 HeadersFrame(QuicTextUtils::HexDecode("00002a94e703626172"));
1745 std::string data = DataFrame(kDataFramePayload);
1746 // HEADERS frame with QPACK encoded single header
1747 // field "custom-key: custom-value".
1748 std::string trailers = HeadersFrame(
1749 QuicTextUtils::HexDecode("00002f0125a849e95ba97d7f8925a849e95bb8e8b4bf"));
renjietang2abedac2019-05-20 14:04:50 -07001750
bnc9f977e42019-06-07 11:36:34 -07001751 std::string stream_frame_payload = QuicStrCat(headers, data, trailers);
renjietang2abedac2019-05-20 14:04:50 -07001752 QuicStreamFrame frame(stream_->id(), false, 0, stream_frame_payload);
1753 stream_->OnStreamFrame(frame);
1754
bnc8d041302019-06-10 10:19:04 -07001755 EXPECT_THAT(stream_->header_list(), ElementsAre(Pair("foo", "bar")));
renjietang2abedac2019-05-20 14:04:50 -07001756
1757 // QuicSpdyStream only calls OnBodyAvailable()
1758 // after the header list has been consumed.
1759 EXPECT_EQ("", stream_->data());
1760 stream_->ConsumeHeaderList();
bnc9f977e42019-06-07 11:36:34 -07001761 EXPECT_EQ(kDataFramePayload, stream_->data());
renjietang2abedac2019-05-20 14:04:50 -07001762
bnc8d041302019-06-10 10:19:04 -07001763 EXPECT_THAT(stream_->received_trailers(),
1764 ElementsAre(Pair("custom-key", "custom-value")));
renjietang2abedac2019-05-20 14:04:50 -07001765}
1766
renjietangbd1a0392019-05-31 11:36:24 -07001767TEST_P(QuicSpdyStreamTest, ProcessBodyAfterTrailers) {
1768 if (!VersionUsesQpack(GetParam().transport_version)) {
1769 return;
1770 }
bnc677451a2019-06-07 10:13:30 -07001771
1772 Initialize(!kShouldProcessData);
renjietangbd1a0392019-05-31 11:36:24 -07001773
bnc9f977e42019-06-07 11:36:34 -07001774 // HEADERS frame with QPACK encoded single header field "foo: bar".
1775 std::string headers =
1776 HeadersFrame(QuicTextUtils::HexDecode("00002a94e703626172"));
1777 std::string data = DataFrame(kDataFramePayload);
renjietangbd1a0392019-05-31 11:36:24 -07001778
1779 // A header block that will take more than one block of sequencer buffer.
1780 // This ensures that when the trailers are consumed, some buffer buckets will
1781 // be freed.
1782 SpdyHeaderBlock trailers_block;
1783 trailers_block["key1"] = std::string(10000, 'x');
1784 std::string trailers_frame_payload =
1785 EncodeQpackHeaders(stream_->id(), &trailers_block);
bnc9f977e42019-06-07 11:36:34 -07001786 std::string trailers = HeadersFrame(trailers_frame_payload);
renjietangbd1a0392019-05-31 11:36:24 -07001787
bnc9f977e42019-06-07 11:36:34 -07001788 std::string stream_frame_payload = QuicStrCat(headers, data, trailers);
renjietangbd1a0392019-05-31 11:36:24 -07001789 QuicStreamFrame frame(stream_->id(), false, 0, stream_frame_payload);
1790 stream_->OnStreamFrame(frame);
1791
1792 stream_->ConsumeHeaderList();
1793 stream_->MarkTrailersConsumed();
1794 char buffer[2048];
1795 struct iovec vec;
1796 vec.iov_base = buffer;
1797 vec.iov_len = QUIC_ARRAYSIZE(buffer);
1798 size_t bytes_read = stream_->Readv(&vec, 1);
bnc9f977e42019-06-07 11:36:34 -07001799 EXPECT_EQ(kDataFramePayload, QuicStringPiece(buffer, bytes_read));
renjietangbd1a0392019-05-31 11:36:24 -07001800}
1801
bnc677451a2019-06-07 10:13:30 -07001802// The test stream will receive a stream frame containing malformed headers and
1803// normal body. Make sure the http decoder stops processing body after the
1804// connection shuts down.
renjietang546a6282019-06-03 10:21:21 -07001805TEST_P(QuicSpdyStreamTest, MalformedHeadersStopHttpDecoder) {
renjietang546a6282019-06-03 10:21:21 -07001806 if (!VersionUsesQpack(GetParam().transport_version)) {
1807 return;
1808 }
1809
bnc677451a2019-06-07 10:13:30 -07001810 testing::InSequence s;
1811
renjietang546a6282019-06-03 10:21:21 -07001812 Initialize(kShouldProcessData);
1813 connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
1814
1815 // Random bad headers.
bnc9f977e42019-06-07 11:36:34 -07001816 std::string headers =
1817 HeadersFrame(QuicTextUtils::HexDecode("00002a94e7036261"));
1818 std::string data = DataFrame(kDataFramePayload);
renjietang546a6282019-06-03 10:21:21 -07001819
bnc9f977e42019-06-07 11:36:34 -07001820 std::string stream_frame_payload = QuicStrCat(headers, data);
renjietang546a6282019-06-03 10:21:21 -07001821 QuicStreamFrame frame(stream_->id(), false, 0, stream_frame_payload);
1822
dschinazi552accc2019-06-17 17:07:34 -07001823 EXPECT_CALL(
1824 *connection_,
1825 CloseConnection(QUIC_DECOMPRESSION_FAILURE,
1826 testing::MatchesRegex(
1827 "Error decompressing header block on stream [0-9]+: "
1828 "Incomplete header block."),
1829 _))
renjietang546a6282019-06-03 10:21:21 -07001830 .WillOnce(
1831 (Invoke([this](QuicErrorCode error, const std::string& error_details,
1832 ConnectionCloseBehavior connection_close_behavior) {
1833 connection_->ReallyCloseConnection(error, error_details,
1834 connection_close_behavior);
1835 })));
1836 EXPECT_CALL(*connection_, SendConnectionClosePacket(_, _));
1837 EXPECT_CALL(*session_, OnConnectionClosed(_, _, _))
1838 .WillOnce(
1839 Invoke([this](QuicErrorCode error, const std::string& error_details,
1840 ConnectionCloseSource source) {
1841 session_->ReallyOnConnectionClosed(error, error_details, source);
1842 }));
1843 EXPECT_CALL(*session_, SendRstStream(_, _, _));
1844 EXPECT_CALL(*session_, SendRstStream(_, _, _));
1845 stream_->OnStreamFrame(frame);
1846}
1847
bnc8d041302019-06-10 10:19:04 -07001848class QuicSpdyStreamIncrementalConsumptionTest : public QuicSpdyStreamTest {
1849 protected:
1850 QuicSpdyStreamIncrementalConsumptionTest() : offset_(0), consumed_bytes_(0) {}
1851 ~QuicSpdyStreamIncrementalConsumptionTest() override = default;
1852
1853 // Create QuicStreamFrame with |payload|
1854 // and pass it to stream_->OnStreamFrame().
1855 void OnStreamFrame(QuicStringPiece payload) {
1856 QuicStreamFrame frame(stream_->id(), /* fin = */ false, offset_, payload);
1857 stream_->OnStreamFrame(frame);
1858 offset_ += payload.size();
1859 }
1860
1861 // Return number of bytes marked consumed with sequencer
1862 // since last NewlyConsumedBytes() call.
1863 QuicStreamOffset NewlyConsumedBytes() {
1864 QuicStreamOffset previously_consumed_bytes = consumed_bytes_;
1865 consumed_bytes_ = stream_->sequencer()->NumBytesConsumed();
1866 return consumed_bytes_ - previously_consumed_bytes;
1867 }
1868
1869 // Read |size| bytes from the stream.
1870 std::string ReadFromStream(QuicByteCount size) {
1871 std::string buffer;
1872 buffer.resize(size);
1873
1874 struct iovec vec;
1875 vec.iov_base = const_cast<char*>(buffer.data());
1876 vec.iov_len = size;
1877
1878 size_t bytes_read = stream_->Readv(&vec, 1);
1879 EXPECT_EQ(bytes_read, size);
1880
1881 return buffer;
1882 }
1883
1884 private:
1885 QuicStreamOffset offset_;
1886 QuicStreamOffset consumed_bytes_;
1887};
1888
1889INSTANTIATE_TEST_SUITE_P(Tests,
1890 QuicSpdyStreamIncrementalConsumptionTest,
1891 ::testing::Values(ParsedQuicVersion{PROTOCOL_TLS1_3,
1892 QUIC_VERSION_99}));
1893
1894// Test that stream bytes are consumed (by calling
1895// sequencer()->MarkConsumed()) incrementally, as soon as possible.
1896TEST_P(QuicSpdyStreamIncrementalConsumptionTest, IncrementalConsumptionTest) {
1897 if (!VersionUsesQpack(GetParam().transport_version)) {
1898 return;
1899 }
1900
1901 Initialize(!kShouldProcessData);
1902
1903 // HEADERS frame with QPACK encoded single header field "foo: bar".
1904 std::string headers =
1905 HeadersFrame(QuicTextUtils::HexDecode("00002a94e703626172"));
1906
1907 // All HEADERS frame bytes are consumed even if the frame is not received
1908 // completely (as long as at least some of the payload is received, which is
1909 // an implementation detail that should not be tested).
1910 OnStreamFrame(QuicStringPiece(headers).substr(0, headers.size() - 1));
1911 EXPECT_EQ(headers.size() - 1, NewlyConsumedBytes());
1912
1913 // The rest of the HEADERS frame is also consumed immediately.
1914 OnStreamFrame(QuicStringPiece(headers).substr(headers.size() - 1));
1915 EXPECT_EQ(1u, NewlyConsumedBytes());
1916
1917 // Verify headers.
1918 EXPECT_THAT(stream_->header_list(), ElementsAre(Pair("foo", "bar")));
1919 stream_->ConsumeHeaderList();
1920
1921 // DATA frame.
1922 QuicStringPiece data_payload(kDataFramePayload);
1923 std::string data_frame = DataFrame(data_payload);
1924
1925 // DATA frame is not consumed because payload has to be buffered.
1926 // TODO(bnc): Consume frame header as soon as possible.
1927 OnStreamFrame(data_frame);
1928 EXPECT_EQ(0u, NewlyConsumedBytes());
1929
1930 // Consume all but last byte of data.
1931 EXPECT_EQ(data_payload.substr(0, data_payload.size() - 1),
1932 ReadFromStream(data_payload.size() - 1));
1933 EXPECT_EQ(data_frame.size() - 1, NewlyConsumedBytes());
1934
1935 // Trailing HEADERS frame with QPACK encoded
1936 // single header field "custom-key: custom-value".
1937 std::string trailers = HeadersFrame(
1938 QuicTextUtils::HexDecode("00002f0125a849e95ba97d7f8925a849e95bb8e8b4bf"));
1939
1940 // No bytes are consumed, because last byte of DATA payload is still buffered.
1941 OnStreamFrame(QuicStringPiece(trailers).substr(0, trailers.size() - 1));
1942 EXPECT_EQ(0u, NewlyConsumedBytes());
1943
1944 // Reading last byte of DATA payload triggers consumption of all data received
1945 // so far, even though last HEADERS frame has not been received completely.
1946 EXPECT_EQ(data_payload.substr(data_payload.size() - 1), ReadFromStream(1));
1947 EXPECT_EQ(1 + trailers.size() - 1, NewlyConsumedBytes());
1948
1949 // Last byte of trailers is immediately consumed.
1950 OnStreamFrame(QuicStringPiece(trailers).substr(trailers.size() - 1));
1951 EXPECT_EQ(1u, NewlyConsumedBytes());
1952
1953 // Verify trailers.
1954 EXPECT_THAT(stream_->received_trailers(),
1955 ElementsAre(Pair("custom-key", "custom-value")));
1956}
1957
QUICHE teama6ef0a62019-03-07 20:34:33 -05001958} // namespace
1959} // namespace test
1960} // namespace quic