blob: 7a8b22d501b51aeef0082f602891827e53d9b751 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright (c) 2017 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/quartc/quartc_stream.h"
6
7#include <memory>
vasilvv872e7a32019-03-12 16:42:44 -07008#include <string>
QUICHE teama6ef0a62019-03-07 20:34:33 -05009#include <type_traits>
10#include <utility>
11
QUICHE teama6ef0a62019-03-07 20:34:33 -050012#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
13#include "net/third_party/quiche/src/quic/core/frames/quic_stream_frame.h"
14#include "net/third_party/quiche/src/quic/core/quic_alarm_factory.h"
15#include "net/third_party/quiche/src/quic/core/quic_buffer_allocator.h"
vasilvv89713d02020-02-11 14:33:26 -080016#include "net/third_party/quiche/src/quic/core/quic_clock.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050017#include "net/third_party/quiche/src/quic/core/quic_config.h"
18#include "net/third_party/quiche/src/quic/core/quic_connection.h"
19#include "net/third_party/quiche/src/quic/core/quic_crypto_stream.h"
20#include "net/third_party/quiche/src/quic/core/quic_data_writer.h"
21#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
22#include "net/third_party/quiche/src/quic/core/quic_packet_writer.h"
23#include "net/third_party/quiche/src/quic/core/quic_session.h"
24#include "net/third_party/quiche/src/quic/core/quic_simple_buffer_allocator.h"
25#include "net/third_party/quiche/src/quic/core/quic_time.h"
26#include "net/third_party/quiche/src/quic/core/quic_types.h"
27#include "net/third_party/quiche/src/quic/core/quic_utils.h"
28#include "net/third_party/quiche/src/quic/core/quic_versions.h"
29#include "net/third_party/quiche/src/quic/core/quic_write_blocked_list.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050030#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
31#include "net/third_party/quiche/src/quic/platform/api/quic_ip_address.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050032#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050033#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
34#include "net/third_party/quiche/src/quic/platform/api/quic_test_mem_slice_vector.h"
35#include "net/third_party/quiche/src/quic/quartc/quartc_factory.h"
36#include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
37#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
QUICHE team173c48f2019-11-19 16:34:44 -080038#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050039#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
40
bnc13895832019-11-27 08:40:50 -080041using ::quic::test::IsQuicStreamNoError;
42using ::quic::test::IsStreamError;
43
QUICHE teama6ef0a62019-03-07 20:34:33 -050044namespace quic {
45
46namespace {
47
48static const QuicStreamId kStreamId = 5;
49
50// MockQuicSession that does not create streams and writes data from
51// QuicStream to a string.
52class MockQuicSession : public QuicSession {
53 public:
54 MockQuicSession(QuicConnection* connection,
55 const QuicConfig& config,
vasilvvc48c8712019-03-11 13:38:16 -070056 std::string* write_buffer)
QUICHE teama6ef0a62019-03-07 20:34:33 -050057 : QuicSession(connection,
58 nullptr /*visitor*/,
59 config,
renjietang216dc012019-08-27 11:28:27 -070060 CurrentSupportedVersions(),
61 /*num_expected_unidirectional_static_streams = */ 0),
QUICHE teama6ef0a62019-03-07 20:34:33 -050062 write_buffer_(write_buffer) {}
63
64 ~MockQuicSession() override {}
65
66 // Writes outgoing data from QuicStream to a string.
renjietang41a1b412020-02-27 15:05:14 -080067 QuicConsumedData WritevData(
68 QuicStreamId id,
69 size_t write_length,
70 QuicStreamOffset offset,
71 StreamSendingState state,
renjietang4d992bf2020-03-03 13:01:55 -080072 TransmissionType /*type*/,
renjietang41a1b412020-02-27 15:05:14 -080073 quiche::QuicheOptional<EncryptionLevel> /*level*/) override {
QUICHE teama6ef0a62019-03-07 20:34:33 -050074 if (!writable_) {
75 return QuicConsumedData(0, false);
76 }
77
78 // WritevData does not pass down a iovec, data is saved in stream before
79 // data is consumed. Retrieve data from stream.
80 char* buf = new char[write_length];
QUICHE team173c48f2019-11-19 16:34:44 -080081 QuicDataWriter writer(write_length, buf, quiche::NETWORK_BYTE_ORDER);
renjietang7c239172020-02-21 13:50:39 -080082 QuicStream* stream = GetOrCreateStream(id);
83 DCHECK(stream);
QUICHE teama6ef0a62019-03-07 20:34:33 -050084 if (write_length > 0) {
85 stream->WriteStreamData(offset, write_length, &writer);
86 }
87 write_buffer_->append(buf, write_length);
88 delete[] buf;
89 return QuicConsumedData(write_length, state != StreamSendingState::NO_FIN);
90 }
91
dschinazi17d42422019-06-18 16:35:07 -070092 QuartcStream* CreateIncomingStream(QuicStreamId /*id*/) override {
QUICHE teama6ef0a62019-03-07 20:34:33 -050093 return nullptr;
94 }
95
dschinazi17d42422019-06-18 16:35:07 -070096 QuartcStream* CreateIncomingStream(PendingStream* /*pending*/) override {
QUICHE teama6ef0a62019-03-07 20:34:33 -050097 return nullptr;
98 }
99
100 const QuicCryptoStream* GetCryptoStream() const override { return nullptr; }
101 QuicCryptoStream* GetMutableCryptoStream() override { return nullptr; }
102 bool ShouldKeepConnectionAlive() const override {
renjietang17e29932019-08-08 10:04:31 -0700103 return GetNumActiveStreams() > 0;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500104 }
105
106 // Called by QuicStream when they want to close stream.
dschinazi17d42422019-06-18 16:35:07 -0700107 void SendRstStream(QuicStreamId /*id*/,
108 QuicRstStreamErrorCode /*error*/,
109 QuicStreamOffset /*bytes_written*/) override {}
QUICHE teama6ef0a62019-03-07 20:34:33 -0500110
111 // Sets whether data is written to buffer, or else if this is write blocked.
112 void set_writable(bool writable) { writable_ = writable; }
113
114 // Tracks whether the stream is write blocked and its priority.
115 void RegisterReliableStream(QuicStreamId stream_id,
116 spdy::SpdyPriority priority) {
fayang476683a2019-07-25 12:42:16 -0700117 write_blocked_streams()->RegisterStream(
118 stream_id,
119 /*is_static_stream=*/false, spdy::SpdyStreamPrecedence(priority));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500120 }
121
122 // The session take ownership of the stream.
123 void ActivateReliableStream(std::unique_ptr<QuicStream> stream) {
124 ActivateStream(std::move(stream));
125 }
126
127 private:
128 // Stores written data from ReliableQuicStreamAdapter.
vasilvvc48c8712019-03-11 13:38:16 -0700129 std::string* write_buffer_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500130 // Whether data is written to write_buffer_.
131 bool writable_ = true;
132};
133
134// Packet writer that does nothing. This is required for QuicConnection but
135// isn't used for writing data.
136class DummyPacketWriter : public QuicPacketWriter {
137 public:
138 DummyPacketWriter() {}
139
140 // QuicPacketWriter overrides.
dschinazi17d42422019-06-18 16:35:07 -0700141 WriteResult WritePacket(const char* /*buffer*/,
142 size_t /*buf_len*/,
143 const QuicIpAddress& /*self_address*/,
144 const QuicSocketAddress& /*peer_address*/,
145 PerPacketOptions* /*options*/) override {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500146 return WriteResult(WRITE_STATUS_ERROR, 0);
147 }
148
149 bool IsWriteBlocked() const override { return false; }
150
151 void SetWritable() override {}
152
153 QuicByteCount GetMaxPacketSize(
dschinazi17d42422019-06-18 16:35:07 -0700154 const QuicSocketAddress& /*peer_address*/) const override {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500155 return 0;
156 }
157
158 bool SupportsReleaseTime() const override { return false; }
159
160 bool IsBatchMode() const override { return false; }
161
dschinazi17d42422019-06-18 16:35:07 -0700162 char* GetNextWriteLocation(
163 const QuicIpAddress& /*self_address*/,
164 const QuicSocketAddress& /*peer_address*/) override {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500165 return nullptr;
166 }
167
168 WriteResult Flush() override { return WriteResult(WRITE_STATUS_OK, 0); }
169};
170
171class MockQuartcStreamDelegate : public QuartcStream::Delegate {
172 public:
vasilvvc48c8712019-03-11 13:38:16 -0700173 MockQuartcStreamDelegate(QuicStreamId id, std::string* read_buffer)
QUICHE teama6ef0a62019-03-07 20:34:33 -0500174 : id_(id), read_buffer_(read_buffer) {}
175
176 void OnBufferChanged(QuartcStream* stream) override {
177 last_bytes_buffered_ = stream->BufferedDataBytes();
178 last_bytes_pending_retransmission_ = stream->BytesPendingRetransmission();
179 }
180
181 size_t OnReceived(QuartcStream* stream,
182 iovec* iov,
183 size_t iov_length,
dschinazi17d42422019-06-18 16:35:07 -0700184 bool /*fin*/) override {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500185 EXPECT_EQ(id_, stream->id());
186 EXPECT_EQ(stream->ReadOffset(), read_buffer_->size());
187 size_t bytes_consumed = 0;
188 for (size_t i = 0; i < iov_length; ++i) {
189 read_buffer_->append(static_cast<const char*>(iov[i].iov_base),
190 iov[i].iov_len);
191 bytes_consumed += iov[i].iov_len;
192 }
193 return bytes_consumed;
194 }
195
dschinazi17d42422019-06-18 16:35:07 -0700196 void OnClose(QuartcStream* /*stream*/) override { closed_ = true; }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500197
198 bool closed() { return closed_; }
199
200 QuicByteCount last_bytes_buffered() { return last_bytes_buffered_; }
201 QuicByteCount last_bytes_pending_retransmission() {
202 return last_bytes_pending_retransmission_;
203 }
204
205 protected:
206 QuicStreamId id_;
207 // Data read by the QuicStream.
vasilvvc48c8712019-03-11 13:38:16 -0700208 std::string* read_buffer_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500209 // Whether the QuicStream is closed.
210 bool closed_ = false;
211
212 // Last amount of data observed as buffered.
213 QuicByteCount last_bytes_buffered_ = 0;
214 QuicByteCount last_bytes_pending_retransmission_ = 0;
215};
216
bnc43b91292020-02-26 10:22:30 -0800217class QuartcStreamTest : public QuicTestWithParam<ParsedQuicVersion>,
218 public QuicConnectionHelperInterface {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500219 public:
bnc43b91292020-02-26 10:22:30 -0800220 QuartcStreamTest() : version_(GetParam()) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -0500221
222 ~QuartcStreamTest() override = default;
223
224 void CreateReliableQuicStream() {
225 // Arbitrary values for QuicConnection.
226 Perspective perspective = Perspective::IS_SERVER;
227 QuicIpAddress ip;
228 ip.FromString("0.0.0.0");
229 bool owns_writer = true;
230
vasilvv0fc587f2019-09-06 13:33:08 -0700231 alarm_factory_ = std::make_unique<test::MockAlarmFactory>();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500232
vasilvv0fc587f2019-09-06 13:33:08 -0700233 connection_ = std::make_unique<QuicConnection>(
bnc43b91292020-02-26 10:22:30 -0800234 QuicUtils::CreateZeroConnectionId(version_.transport_version),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500235 QuicSocketAddress(ip, 0), this /*QuicConnectionHelperInterface*/,
236 alarm_factory_.get(), new DummyPacketWriter(), owns_writer, perspective,
bnc43b91292020-02-26 10:22:30 -0800237 ParsedQuicVersionVector{version_});
QUICHE teama6ef0a62019-03-07 20:34:33 -0500238 clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
vasilvv0fc587f2019-09-06 13:33:08 -0700239 session_ = std::make_unique<MockQuicSession>(connection_.get(),
240 QuicConfig(), &write_buffer_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500241 mock_stream_delegate_ =
vasilvv0fc587f2019-09-06 13:33:08 -0700242 std::make_unique<MockQuartcStreamDelegate>(kStreamId, &read_buffer_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500243 stream_ = new QuartcStream(kStreamId, session_.get());
244 stream_->SetDelegate(mock_stream_delegate_.get());
245 session_->ActivateReliableStream(std::unique_ptr<QuartcStream>(stream_));
246 }
247
248 const QuicClock* GetClock() const override { return &clock_; }
249
250 QuicRandom* GetRandomGenerator() override {
251 return QuicRandom::GetInstance();
252 }
253
254 QuicBufferAllocator* GetStreamSendBufferAllocator() override {
255 return &buffer_allocator_;
256 }
257
258 protected:
bnc43b91292020-02-26 10:22:30 -0800259 const ParsedQuicVersion version_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500260 // The QuicSession will take the ownership.
261 QuartcStream* stream_;
262 std::unique_ptr<MockQuartcStreamDelegate> mock_stream_delegate_;
263 std::unique_ptr<MockQuicSession> session_;
264 // Data written by the ReliableQuicStreamAdapterTest.
vasilvvc48c8712019-03-11 13:38:16 -0700265 std::string write_buffer_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500266 // Data read by the ReliableQuicStreamAdapterTest.
vasilvvc48c8712019-03-11 13:38:16 -0700267 std::string read_buffer_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500268 std::unique_ptr<QuicAlarmFactory> alarm_factory_;
269 std::unique_ptr<QuicConnection> connection_;
270 // Used to implement the QuicConnectionHelperInterface.
271 SimpleBufferAllocator buffer_allocator_;
272 MockClock clock_;
273};
274
bnc36b7a032020-03-04 10:27:23 -0800275// TODO(b/150224094): Enable versions with TLS handshake.
276INSTANTIATE_TEST_SUITE_P(
277 Tests,
278 QuartcStreamTest,
279 ::testing::ValuesIn(CurrentSupportedVersionsWithQuicCrypto()),
280 ::testing::PrintToStringParamName());
bnc43b91292020-02-26 10:22:30 -0800281
QUICHE teama6ef0a62019-03-07 20:34:33 -0500282// Write an entire string.
bnc43b91292020-02-26 10:22:30 -0800283TEST_P(QuartcStreamTest, WriteDataWhole) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500284 CreateReliableQuicStream();
285 char message[] = "Foo bar";
286 test::QuicTestMemSliceVector data({std::make_pair(message, 7)});
287 stream_->WriteMemSlices(data.span(), /*fin=*/false);
288 EXPECT_EQ("Foo bar", write_buffer_);
289}
290
291// Write part of a string.
bnc43b91292020-02-26 10:22:30 -0800292TEST_P(QuartcStreamTest, WriteDataPartial) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500293 CreateReliableQuicStream();
294 char message[] = "Foo bar";
295 test::QuicTestMemSliceVector data({std::make_pair(message, 5)});
296 stream_->WriteMemSlices(data.span(), /*fin=*/false);
297 EXPECT_EQ("Foo b", write_buffer_);
298}
299
300// Test that a QuartcStream buffers writes correctly.
bnc43b91292020-02-26 10:22:30 -0800301TEST_P(QuartcStreamTest, StreamBuffersData) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500302 CreateReliableQuicStream();
303
304 char message[] = "Foo bar";
305 test::QuicTestMemSliceVector data({std::make_pair(message, 7)});
306
307 // The stream is not yet writable, so data will be buffered.
308 session_->set_writable(false);
309 stream_->WriteMemSlices(data.span(), /*fin=*/false);
310
311 // Check that data is buffered.
312 EXPECT_TRUE(stream_->HasBufferedData());
313 EXPECT_EQ(7u, stream_->BufferedDataBytes());
314
315 // Check that the stream told its delegate about the buffer change.
316 EXPECT_EQ(7u, mock_stream_delegate_->last_bytes_buffered());
317
318 // Check that none of the data was written yet.
319 // Note that |write_buffer_| actually holds data written by the QuicSession
320 // (not data buffered by the stream).
321 EXPECT_EQ(0ul, write_buffer_.size());
322
323 char message1[] = "xyzzy";
324 test::QuicTestMemSliceVector data1({std::make_pair(message1, 5)});
325
326 // More writes go into the buffer.
327 stream_->WriteMemSlices(data1.span(), /*fin=*/false);
328
329 EXPECT_TRUE(stream_->HasBufferedData());
330 EXPECT_EQ(12u, stream_->BufferedDataBytes());
331 EXPECT_EQ(12u, mock_stream_delegate_->last_bytes_buffered());
332 EXPECT_EQ(0ul, write_buffer_.size());
333
334 // The stream becomes writable, so it sends the buffered data.
335 session_->set_writable(true);
336 stream_->OnCanWrite();
337
338 EXPECT_FALSE(stream_->HasBufferedData());
339 EXPECT_EQ(0u, stream_->BufferedDataBytes());
340 EXPECT_EQ(0u, mock_stream_delegate_->last_bytes_buffered());
341 EXPECT_EQ("Foo barxyzzy", write_buffer_);
342}
343
344// Finish writing to a stream.
345// It delivers the fin bit and closes the write-side as soon as possible.
bnc43b91292020-02-26 10:22:30 -0800346TEST_P(QuartcStreamTest, FinishWriting) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500347 CreateReliableQuicStream();
348
349 session_->set_writable(false);
350 stream_->FinishWriting();
351 EXPECT_FALSE(stream_->fin_sent());
352
353 // Fin is sent as soon as the stream becomes writable.
354 session_->set_writable(true);
355 stream_->OnCanWrite();
356 EXPECT_TRUE(stream_->fin_sent());
357 EXPECT_TRUE(stream_->write_side_closed());
358}
359
360// Read an entire string.
bnc43b91292020-02-26 10:22:30 -0800361TEST_P(QuartcStreamTest, ReadDataWhole) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500362 CreateReliableQuicStream();
363 QuicStreamFrame frame(kStreamId, false, 0, "Hello, World!");
364 stream_->OnStreamFrame(frame);
365
366 EXPECT_EQ("Hello, World!", read_buffer_);
367}
368
369// Read part of a string.
bnc43b91292020-02-26 10:22:30 -0800370TEST_P(QuartcStreamTest, ReadDataPartial) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500371 CreateReliableQuicStream();
372 QuicStreamFrame frame(kStreamId, false, 0, "Hello, World!");
373 frame.data_length = 5;
374 stream_->OnStreamFrame(frame);
375
376 EXPECT_EQ("Hello", read_buffer_);
377}
378
379// Streams do not call OnReceived() after StopReading().
380// Note: this is tested here because Quartc relies on this behavior.
bnc43b91292020-02-26 10:22:30 -0800381TEST_P(QuartcStreamTest, StopReading) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500382 CreateReliableQuicStream();
383 stream_->StopReading();
384
385 QuicStreamFrame frame(kStreamId, false, 0, "Hello, World!");
386 stream_->OnStreamFrame(frame);
387
388 EXPECT_EQ(0ul, read_buffer_.size());
389
390 QuicStreamFrame frame2(kStreamId, true, 0, "Hello, World!");
391 stream_->OnStreamFrame(frame2);
392
393 EXPECT_EQ(0ul, read_buffer_.size());
394 EXPECT_TRUE(stream_->fin_received());
395}
396
397// Test that closing the stream results in a callback.
bnc43b91292020-02-26 10:22:30 -0800398TEST_P(QuartcStreamTest, CloseStream) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500399 CreateReliableQuicStream();
400 EXPECT_FALSE(mock_stream_delegate_->closed());
401 stream_->OnClose();
402 EXPECT_TRUE(mock_stream_delegate_->closed());
403}
404
405// Both sending and receiving fin automatically closes a stream.
bnc43b91292020-02-26 10:22:30 -0800406TEST_P(QuartcStreamTest, CloseOnFins) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500407 CreateReliableQuicStream();
408 QuicStreamFrame frame(kStreamId, true, 0, 0);
409 stream_->OnStreamFrame(frame);
410
411 test::QuicTestMemSliceVector data({});
412 stream_->WriteMemSlices(data.span(), /*fin=*/true);
413
414 // Check that the OnClose() callback occurred.
415 EXPECT_TRUE(mock_stream_delegate_->closed());
416}
417
bnc43b91292020-02-26 10:22:30 -0800418TEST_P(QuartcStreamTest, TestCancelOnLossDisabled) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500419 CreateReliableQuicStream();
420
421 // This should be the default state.
422 EXPECT_FALSE(stream_->cancel_on_loss());
423
424 char message[] = "Foo bar";
425 test::QuicTestMemSliceVector data({std::make_pair(message, 7)});
426 stream_->WriteMemSlices(data.span(), /*fin=*/false);
427
428 EXPECT_EQ("Foo bar", write_buffer_);
429
430 stream_->OnStreamFrameLost(0, 7, false);
431 stream_->OnCanWrite();
432
433 EXPECT_EQ("Foo barFoo bar", write_buffer_);
bnc13895832019-11-27 08:40:50 -0800434 EXPECT_THAT(stream_->stream_error(), IsQuicStreamNoError());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500435}
436
bnc43b91292020-02-26 10:22:30 -0800437TEST_P(QuartcStreamTest, TestCancelOnLossEnabled) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500438 CreateReliableQuicStream();
439 stream_->set_cancel_on_loss(true);
440
441 char message[] = "Foo bar";
442 test::QuicTestMemSliceVector data({std::make_pair(message, 7)});
443 stream_->WriteMemSlices(data.span(), /*fin=*/false);
444
445 EXPECT_EQ("Foo bar", write_buffer_);
446
447 stream_->OnStreamFrameLost(0, 7, false);
448 stream_->OnCanWrite();
449
450 EXPECT_EQ("Foo bar", write_buffer_);
bnc13895832019-11-27 08:40:50 -0800451 EXPECT_THAT(stream_->stream_error(), IsStreamError(QUIC_STREAM_CANCELLED));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500452}
453
bnc43b91292020-02-26 10:22:30 -0800454TEST_P(QuartcStreamTest, MaxRetransmissionsAbsent) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500455 CreateReliableQuicStream();
456
457 // This should be the default state.
458 EXPECT_EQ(stream_->max_retransmission_count(),
459 std::numeric_limits<int>::max());
460
461 char message[] = "Foo bar";
462 test::QuicTestMemSliceVector data({std::make_pair(message, 7)});
463 stream_->WriteMemSlices(data.span(), /*fin=*/false);
464
465 EXPECT_EQ("Foo bar", write_buffer_);
466
467 stream_->OnStreamFrameLost(0, 7, false);
468 stream_->OnCanWrite();
469
470 EXPECT_EQ("Foo barFoo bar", write_buffer_);
bnc13895832019-11-27 08:40:50 -0800471 EXPECT_THAT(stream_->stream_error(), IsQuicStreamNoError());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500472}
473
bnc43b91292020-02-26 10:22:30 -0800474TEST_P(QuartcStreamTest, MaxRetransmissionsSet) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500475 CreateReliableQuicStream();
476 stream_->set_max_retransmission_count(2);
477
478 char message[] = "Foo bar";
479 test::QuicTestMemSliceVector data({std::make_pair(message, 7)});
480 stream_->WriteMemSlices(data.span(), /*fin=*/false);
481
482 EXPECT_EQ("Foo bar", write_buffer_);
483
484 stream_->OnStreamFrameLost(0, 7, false);
485 stream_->OnCanWrite();
486
487 EXPECT_EQ("Foo barFoo bar", write_buffer_);
488
489 stream_->OnStreamFrameLost(0, 7, false);
490 stream_->OnCanWrite();
491
492 EXPECT_EQ("Foo barFoo barFoo bar", write_buffer_);
493
494 stream_->OnStreamFrameLost(0, 7, false);
495 stream_->OnCanWrite();
496
497 EXPECT_EQ("Foo barFoo barFoo bar", write_buffer_);
bnc13895832019-11-27 08:40:50 -0800498 EXPECT_THAT(stream_->stream_error(), IsStreamError(QUIC_STREAM_CANCELLED));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500499}
500
bnc43b91292020-02-26 10:22:30 -0800501TEST_P(QuartcStreamTest, MaxRetransmissionsDisjointFrames) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500502 CreateReliableQuicStream();
503 stream_->set_max_retransmission_count(2);
504
505 char message[] = "Foo bar";
506 test::QuicTestMemSliceVector data({std::make_pair(message, 7)});
507 stream_->WriteMemSlices(data.span(), /*fin=*/false);
508
509 EXPECT_EQ("Foo bar", write_buffer_);
510
511 // Retransmit bytes [0, 3].
512 stream_->OnStreamFrameLost(0, 4, false);
513 stream_->OnCanWrite();
514
515 EXPECT_EQ("Foo barFoo ", write_buffer_);
516
517 // Retransmit bytes [4, 6]. Everything has been retransmitted once.
518 stream_->OnStreamFrameLost(4, 3, false);
519 stream_->OnCanWrite();
520
521 EXPECT_EQ("Foo barFoo bar", write_buffer_);
522
523 // Retransmit bytes [0, 6]. Everything can be retransmitted a second time.
524 stream_->OnStreamFrameLost(0, 7, false);
525 stream_->OnCanWrite();
526
527 EXPECT_EQ("Foo barFoo barFoo bar", write_buffer_);
528}
529
bnc43b91292020-02-26 10:22:30 -0800530TEST_P(QuartcStreamTest, MaxRetransmissionsOverlappingFrames) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500531 CreateReliableQuicStream();
532 stream_->set_max_retransmission_count(2);
533
534 char message[] = "Foo bar";
535 test::QuicTestMemSliceVector data({std::make_pair(message, 7)});
536 stream_->WriteMemSlices(data.span(), /*fin=*/false);
537
538 EXPECT_EQ("Foo bar", write_buffer_);
539
540 // Retransmit bytes 0 to 3.
541 stream_->OnStreamFrameLost(0, 4, false);
542 stream_->OnCanWrite();
543
544 EXPECT_EQ("Foo barFoo ", write_buffer_);
545
546 // Retransmit bytes 3 to 6. Byte 3 has been retransmitted twice.
547 stream_->OnStreamFrameLost(3, 4, false);
548 stream_->OnCanWrite();
549
550 EXPECT_EQ("Foo barFoo bar", write_buffer_);
551
552 // Retransmit byte 3 a third time. This should cause cancellation.
553 stream_->OnStreamFrameLost(3, 1, false);
554 stream_->OnCanWrite();
555
556 EXPECT_EQ("Foo barFoo bar", write_buffer_);
bnc13895832019-11-27 08:40:50 -0800557 EXPECT_THAT(stream_->stream_error(), IsStreamError(QUIC_STREAM_CANCELLED));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500558}
559
bnc43b91292020-02-26 10:22:30 -0800560TEST_P(QuartcStreamTest, MaxRetransmissionsWithAckedFrame) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500561 CreateReliableQuicStream();
562 stream_->set_max_retransmission_count(1);
563
564 char message[] = "Foo bar";
565 test::QuicTestMemSliceVector data({std::make_pair(message, 7)});
566 stream_->WriteMemSlices(data.span(), /*fin=*/false);
567
568 EXPECT_EQ("Foo bar", write_buffer_);
569
570 // Retransmit bytes [0, 7).
571 stream_->OnStreamFrameLost(0, 7, false);
572 stream_->OnCanWrite();
573
574 EXPECT_EQ("Foo barFoo bar", write_buffer_);
575
576 // Ack bytes [0, 7). These bytes should be pruned from the data tracked by
577 // the stream.
578 QuicByteCount newly_acked_length = 0;
579 stream_->OnStreamFrameAcked(0, 7, false, QuicTime::Delta::FromMilliseconds(1),
QUICHE team2f5f30b2020-02-18 08:52:28 -0800580 QuicTime::Zero(), &newly_acked_length);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500581 EXPECT_EQ(7u, newly_acked_length);
582 stream_->OnCanWrite();
583
584 EXPECT_EQ("Foo barFoo bar", write_buffer_);
585
586 // Retransmit bytes [0, 7) again.
587 // QUIC will never mark frames as lost after they've been acked, but this lets
588 // us test that QuartcStream stopped tracking these bytes after the acked.
589 stream_->OnStreamFrameLost(0, 7, false);
590 stream_->OnCanWrite();
591
592 // QuartcStream should be cancelled, but it stopped tracking the lost bytes
593 // after they were acked, so it's not.
bnc13895832019-11-27 08:40:50 -0800594 EXPECT_THAT(stream_->stream_error(), IsQuicStreamNoError());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500595}
596
bnc43b91292020-02-26 10:22:30 -0800597TEST_P(QuartcStreamTest, TestBytesPendingRetransmission) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500598 CreateReliableQuicStream();
599 stream_->set_cancel_on_loss(false);
600
601 char message[] = "Foo bar";
602 test::QuicTestMemSliceVector data({std::make_pair(message, 7)});
603 stream_->WriteMemSlices(data.span(), /*fin=*/false);
604
605 EXPECT_EQ("Foo bar", write_buffer_);
606
607 stream_->OnStreamFrameLost(0, 4, false);
608 EXPECT_EQ(stream_->BytesPendingRetransmission(), 4u);
609 EXPECT_EQ(mock_stream_delegate_->last_bytes_pending_retransmission(), 4u);
610
611 stream_->OnStreamFrameLost(4, 3, false);
612 EXPECT_EQ(stream_->BytesPendingRetransmission(), 7u);
613 EXPECT_EQ(mock_stream_delegate_->last_bytes_pending_retransmission(), 7u);
614
615 stream_->OnCanWrite();
616 EXPECT_EQ(stream_->BytesPendingRetransmission(), 0u);
617 EXPECT_EQ(mock_stream_delegate_->last_bytes_pending_retransmission(), 0u);
618
619 EXPECT_EQ("Foo barFoo bar", write_buffer_);
bnc13895832019-11-27 08:40:50 -0800620 EXPECT_THAT(stream_->stream_error(), IsQuicStreamNoError());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500621}
622
bnc43b91292020-02-26 10:22:30 -0800623TEST_P(QuartcStreamTest, TestBytesPendingRetransmissionWithCancelOnLoss) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500624 CreateReliableQuicStream();
625 stream_->set_cancel_on_loss(true);
626
627 char message[] = "Foo bar";
628 test::QuicTestMemSliceVector data({std::make_pair(message, 7)});
629 stream_->WriteMemSlices(data.span(), /*fin=*/false);
630
631 EXPECT_EQ("Foo bar", write_buffer_);
632
633 stream_->OnStreamFrameLost(0, 4, false);
634 EXPECT_EQ(stream_->BytesPendingRetransmission(), 0u);
635 EXPECT_EQ(mock_stream_delegate_->last_bytes_pending_retransmission(), 0u);
636
637 stream_->OnStreamFrameLost(4, 3, false);
638 EXPECT_EQ(stream_->BytesPendingRetransmission(), 0u);
639 EXPECT_EQ(mock_stream_delegate_->last_bytes_pending_retransmission(), 0u);
640
641 stream_->OnCanWrite();
642 EXPECT_EQ(stream_->BytesPendingRetransmission(), 0u);
643 EXPECT_EQ(mock_stream_delegate_->last_bytes_pending_retransmission(), 0u);
644
645 EXPECT_EQ("Foo bar", write_buffer_);
bnc13895832019-11-27 08:40:50 -0800646 EXPECT_THAT(stream_->stream_error(), IsStreamError(QUIC_STREAM_CANCELLED));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500647}
648
649} // namespace
650
651} // namespace quic