blob: dc21a0974418eb2acde50d5463c6973156b86889 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright (c) 2015 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
QUICHE team5be974e2020-12-29 18:35:24 -05005#include "quic/core/quic_stream_sequencer_buffer.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -05006
7#include <algorithm>
8#include <cstddef>
9#include <cstdint>
10#include <map>
vasilvv872e7a32019-03-12 16:42:44 -070011#include <string>
QUICHE teama6ef0a62019-03-07 20:34:33 -050012#include <utility>
13
vasilvv9edb31e2020-12-03 19:32:58 -080014#include "absl/strings/str_cat.h"
vasilvvc872ee42020-10-07 19:50:22 -070015#include "absl/strings/string_view.h"
QUICHE team5be974e2020-12-29 18:35:24 -050016#include "quic/platform/api/quic_logging.h"
17#include "quic/platform/api/quic_test.h"
18#include "quic/test_tools/quic_stream_sequencer_buffer_peer.h"
19#include "quic/test_tools/quic_test_utils.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050020
21namespace quic {
22
23namespace test {
24
vasilvvc872ee42020-10-07 19:50:22 -070025absl::string_view IovecToStringPiece(iovec iov) {
26 return absl::string_view(reinterpret_cast<const char*>(iov.iov_base),
27 iov.iov_len);
bnccb3ef7d2019-06-24 10:46:13 -070028}
29
QUICHE teama6ef0a62019-03-07 20:34:33 -050030char GetCharFromIOVecs(size_t offset, iovec iov[], size_t count) {
31 size_t start_offset = 0;
32 for (size_t i = 0; i < count; i++) {
33 if (iov[i].iov_len == 0) {
34 continue;
35 }
36 size_t end_offset = start_offset + iov[i].iov_len - 1;
37 if (offset >= start_offset && offset <= end_offset) {
38 const char* buf = reinterpret_cast<const char*>(iov[i].iov_base);
39 return buf[offset - start_offset];
40 }
41 start_offset += iov[i].iov_len;
42 }
dschinazi4620e9a2019-04-26 16:07:11 -070043 QUIC_LOG(ERROR) << "Could not locate char at offset " << offset << " in "
44 << count << " iovecs";
QUICHE teama6ef0a62019-03-07 20:34:33 -050045 for (size_t i = 0; i < count; ++i) {
dschinazi4620e9a2019-04-26 16:07:11 -070046 QUIC_LOG(ERROR) << " iov[" << i << "].iov_len = " << iov[i].iov_len;
QUICHE teama6ef0a62019-03-07 20:34:33 -050047 }
48 return '\0';
49}
50
51const size_t kMaxNumGapsAllowed = 2 * kMaxPacketGap;
52
53static const size_t kBlockSizeBytes =
54 QuicStreamSequencerBuffer::kBlockSizeBytes;
renjietang58b3af32020-11-11 15:48:58 -080055using BufferBlock = QuicStreamSequencerBuffer::BufferBlock;
QUICHE teama6ef0a62019-03-07 20:34:33 -050056
57namespace {
58
59class QuicStreamSequencerBufferTest : public QuicTest {
60 public:
61 void SetUp() override { Initialize(); }
62
63 void ResetMaxCapacityBytes(size_t max_capacity_bytes) {
64 max_capacity_bytes_ = max_capacity_bytes;
65 Initialize();
66 }
67
68 protected:
69 void Initialize() {
vasilvv0fc587f2019-09-06 13:33:08 -070070 buffer_ =
71 std::make_unique<QuicStreamSequencerBuffer>((max_capacity_bytes_));
72 helper_ = std::make_unique<QuicStreamSequencerBufferPeer>((buffer_.get()));
QUICHE teama6ef0a62019-03-07 20:34:33 -050073 }
74
haoyuewang21843db2020-11-09 20:45:38 -080075 // Use 8.5 here to make sure that the buffer has more than
76 // QuicStreamSequencerBuffer::kInitialBlockCount block and its end doesn't
77 // align with the end of a block in order to test all the offset calculation.
78 size_t max_capacity_bytes_ = 8.5 * kBlockSizeBytes;
QUICHE teama6ef0a62019-03-07 20:34:33 -050079
80 std::unique_ptr<QuicStreamSequencerBuffer> buffer_;
81 std::unique_ptr<QuicStreamSequencerBufferPeer> helper_;
bncce609f72019-06-24 10:23:58 -070082 size_t written_ = 0;
vasilvvc48c8712019-03-11 13:38:16 -070083 std::string error_details_;
QUICHE teama6ef0a62019-03-07 20:34:33 -050084};
85
86TEST_F(QuicStreamSequencerBufferTest, InitializeWithMaxRecvWindowSize) {
87 ResetMaxCapacityBytes(16 * 1024 * 1024); // 16MB
88 EXPECT_EQ(2 * 1024u, // 16MB / 8KB = 2K
haoyuewang21843db2020-11-09 20:45:38 -080089 helper_->max_blocks_count());
QUICHE teama6ef0a62019-03-07 20:34:33 -050090 EXPECT_EQ(max_capacity_bytes_, helper_->max_buffer_capacity());
91 EXPECT_TRUE(helper_->CheckInitialState());
92}
93
94TEST_F(QuicStreamSequencerBufferTest, InitializationWithDifferentSizes) {
haoyuewang21843db2020-11-09 20:45:38 -080095 const size_t kCapacity = 16 * QuicStreamSequencerBuffer::kBlockSizeBytes;
QUICHE teama6ef0a62019-03-07 20:34:33 -050096 ResetMaxCapacityBytes(kCapacity);
97 EXPECT_EQ(max_capacity_bytes_, helper_->max_buffer_capacity());
98 EXPECT_TRUE(helper_->CheckInitialState());
99
haoyuewang21843db2020-11-09 20:45:38 -0800100 const size_t kCapacity1 = 32 * QuicStreamSequencerBuffer::kBlockSizeBytes;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500101 ResetMaxCapacityBytes(kCapacity1);
102 EXPECT_EQ(kCapacity1, helper_->max_buffer_capacity());
103 EXPECT_TRUE(helper_->CheckInitialState());
104}
105
106TEST_F(QuicStreamSequencerBufferTest, ClearOnEmpty) {
107 buffer_->Clear();
108 EXPECT_TRUE(helper_->CheckBufferInvariants());
109}
110
111TEST_F(QuicStreamSequencerBufferTest, OnStreamData0length) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500112 QuicErrorCode error =
bncce609f72019-06-24 10:23:58 -0700113 buffer_->OnStreamData(800, "", &written_, &error_details_);
bncf54082a2019-11-27 10:19:47 -0800114 EXPECT_THAT(error, IsError(QUIC_EMPTY_STREAM_FRAME_NO_FIN));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500115 EXPECT_TRUE(helper_->CheckBufferInvariants());
116}
117
118TEST_F(QuicStreamSequencerBufferTest, OnStreamDataWithinBlock) {
119 EXPECT_FALSE(helper_->IsBufferAllocated());
vasilvvc48c8712019-03-11 13:38:16 -0700120 std::string source(1024, 'a');
bncf54082a2019-11-27 10:19:47 -0800121 EXPECT_THAT(buffer_->OnStreamData(800, source, &written_, &error_details_),
122 IsQuicNoError());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500123 BufferBlock* block_ptr = helper_->GetBlock(0);
124 for (size_t i = 0; i < source.size(); ++i) {
125 ASSERT_EQ('a', block_ptr->buffer[helper_->GetInBlockOffset(800) + i]);
126 }
127 EXPECT_EQ(2, helper_->IntervalSize());
128 EXPECT_EQ(0u, helper_->ReadableBytes());
129 EXPECT_EQ(1u, helper_->bytes_received().Size());
130 EXPECT_EQ(800u, helper_->bytes_received().begin()->min());
131 EXPECT_EQ(1824u, helper_->bytes_received().begin()->max());
132 EXPECT_TRUE(helper_->CheckBufferInvariants());
133 EXPECT_TRUE(helper_->IsBufferAllocated());
134}
135
136TEST_F(QuicStreamSequencerBufferTest, Move) {
137 EXPECT_FALSE(helper_->IsBufferAllocated());
vasilvvc48c8712019-03-11 13:38:16 -0700138 std::string source(1024, 'a');
bncf54082a2019-11-27 10:19:47 -0800139 EXPECT_THAT(buffer_->OnStreamData(800, source, &written_, &error_details_),
140 IsQuicNoError());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500141 BufferBlock* block_ptr = helper_->GetBlock(0);
142 for (size_t i = 0; i < source.size(); ++i) {
143 ASSERT_EQ('a', block_ptr->buffer[helper_->GetInBlockOffset(800) + i]);
144 }
145
146 QuicStreamSequencerBuffer buffer2(std::move(*buffer_));
147 QuicStreamSequencerBufferPeer helper2(&buffer2);
148
149 EXPECT_FALSE(helper_->IsBufferAllocated());
150
151 EXPECT_EQ(2, helper2.IntervalSize());
152 EXPECT_EQ(0u, helper2.ReadableBytes());
153 EXPECT_EQ(1u, helper2.bytes_received().Size());
154 EXPECT_EQ(800u, helper2.bytes_received().begin()->min());
155 EXPECT_EQ(1824u, helper2.bytes_received().begin()->max());
156 EXPECT_TRUE(helper2.CheckBufferInvariants());
157 EXPECT_TRUE(helper2.IsBufferAllocated());
158}
159
160TEST_F(QuicStreamSequencerBufferTest, OnStreamDataInvalidSource) {
161 // Pass in an invalid source, expects to return error.
vasilvvc872ee42020-10-07 19:50:22 -0700162 absl::string_view source;
163 source = absl::string_view(nullptr, 1024);
bncf54082a2019-11-27 10:19:47 -0800164 EXPECT_THAT(buffer_->OnStreamData(800, source, &written_, &error_details_),
165 IsError(QUIC_STREAM_SEQUENCER_INVALID_STATE));
vasilvv9edb31e2020-12-03 19:32:58 -0800166 EXPECT_EQ(0u, error_details_.find(absl::StrCat(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500167 "QuicStreamSequencerBuffer error: OnStreamData() "
168 "dest == nullptr: ",
169 false, " source == nullptr: ", true)));
170}
171
172TEST_F(QuicStreamSequencerBufferTest, OnStreamDataWithOverlap) {
vasilvvc48c8712019-03-11 13:38:16 -0700173 std::string source(1024, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500174 // Write something into [800, 1824)
bncf54082a2019-11-27 10:19:47 -0800175 EXPECT_THAT(buffer_->OnStreamData(800, source, &written_, &error_details_),
176 IsQuicNoError());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500177 // Try to write to [0, 1024) and [1024, 2048).
bncf54082a2019-11-27 10:19:47 -0800178 EXPECT_THAT(buffer_->OnStreamData(0, source, &written_, &error_details_),
179 IsQuicNoError());
180 EXPECT_THAT(buffer_->OnStreamData(1024, source, &written_, &error_details_),
181 IsQuicNoError());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500182}
183
184TEST_F(QuicStreamSequencerBufferTest,
185 OnStreamDataOverlapAndDuplicateCornerCases) {
vasilvvc48c8712019-03-11 13:38:16 -0700186 std::string source(1024, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500187 // Write something into [800, 1824)
bncce609f72019-06-24 10:23:58 -0700188 buffer_->OnStreamData(800, source, &written_, &error_details_);
vasilvvc48c8712019-03-11 13:38:16 -0700189 source = std::string(800, 'b');
190 std::string one_byte = "c";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500191 // Write [1, 801).
bncf54082a2019-11-27 10:19:47 -0800192 EXPECT_THAT(buffer_->OnStreamData(1, source, &written_, &error_details_),
193 IsQuicNoError());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500194 // Write [0, 800).
bncf54082a2019-11-27 10:19:47 -0800195 EXPECT_THAT(buffer_->OnStreamData(0, source, &written_, &error_details_),
196 IsQuicNoError());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500197 // Write [1823, 1824).
bncf54082a2019-11-27 10:19:47 -0800198 EXPECT_THAT(buffer_->OnStreamData(1823, one_byte, &written_, &error_details_),
199 IsQuicNoError());
bncce609f72019-06-24 10:23:58 -0700200 EXPECT_EQ(0u, written_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500201 // write one byte to [1824, 1825)
bncf54082a2019-11-27 10:19:47 -0800202 EXPECT_THAT(buffer_->OnStreamData(1824, one_byte, &written_, &error_details_),
203 IsQuicNoError());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500204 EXPECT_TRUE(helper_->CheckBufferInvariants());
205}
206
207TEST_F(QuicStreamSequencerBufferTest, OnStreamDataWithoutOverlap) {
vasilvvc48c8712019-03-11 13:38:16 -0700208 std::string source(1024, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500209 // Write something into [800, 1824).
bncf54082a2019-11-27 10:19:47 -0800210 EXPECT_THAT(buffer_->OnStreamData(800, source, &written_, &error_details_),
211 IsQuicNoError());
vasilvvc48c8712019-03-11 13:38:16 -0700212 source = std::string(100, 'b');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500213 // Write something into [kBlockSizeBytes * 2 - 20, kBlockSizeBytes * 2 + 80).
bncf54082a2019-11-27 10:19:47 -0800214 EXPECT_THAT(buffer_->OnStreamData(kBlockSizeBytes * 2 - 20, source, &written_,
215 &error_details_),
216 IsQuicNoError());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500217 EXPECT_EQ(3, helper_->IntervalSize());
218 EXPECT_EQ(1024u + 100u, buffer_->BytesBuffered());
219 EXPECT_TRUE(helper_->CheckBufferInvariants());
220}
221
222TEST_F(QuicStreamSequencerBufferTest, OnStreamDataInLongStreamWithOverlap) {
223 // Assume a stream has already buffered almost 4GB.
224 uint64_t total_bytes_read = pow(2, 32) - 1;
225 helper_->set_total_bytes_read(total_bytes_read);
226 helper_->AddBytesReceived(0, total_bytes_read);
227
228 // Three new out of order frames arrive.
229 const size_t kBytesToWrite = 100;
vasilvvc48c8712019-03-11 13:38:16 -0700230 std::string source(kBytesToWrite, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500231 // Frame [2^32 + 500, 2^32 + 600).
232 QuicStreamOffset offset = pow(2, 32) + 500;
bncf54082a2019-11-27 10:19:47 -0800233 EXPECT_THAT(buffer_->OnStreamData(offset, source, &written_, &error_details_),
234 IsQuicNoError());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500235 EXPECT_EQ(2, helper_->IntervalSize());
236
237 // Frame [2^32 + 700, 2^32 + 800).
238 offset = pow(2, 32) + 700;
bncf54082a2019-11-27 10:19:47 -0800239 EXPECT_THAT(buffer_->OnStreamData(offset, source, &written_, &error_details_),
240 IsQuicNoError());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500241 EXPECT_EQ(3, helper_->IntervalSize());
242
243 // Another frame [2^32 + 300, 2^32 + 400).
244 offset = pow(2, 32) + 300;
bncf54082a2019-11-27 10:19:47 -0800245 EXPECT_THAT(buffer_->OnStreamData(offset, source, &written_, &error_details_),
246 IsQuicNoError());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500247 EXPECT_EQ(4, helper_->IntervalSize());
248}
249
250TEST_F(QuicStreamSequencerBufferTest, OnStreamDataTillEnd) {
251 // Write 50 bytes to the end.
252 const size_t kBytesToWrite = 50;
vasilvvc48c8712019-03-11 13:38:16 -0700253 std::string source(kBytesToWrite, 'a');
bncf54082a2019-11-27 10:19:47 -0800254 EXPECT_THAT(buffer_->OnStreamData(max_capacity_bytes_ - kBytesToWrite, source,
255 &written_, &error_details_),
256 IsQuicNoError());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500257 EXPECT_EQ(50u, buffer_->BytesBuffered());
258 EXPECT_TRUE(helper_->CheckBufferInvariants());
259}
260
261TEST_F(QuicStreamSequencerBufferTest, OnStreamDataTillEndCorner) {
262 // Write 1 byte to the end.
263 const size_t kBytesToWrite = 1;
vasilvvc48c8712019-03-11 13:38:16 -0700264 std::string source(kBytesToWrite, 'a');
bncf54082a2019-11-27 10:19:47 -0800265 EXPECT_THAT(buffer_->OnStreamData(max_capacity_bytes_ - kBytesToWrite, source,
266 &written_, &error_details_),
267 IsQuicNoError());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500268 EXPECT_EQ(1u, buffer_->BytesBuffered());
269 EXPECT_TRUE(helper_->CheckBufferInvariants());
270}
271
272TEST_F(QuicStreamSequencerBufferTest, OnStreamDataBeyondCapacity) {
vasilvvc48c8712019-03-11 13:38:16 -0700273 std::string source(60, 'a');
bncf54082a2019-11-27 10:19:47 -0800274 EXPECT_THAT(buffer_->OnStreamData(max_capacity_bytes_ - 50, source, &written_,
275 &error_details_),
276 IsError(QUIC_INTERNAL_ERROR));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500277 EXPECT_TRUE(helper_->CheckBufferInvariants());
278
279 source = "b";
bncf54082a2019-11-27 10:19:47 -0800280 EXPECT_THAT(buffer_->OnStreamData(max_capacity_bytes_, source, &written_,
281 &error_details_),
282 IsError(QUIC_INTERNAL_ERROR));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500283 EXPECT_TRUE(helper_->CheckBufferInvariants());
284
bncf54082a2019-11-27 10:19:47 -0800285 EXPECT_THAT(buffer_->OnStreamData(max_capacity_bytes_ * 1000, source,
286 &written_, &error_details_),
287 IsError(QUIC_INTERNAL_ERROR));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500288 EXPECT_TRUE(helper_->CheckBufferInvariants());
289
290 // Disallow current_gap != gaps_.end()
bncf54082a2019-11-27 10:19:47 -0800291 EXPECT_THAT(buffer_->OnStreamData(static_cast<QuicStreamOffset>(-1), source,
292 &written_, &error_details_),
293 IsError(QUIC_INTERNAL_ERROR));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500294 EXPECT_TRUE(helper_->CheckBufferInvariants());
295
296 // Disallow offset + size overflow
297 source = "bbb";
bncf54082a2019-11-27 10:19:47 -0800298 EXPECT_THAT(buffer_->OnStreamData(static_cast<QuicStreamOffset>(-2), source,
299 &written_, &error_details_),
300 IsError(QUIC_INTERNAL_ERROR));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500301 EXPECT_TRUE(helper_->CheckBufferInvariants());
302 EXPECT_EQ(0u, buffer_->BytesBuffered());
303}
304
305TEST_F(QuicStreamSequencerBufferTest, Readv100Bytes) {
vasilvvc48c8712019-03-11 13:38:16 -0700306 std::string source(1024, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500307 // Write something into [kBlockSizeBytes, kBlockSizeBytes + 1024).
bncce609f72019-06-24 10:23:58 -0700308 buffer_->OnStreamData(kBlockSizeBytes, source, &written_, &error_details_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500309 EXPECT_FALSE(buffer_->HasBytesToRead());
vasilvvc48c8712019-03-11 13:38:16 -0700310 source = std::string(100, 'b');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500311 // Write something into [0, 100).
bncce609f72019-06-24 10:23:58 -0700312 buffer_->OnStreamData(0, source, &written_, &error_details_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500313 EXPECT_TRUE(buffer_->HasBytesToRead());
314 // Read into a iovec array with total capacity of 120 bytes.
315 char dest[120];
316 iovec iovecs[3]{iovec{dest, 40}, iovec{dest + 40, 40}, iovec{dest + 80, 40}};
317 size_t read;
bncf54082a2019-11-27 10:19:47 -0800318 EXPECT_THAT(buffer_->Readv(iovecs, 3, &read, &error_details_),
319 IsQuicNoError());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500320 QUIC_LOG(ERROR) << error_details_;
321 EXPECT_EQ(100u, read);
322 EXPECT_EQ(100u, buffer_->BytesConsumed());
vasilvvc872ee42020-10-07 19:50:22 -0700323 EXPECT_EQ(source, absl::string_view(dest, read));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500324 // The first block should be released as its data has been read out.
325 EXPECT_EQ(nullptr, helper_->GetBlock(0));
326 EXPECT_TRUE(helper_->CheckBufferInvariants());
327}
328
329TEST_F(QuicStreamSequencerBufferTest, ReadvAcrossBlocks) {
vasilvvc48c8712019-03-11 13:38:16 -0700330 std::string source(kBlockSizeBytes + 50, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500331 // Write 1st block to full and extand 50 bytes to next block.
bncce609f72019-06-24 10:23:58 -0700332 buffer_->OnStreamData(0, source, &written_, &error_details_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500333 EXPECT_EQ(source.size(), helper_->ReadableBytes());
334 // Iteratively read 512 bytes from buffer_-> Overwrite dest[] each time.
335 char dest[512];
336 while (helper_->ReadableBytes()) {
337 std::fill(dest, dest + 512, 0);
338 iovec iovecs[2]{iovec{dest, 256}, iovec{dest + 256, 256}};
339 size_t read;
bncf54082a2019-11-27 10:19:47 -0800340 EXPECT_THAT(buffer_->Readv(iovecs, 2, &read, &error_details_),
341 IsQuicNoError());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500342 }
343 // The last read only reads the rest 50 bytes in 2nd block.
vasilvvc48c8712019-03-11 13:38:16 -0700344 EXPECT_EQ(std::string(50, 'a'), std::string(dest, 50));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500345 EXPECT_EQ(0, dest[50]) << "Dest[50] shouln't be filled.";
346 EXPECT_EQ(source.size(), buffer_->BytesConsumed());
347 EXPECT_TRUE(buffer_->Empty());
348 EXPECT_TRUE(helper_->CheckBufferInvariants());
349}
350
351TEST_F(QuicStreamSequencerBufferTest, ClearAfterRead) {
vasilvvc48c8712019-03-11 13:38:16 -0700352 std::string source(kBlockSizeBytes + 50, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500353 // Write 1st block to full with 'a'.
bncce609f72019-06-24 10:23:58 -0700354 buffer_->OnStreamData(0, source, &written_, &error_details_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500355 // Read first 512 bytes from buffer to make space at the beginning.
356 char dest[512]{0};
357 const iovec iov{dest, 512};
358 size_t read;
bncf54082a2019-11-27 10:19:47 -0800359 EXPECT_THAT(buffer_->Readv(&iov, 1, &read, &error_details_), IsQuicNoError());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500360 // Clear() should make buffer empty while preserving BytesConsumed()
361 buffer_->Clear();
362 EXPECT_TRUE(buffer_->Empty());
363 EXPECT_TRUE(helper_->CheckBufferInvariants());
364}
365
366TEST_F(QuicStreamSequencerBufferTest,
367 OnStreamDataAcrossLastBlockAndFillCapacity) {
vasilvvc48c8712019-03-11 13:38:16 -0700368 std::string source(kBlockSizeBytes + 50, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500369 // Write 1st block to full with 'a'.
bncce609f72019-06-24 10:23:58 -0700370 buffer_->OnStreamData(0, source, &written_, &error_details_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500371 // Read first 512 bytes from buffer to make space at the beginning.
372 char dest[512]{0};
373 const iovec iov{dest, 512};
374 size_t read;
bncf54082a2019-11-27 10:19:47 -0800375 EXPECT_THAT(buffer_->Readv(&iov, 1, &read, &error_details_), IsQuicNoError());
bncce609f72019-06-24 10:23:58 -0700376 EXPECT_EQ(source.size(), written_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500377
378 // Write more than half block size of bytes in the last block with 'b', which
379 // will wrap to the beginning and reaches the full capacity.
vasilvvc48c8712019-03-11 13:38:16 -0700380 source = std::string(0.5 * kBlockSizeBytes + 512, 'b');
bncf54082a2019-11-27 10:19:47 -0800381 EXPECT_THAT(buffer_->OnStreamData(2 * kBlockSizeBytes, source, &written_,
382 &error_details_),
383 IsQuicNoError());
bncce609f72019-06-24 10:23:58 -0700384 EXPECT_EQ(source.size(), written_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500385 EXPECT_TRUE(helper_->CheckBufferInvariants());
386}
387
388TEST_F(QuicStreamSequencerBufferTest,
389 OnStreamDataAcrossLastBlockAndExceedCapacity) {
vasilvvc48c8712019-03-11 13:38:16 -0700390 std::string source(kBlockSizeBytes + 50, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500391 // Write 1st block to full.
bncce609f72019-06-24 10:23:58 -0700392 buffer_->OnStreamData(0, source, &written_, &error_details_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500393 // Read first 512 bytes from buffer to make space at the beginning.
394 char dest[512]{0};
395 const iovec iov{dest, 512};
396 size_t read;
bncf54082a2019-11-27 10:19:47 -0800397 EXPECT_THAT(buffer_->Readv(&iov, 1, &read, &error_details_), IsQuicNoError());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500398
399 // Try to write from [max_capacity_bytes_ - 0.5 * kBlockSizeBytes,
400 // max_capacity_bytes_ + 512 + 1). But last bytes exceeds current capacity.
vasilvvc48c8712019-03-11 13:38:16 -0700401 source = std::string(0.5 * kBlockSizeBytes + 512 + 1, 'b');
haoyuewang21843db2020-11-09 20:45:38 -0800402 EXPECT_THAT(buffer_->OnStreamData(8 * kBlockSizeBytes, source, &written_,
bncf54082a2019-11-27 10:19:47 -0800403 &error_details_),
404 IsError(QUIC_INTERNAL_ERROR));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500405 EXPECT_TRUE(helper_->CheckBufferInvariants());
406}
407
408TEST_F(QuicStreamSequencerBufferTest, ReadvAcrossLastBlock) {
409 // Write to full capacity and read out 512 bytes at beginning and continue
410 // appending 256 bytes.
vasilvvc48c8712019-03-11 13:38:16 -0700411 std::string source(max_capacity_bytes_, 'a');
bncce609f72019-06-24 10:23:58 -0700412 buffer_->OnStreamData(0, source, &written_, &error_details_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500413 char dest[512]{0};
414 const iovec iov{dest, 512};
415 size_t read;
bncf54082a2019-11-27 10:19:47 -0800416 EXPECT_THAT(buffer_->Readv(&iov, 1, &read, &error_details_), IsQuicNoError());
vasilvvc48c8712019-03-11 13:38:16 -0700417 source = std::string(256, 'b');
bncce609f72019-06-24 10:23:58 -0700418 buffer_->OnStreamData(max_capacity_bytes_, source, &written_,
419 &error_details_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500420 EXPECT_TRUE(helper_->CheckBufferInvariants());
421
422 // Read all data out.
423 std::unique_ptr<char[]> dest1{new char[max_capacity_bytes_]};
424 dest1[0] = 0;
425 const iovec iov1{dest1.get(), max_capacity_bytes_};
bncf54082a2019-11-27 10:19:47 -0800426 EXPECT_THAT(buffer_->Readv(&iov1, 1, &read, &error_details_),
427 IsQuicNoError());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500428 EXPECT_EQ(max_capacity_bytes_ - 512 + 256, read);
429 EXPECT_EQ(max_capacity_bytes_ + 256, buffer_->BytesConsumed());
430 EXPECT_TRUE(buffer_->Empty());
431 EXPECT_TRUE(helper_->CheckBufferInvariants());
432}
433
434TEST_F(QuicStreamSequencerBufferTest, ReadvEmpty) {
435 char dest[512]{0};
436 iovec iov{dest, 512};
437 size_t read;
bncf54082a2019-11-27 10:19:47 -0800438 EXPECT_THAT(buffer_->Readv(&iov, 1, &read, &error_details_), IsQuicNoError());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500439 EXPECT_EQ(0u, read);
440 EXPECT_TRUE(helper_->CheckBufferInvariants());
441}
442
443TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionsEmpty) {
444 iovec iovs[2];
445 int iov_count = buffer_->GetReadableRegions(iovs, 2);
446 EXPECT_EQ(0, iov_count);
447 EXPECT_EQ(nullptr, iovs[iov_count].iov_base);
448 EXPECT_EQ(0u, iovs[iov_count].iov_len);
449}
450
451TEST_F(QuicStreamSequencerBufferTest, ReleaseWholeBuffer) {
452 // Tests that buffer is not deallocated unless ReleaseWholeBuffer() is called.
vasilvvc48c8712019-03-11 13:38:16 -0700453 std::string source(100, 'b');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500454 // Write something into [0, 100).
bncce609f72019-06-24 10:23:58 -0700455 buffer_->OnStreamData(0, source, &written_, &error_details_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500456 EXPECT_TRUE(buffer_->HasBytesToRead());
457 char dest[120];
458 iovec iovecs[3]{iovec{dest, 40}, iovec{dest + 40, 40}, iovec{dest + 80, 40}};
459 size_t read;
bncf54082a2019-11-27 10:19:47 -0800460 EXPECT_THAT(buffer_->Readv(iovecs, 3, &read, &error_details_),
461 IsQuicNoError());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500462 EXPECT_EQ(100u, read);
463 EXPECT_EQ(100u, buffer_->BytesConsumed());
464 EXPECT_TRUE(helper_->CheckBufferInvariants());
465 EXPECT_TRUE(helper_->IsBufferAllocated());
466 buffer_->ReleaseWholeBuffer();
467 EXPECT_FALSE(helper_->IsBufferAllocated());
468}
469
470TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionsBlockedByGap) {
471 // Write into [1, 1024).
vasilvvc48c8712019-03-11 13:38:16 -0700472 std::string source(1023, 'a');
bncce609f72019-06-24 10:23:58 -0700473 buffer_->OnStreamData(1, source, &written_, &error_details_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500474 // Try to get readable regions, but none is there.
475 iovec iovs[2];
476 int iov_count = buffer_->GetReadableRegions(iovs, 2);
477 EXPECT_EQ(0, iov_count);
478}
479
480TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionsTillEndOfBlock) {
481 // Write first block to full with [0, 256) 'a' and the rest 'b' then read out
482 // [0, 256)
vasilvvc48c8712019-03-11 13:38:16 -0700483 std::string source(kBlockSizeBytes, 'a');
bncce609f72019-06-24 10:23:58 -0700484 buffer_->OnStreamData(0, source, &written_, &error_details_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500485 char dest[256];
486 helper_->Read(dest, 256);
487 // Get readable region from [256, 1024)
488 iovec iovs[2];
489 int iov_count = buffer_->GetReadableRegions(iovs, 2);
490 EXPECT_EQ(1, iov_count);
vasilvvc48c8712019-03-11 13:38:16 -0700491 EXPECT_EQ(std::string(kBlockSizeBytes - 256, 'a'),
bnccb3ef7d2019-06-24 10:46:13 -0700492 IovecToStringPiece(iovs[0]));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500493}
494
495TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionsWithinOneBlock) {
496 // Write into [0, 1024) and then read out [0, 256)
vasilvvc48c8712019-03-11 13:38:16 -0700497 std::string source(1024, 'a');
bncce609f72019-06-24 10:23:58 -0700498 buffer_->OnStreamData(0, source, &written_, &error_details_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500499 char dest[256];
500 helper_->Read(dest, 256);
501 // Get readable region from [256, 1024)
502 iovec iovs[2];
503 int iov_count = buffer_->GetReadableRegions(iovs, 2);
504 EXPECT_EQ(1, iov_count);
bnccb3ef7d2019-06-24 10:46:13 -0700505 EXPECT_EQ(std::string(1024 - 256, 'a'), IovecToStringPiece(iovs[0]));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500506}
507
508TEST_F(QuicStreamSequencerBufferTest,
509 GetReadableRegionsAcrossBlockWithLongIOV) {
510 // Write into [0, 2 * kBlockSizeBytes + 1024) and then read out [0, 1024)
vasilvvc48c8712019-03-11 13:38:16 -0700511 std::string source(2 * kBlockSizeBytes + 1024, 'a');
bncce609f72019-06-24 10:23:58 -0700512 buffer_->OnStreamData(0, source, &written_, &error_details_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500513 char dest[1024];
514 helper_->Read(dest, 1024);
515
516 iovec iovs[4];
517 int iov_count = buffer_->GetReadableRegions(iovs, 4);
518 EXPECT_EQ(3, iov_count);
519 EXPECT_EQ(kBlockSizeBytes - 1024, iovs[0].iov_len);
520 EXPECT_EQ(kBlockSizeBytes, iovs[1].iov_len);
521 EXPECT_EQ(1024u, iovs[2].iov_len);
522}
523
524TEST_F(QuicStreamSequencerBufferTest,
525 GetReadableRegionsWithMultipleIOVsAcrossEnd) {
haoyuewang21843db2020-11-09 20:45:38 -0800526 // Write into [0, 8.5 * kBlockSizeBytes - 1024) and then read out [0, 1024)
QUICHE teama6ef0a62019-03-07 20:34:33 -0500527 // and then append 1024 + 512 bytes.
haoyuewang21843db2020-11-09 20:45:38 -0800528 std::string source(8.5 * kBlockSizeBytes - 1024, 'a');
bncce609f72019-06-24 10:23:58 -0700529 buffer_->OnStreamData(0, source, &written_, &error_details_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500530 char dest[1024];
531 helper_->Read(dest, 1024);
532 // Write across the end.
vasilvvc48c8712019-03-11 13:38:16 -0700533 source = std::string(1024 + 512, 'b');
haoyuewang21843db2020-11-09 20:45:38 -0800534 buffer_->OnStreamData(8.5 * kBlockSizeBytes - 1024, source, &written_,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500535 &error_details_);
536 // Use short iovec's.
537 iovec iovs[2];
538 int iov_count = buffer_->GetReadableRegions(iovs, 2);
539 EXPECT_EQ(2, iov_count);
540 EXPECT_EQ(kBlockSizeBytes - 1024, iovs[0].iov_len);
541 EXPECT_EQ(kBlockSizeBytes, iovs[1].iov_len);
542 // Use long iovec's and wrap the end of buffer.
haoyuewang21843db2020-11-09 20:45:38 -0800543 iovec iovs1[11];
544 EXPECT_EQ(10, buffer_->GetReadableRegions(iovs1, 11));
545 EXPECT_EQ(0.5 * kBlockSizeBytes, iovs1[8].iov_len);
546 EXPECT_EQ(512u, iovs1[9].iov_len);
547 EXPECT_EQ(std::string(512, 'b'), IovecToStringPiece(iovs1[9]));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500548}
549
550TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionEmpty) {
551 iovec iov;
552 EXPECT_FALSE(buffer_->GetReadableRegion(&iov));
553 EXPECT_EQ(nullptr, iov.iov_base);
554 EXPECT_EQ(0u, iov.iov_len);
555}
556
557TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionBeforeGap) {
558 // Write into [1, 1024).
vasilvvc48c8712019-03-11 13:38:16 -0700559 std::string source(1023, 'a');
bncce609f72019-06-24 10:23:58 -0700560 buffer_->OnStreamData(1, source, &written_, &error_details_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500561 // GetReadableRegion should return false because range [0,1) hasn't been
562 // filled yet.
563 iovec iov;
564 EXPECT_FALSE(buffer_->GetReadableRegion(&iov));
565}
566
567TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionTillEndOfBlock) {
568 // Write into [0, kBlockSizeBytes + 1) and then read out [0, 256)
vasilvvc48c8712019-03-11 13:38:16 -0700569 std::string source(kBlockSizeBytes + 1, 'a');
bncce609f72019-06-24 10:23:58 -0700570 buffer_->OnStreamData(0, source, &written_, &error_details_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500571 char dest[256];
572 helper_->Read(dest, 256);
573 // Get readable region from [256, 1024)
574 iovec iov;
575 EXPECT_TRUE(buffer_->GetReadableRegion(&iov));
bnccb3ef7d2019-06-24 10:46:13 -0700576 EXPECT_EQ(std::string(kBlockSizeBytes - 256, 'a'), IovecToStringPiece(iov));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500577}
578
579TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionTillGap) {
580 // Write into [0, kBlockSizeBytes - 1) and then read out [0, 256)
vasilvvc48c8712019-03-11 13:38:16 -0700581 std::string source(kBlockSizeBytes - 1, 'a');
bncce609f72019-06-24 10:23:58 -0700582 buffer_->OnStreamData(0, source, &written_, &error_details_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500583 char dest[256];
584 helper_->Read(dest, 256);
585 // Get readable region from [256, 1023)
586 iovec iov;
587 EXPECT_TRUE(buffer_->GetReadableRegion(&iov));
bnccb3ef7d2019-06-24 10:46:13 -0700588 EXPECT_EQ(std::string(kBlockSizeBytes - 1 - 256, 'a'),
589 IovecToStringPiece(iov));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500590}
591
bnc7b3e0a92019-06-24 16:06:45 -0700592TEST_F(QuicStreamSequencerBufferTest, PeekEmptyBuffer) {
593 iovec iov;
594 EXPECT_FALSE(buffer_->PeekRegion(0, &iov));
595 EXPECT_FALSE(buffer_->PeekRegion(1, &iov));
596 EXPECT_FALSE(buffer_->PeekRegion(100, &iov));
597}
598
599TEST_F(QuicStreamSequencerBufferTest, PeekSingleBlock) {
600 std::string source(kBlockSizeBytes, 'a');
601 buffer_->OnStreamData(0, source, &written_, &error_details_);
602
603 iovec iov;
604 EXPECT_TRUE(buffer_->PeekRegion(0, &iov));
605 EXPECT_EQ(source, IovecToStringPiece(iov));
606
607 // Peeking again gives the same result.
608 EXPECT_TRUE(buffer_->PeekRegion(0, &iov));
609 EXPECT_EQ(source, IovecToStringPiece(iov));
610
611 // Peek at a different offset.
612 EXPECT_TRUE(buffer_->PeekRegion(100, &iov));
vasilvvc872ee42020-10-07 19:50:22 -0700613 EXPECT_EQ(absl::string_view(source).substr(100), IovecToStringPiece(iov));
bnc7b3e0a92019-06-24 16:06:45 -0700614
615 // Peeking at or after FirstMissingByte() returns false.
616 EXPECT_FALSE(buffer_->PeekRegion(kBlockSizeBytes, &iov));
617 EXPECT_FALSE(buffer_->PeekRegion(kBlockSizeBytes + 1, &iov));
618}
619
620TEST_F(QuicStreamSequencerBufferTest, PeekTwoWritesInSingleBlock) {
621 const size_t length1 = 1024;
622 std::string source1(length1, 'a');
623 buffer_->OnStreamData(0, source1, &written_, &error_details_);
624
625 iovec iov;
626 EXPECT_TRUE(buffer_->PeekRegion(0, &iov));
627 EXPECT_EQ(source1, IovecToStringPiece(iov));
628
629 // The second frame goes into the same block.
630 const size_t length2 = 800;
631 std::string source2(length2, 'b');
632 buffer_->OnStreamData(length1, source2, &written_, &error_details_);
633
634 EXPECT_TRUE(buffer_->PeekRegion(length1, &iov));
635 EXPECT_EQ(source2, IovecToStringPiece(iov));
636
637 // Peek with an offset inside the first write.
638 const QuicStreamOffset offset1 = 500;
639 EXPECT_TRUE(buffer_->PeekRegion(offset1, &iov));
vasilvvc872ee42020-10-07 19:50:22 -0700640 EXPECT_EQ(absl::string_view(source1).substr(offset1),
bnc7b3e0a92019-06-24 16:06:45 -0700641 IovecToStringPiece(iov).substr(0, length1 - offset1));
vasilvvc872ee42020-10-07 19:50:22 -0700642 EXPECT_EQ(absl::string_view(source2),
bnc7b3e0a92019-06-24 16:06:45 -0700643 IovecToStringPiece(iov).substr(length1 - offset1));
644
645 // Peek with an offset inside the second write.
646 const QuicStreamOffset offset2 = 1500;
647 EXPECT_TRUE(buffer_->PeekRegion(offset2, &iov));
vasilvvc872ee42020-10-07 19:50:22 -0700648 EXPECT_EQ(absl::string_view(source2).substr(offset2 - length1),
bnc7b3e0a92019-06-24 16:06:45 -0700649 IovecToStringPiece(iov));
650
651 // Peeking at or after FirstMissingByte() returns false.
652 EXPECT_FALSE(buffer_->PeekRegion(length1 + length2, &iov));
653 EXPECT_FALSE(buffer_->PeekRegion(length1 + length2 + 1, &iov));
654}
655
656TEST_F(QuicStreamSequencerBufferTest, PeekBufferWithMultipleBlocks) {
657 const size_t length1 = 1024;
658 std::string source1(length1, 'a');
659 buffer_->OnStreamData(0, source1, &written_, &error_details_);
660
661 iovec iov;
662 EXPECT_TRUE(buffer_->PeekRegion(0, &iov));
663 EXPECT_EQ(source1, IovecToStringPiece(iov));
664
665 const size_t length2 = kBlockSizeBytes + 2;
666 std::string source2(length2, 'b');
667 buffer_->OnStreamData(length1, source2, &written_, &error_details_);
668
669 // Peek with offset 0 returns the entire block.
670 EXPECT_TRUE(buffer_->PeekRegion(0, &iov));
671 EXPECT_EQ(kBlockSizeBytes, iov.iov_len);
672 EXPECT_EQ(source1, IovecToStringPiece(iov).substr(0, length1));
vasilvvc872ee42020-10-07 19:50:22 -0700673 EXPECT_EQ(absl::string_view(source2).substr(0, kBlockSizeBytes - length1),
674 IovecToStringPiece(iov).substr(length1));
bnc7b3e0a92019-06-24 16:06:45 -0700675
676 EXPECT_TRUE(buffer_->PeekRegion(length1, &iov));
vasilvvc872ee42020-10-07 19:50:22 -0700677 EXPECT_EQ(absl::string_view(source2).substr(0, kBlockSizeBytes - length1),
678 IovecToStringPiece(iov));
bnc7b3e0a92019-06-24 16:06:45 -0700679
680 EXPECT_TRUE(buffer_->PeekRegion(kBlockSizeBytes, &iov));
vasilvvc872ee42020-10-07 19:50:22 -0700681 EXPECT_EQ(absl::string_view(source2).substr(kBlockSizeBytes - length1),
682 IovecToStringPiece(iov));
bnc7b3e0a92019-06-24 16:06:45 -0700683
684 // Peeking at or after FirstMissingByte() returns false.
685 EXPECT_FALSE(buffer_->PeekRegion(length1 + length2, &iov));
686 EXPECT_FALSE(buffer_->PeekRegion(length1 + length2 + 1, &iov));
687}
688
689TEST_F(QuicStreamSequencerBufferTest, PeekAfterConsumed) {
690 std::string source1(kBlockSizeBytes, 'a');
691 buffer_->OnStreamData(0, source1, &written_, &error_details_);
692
693 iovec iov;
694 EXPECT_TRUE(buffer_->PeekRegion(0, &iov));
695 EXPECT_EQ(source1, IovecToStringPiece(iov));
696
697 // Consume some data.
698 EXPECT_TRUE(buffer_->MarkConsumed(1024));
699
700 // Peeking into consumed data fails.
701 EXPECT_FALSE(buffer_->PeekRegion(0, &iov));
702 EXPECT_FALSE(buffer_->PeekRegion(512, &iov));
703
704 EXPECT_TRUE(buffer_->PeekRegion(1024, &iov));
vasilvvc872ee42020-10-07 19:50:22 -0700705 EXPECT_EQ(absl::string_view(source1).substr(1024), IovecToStringPiece(iov));
bnc7b3e0a92019-06-24 16:06:45 -0700706
707 EXPECT_TRUE(buffer_->PeekRegion(1500, &iov));
vasilvvc872ee42020-10-07 19:50:22 -0700708 EXPECT_EQ(absl::string_view(source1).substr(1500), IovecToStringPiece(iov));
bnc7b3e0a92019-06-24 16:06:45 -0700709
710 // Consume rest of block.
711 EXPECT_TRUE(buffer_->MarkConsumed(kBlockSizeBytes - 1024));
712
713 // Read new data.
714 std::string source2(300, 'b');
715 buffer_->OnStreamData(kBlockSizeBytes, source2, &written_, &error_details_);
716
717 // Peek into new data.
718 EXPECT_TRUE(buffer_->PeekRegion(kBlockSizeBytes, &iov));
719 EXPECT_EQ(source2, IovecToStringPiece(iov));
720
721 EXPECT_TRUE(buffer_->PeekRegion(kBlockSizeBytes + 128, &iov));
vasilvvc872ee42020-10-07 19:50:22 -0700722 EXPECT_EQ(absl::string_view(source2).substr(128), IovecToStringPiece(iov));
bnc7b3e0a92019-06-24 16:06:45 -0700723
724 // Peeking into consumed data still fails.
725 EXPECT_FALSE(buffer_->PeekRegion(0, &iov));
726 EXPECT_FALSE(buffer_->PeekRegion(512, &iov));
727 EXPECT_FALSE(buffer_->PeekRegion(1024, &iov));
728 EXPECT_FALSE(buffer_->PeekRegion(1500, &iov));
729}
730
731TEST_F(QuicStreamSequencerBufferTest, PeekContinously) {
732 std::string source1(kBlockSizeBytes, 'a');
733 buffer_->OnStreamData(0, source1, &written_, &error_details_);
734
735 iovec iov;
736 EXPECT_TRUE(buffer_->PeekRegion(0, &iov));
737 EXPECT_EQ(source1, IovecToStringPiece(iov));
738
739 std::string source2(kBlockSizeBytes, 'b');
740 buffer_->OnStreamData(kBlockSizeBytes, source2, &written_, &error_details_);
741
742 EXPECT_TRUE(buffer_->PeekRegion(kBlockSizeBytes, &iov));
743 EXPECT_EQ(source2, IovecToStringPiece(iov));
744
745 // First block is still there.
746 EXPECT_TRUE(buffer_->PeekRegion(0, &iov));
747 EXPECT_EQ(source1, IovecToStringPiece(iov));
748}
749
QUICHE teama6ef0a62019-03-07 20:34:33 -0500750TEST_F(QuicStreamSequencerBufferTest, MarkConsumedInOneBlock) {
751 // Write into [0, 1024) and then read out [0, 256)
vasilvvc48c8712019-03-11 13:38:16 -0700752 std::string source(1024, 'a');
bncce609f72019-06-24 10:23:58 -0700753 buffer_->OnStreamData(0, source, &written_, &error_details_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500754 char dest[256];
755 helper_->Read(dest, 256);
756
757 EXPECT_TRUE(buffer_->MarkConsumed(512));
758 EXPECT_EQ(256u + 512u, buffer_->BytesConsumed());
759 EXPECT_EQ(256u, helper_->ReadableBytes());
760 buffer_->MarkConsumed(256);
761 EXPECT_TRUE(buffer_->Empty());
762 EXPECT_TRUE(helper_->CheckBufferInvariants());
763}
764
765TEST_F(QuicStreamSequencerBufferTest, MarkConsumedNotEnoughBytes) {
766 // Write into [0, 1024) and then read out [0, 256)
vasilvvc48c8712019-03-11 13:38:16 -0700767 std::string source(1024, 'a');
bncce609f72019-06-24 10:23:58 -0700768 buffer_->OnStreamData(0, source, &written_, &error_details_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500769 char dest[256];
770 helper_->Read(dest, 256);
771
772 // Consume 1st 512 bytes
773 EXPECT_TRUE(buffer_->MarkConsumed(512));
774 EXPECT_EQ(256u + 512u, buffer_->BytesConsumed());
775 EXPECT_EQ(256u, helper_->ReadableBytes());
776 // Try to consume one bytes more than available. Should return false.
777 EXPECT_FALSE(buffer_->MarkConsumed(257));
778 EXPECT_EQ(256u + 512u, buffer_->BytesConsumed());
779 iovec iov;
780 EXPECT_TRUE(buffer_->GetReadableRegion(&iov));
781 EXPECT_TRUE(helper_->CheckBufferInvariants());
782}
783
784TEST_F(QuicStreamSequencerBufferTest, MarkConsumedAcrossBlock) {
785 // Write into [0, 2 * kBlockSizeBytes + 1024) and then read out [0, 1024)
vasilvvc48c8712019-03-11 13:38:16 -0700786 std::string source(2 * kBlockSizeBytes + 1024, 'a');
bncce609f72019-06-24 10:23:58 -0700787 buffer_->OnStreamData(0, source, &written_, &error_details_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500788 char dest[1024];
789 helper_->Read(dest, 1024);
790
791 buffer_->MarkConsumed(2 * kBlockSizeBytes);
792 EXPECT_EQ(source.size(), buffer_->BytesConsumed());
793 EXPECT_TRUE(buffer_->Empty());
794 EXPECT_TRUE(helper_->CheckBufferInvariants());
795}
796
797TEST_F(QuicStreamSequencerBufferTest, MarkConsumedAcrossEnd) {
haoyuewang21843db2020-11-09 20:45:38 -0800798 // Write into [0, 8.5 * kBlockSizeBytes - 1024) and then read out [0, 1024)
QUICHE teama6ef0a62019-03-07 20:34:33 -0500799 // and then append 1024 + 512 bytes.
haoyuewang21843db2020-11-09 20:45:38 -0800800 std::string source(8.5 * kBlockSizeBytes - 1024, 'a');
bncce609f72019-06-24 10:23:58 -0700801 buffer_->OnStreamData(0, source, &written_, &error_details_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500802 char dest[1024];
803 helper_->Read(dest, 1024);
vasilvvc48c8712019-03-11 13:38:16 -0700804 source = std::string(1024 + 512, 'b');
haoyuewang21843db2020-11-09 20:45:38 -0800805 buffer_->OnStreamData(8.5 * kBlockSizeBytes - 1024, source, &written_,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500806 &error_details_);
807 EXPECT_EQ(1024u, buffer_->BytesConsumed());
808
haoyuewang21843db2020-11-09 20:45:38 -0800809 // Consume to the end of 8th block.
810 buffer_->MarkConsumed(8 * kBlockSizeBytes - 1024);
811 EXPECT_EQ(8 * kBlockSizeBytes, buffer_->BytesConsumed());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500812 // Consume across the physical end of buffer
813 buffer_->MarkConsumed(0.5 * kBlockSizeBytes + 500);
814 EXPECT_EQ(max_capacity_bytes_ + 500, buffer_->BytesConsumed());
815 EXPECT_EQ(12u, helper_->ReadableBytes());
816 // Consume to the logical end of buffer
817 buffer_->MarkConsumed(12);
818 EXPECT_EQ(max_capacity_bytes_ + 512, buffer_->BytesConsumed());
819 EXPECT_TRUE(buffer_->Empty());
820 EXPECT_TRUE(helper_->CheckBufferInvariants());
821}
822
823TEST_F(QuicStreamSequencerBufferTest, FlushBufferedFrames) {
haoyuewang21843db2020-11-09 20:45:38 -0800824 // Write into [0, 8.5 * kBlockSizeBytes - 1024) and then read out [0, 1024).
vasilvvc48c8712019-03-11 13:38:16 -0700825 std::string source(max_capacity_bytes_ - 1024, 'a');
bncce609f72019-06-24 10:23:58 -0700826 buffer_->OnStreamData(0, source, &written_, &error_details_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500827 char dest[1024];
828 helper_->Read(dest, 1024);
829 EXPECT_EQ(1024u, buffer_->BytesConsumed());
830 // Write [1024, 512) to the physical beginning.
vasilvvc48c8712019-03-11 13:38:16 -0700831 source = std::string(512, 'b');
bncce609f72019-06-24 10:23:58 -0700832 buffer_->OnStreamData(max_capacity_bytes_, source, &written_,
833 &error_details_);
834 EXPECT_EQ(512u, written_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500835 EXPECT_EQ(max_capacity_bytes_ - 1024 + 512, buffer_->FlushBufferedFrames());
836 EXPECT_EQ(max_capacity_bytes_ + 512, buffer_->BytesConsumed());
837 EXPECT_TRUE(buffer_->Empty());
838 EXPECT_TRUE(helper_->CheckBufferInvariants());
839 // Clear buffer at this point should still preserve BytesConsumed().
840 buffer_->Clear();
841 EXPECT_EQ(max_capacity_bytes_ + 512, buffer_->BytesConsumed());
842 EXPECT_TRUE(helper_->CheckBufferInvariants());
843}
844
845TEST_F(QuicStreamSequencerBufferTest, TooManyGaps) {
846 // Make sure max capacity is large enough that it is possible to have more
847 // than |kMaxNumGapsAllowed| number of gaps.
848 max_capacity_bytes_ = 3 * kBlockSizeBytes;
849 // Feed buffer with 1-byte discontiguous frames. e.g. [1,2), [3,4), [5,6)...
850 for (QuicStreamOffset begin = 1; begin <= max_capacity_bytes_; begin += 2) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500851 QuicErrorCode rs =
bncce609f72019-06-24 10:23:58 -0700852 buffer_->OnStreamData(begin, "a", &written_, &error_details_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500853
854 QuicStreamOffset last_straw = 2 * kMaxNumGapsAllowed - 1;
855 if (begin == last_straw) {
bncf54082a2019-11-27 10:19:47 -0800856 EXPECT_THAT(rs, IsError(QUIC_TOO_MANY_STREAM_DATA_INTERVALS));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500857 EXPECT_EQ("Too many data intervals received for this stream.",
858 error_details_);
859 break;
860 }
861 }
862}
863
864class QuicStreamSequencerBufferRandomIOTest
865 : public QuicStreamSequencerBufferTest {
866 public:
renjietang58b3af32020-11-11 15:48:58 -0800867 using OffsetSizePair = std::pair<QuicStreamOffset, size_t>;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500868
869 void SetUp() override {
870 // Test against a larger capacity then above tests. Also make sure the last
871 // block is partially available to use.
haoyuewang21843db2020-11-09 20:45:38 -0800872 max_capacity_bytes_ = 8.25 * kBlockSizeBytes;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500873 // Stream to be buffered should be larger than the capacity to test wrap
874 // around.
875 bytes_to_buffer_ = 2 * max_capacity_bytes_;
876 Initialize();
877
878 uint64_t seed = QuicRandom::GetInstance()->RandUint64();
879 QUIC_LOG(INFO) << "**** The current seed is " << seed << " ****";
880 rng_.set_seed(seed);
881 }
882
883 // Create an out-of-order source stream with given size to populate
884 // shuffled_buf_.
885 void CreateSourceAndShuffle(size_t max_chunk_size_bytes) {
886 max_chunk_size_bytes_ = max_chunk_size_bytes;
887 std::unique_ptr<OffsetSizePair[]> chopped_stream(
888 new OffsetSizePair[bytes_to_buffer_]);
889
890 // Split stream into small chunks with random length. chopped_stream will be
891 // populated with segmented stream chunks.
892 size_t start_chopping_offset = 0;
893 size_t iterations = 0;
894 while (start_chopping_offset < bytes_to_buffer_) {
895 size_t max_chunk = std::min<size_t>(
896 max_chunk_size_bytes_, bytes_to_buffer_ - start_chopping_offset);
897 size_t chunk_size = rng_.RandUint64() % max_chunk + 1;
898 chopped_stream[iterations] =
899 OffsetSizePair(start_chopping_offset, chunk_size);
900 start_chopping_offset += chunk_size;
901 ++iterations;
902 }
vasilvvf8035162021-02-01 14:49:14 -0800903 QUICHE_DCHECK(start_chopping_offset == bytes_to_buffer_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500904 size_t chunk_num = iterations;
905
906 // Randomly change the sequence of in-ordered OffsetSizePairs to make a
907 // out-of-order array of OffsetSizePairs.
908 for (int i = chunk_num - 1; i >= 0; --i) {
909 size_t random_idx = rng_.RandUint64() % (i + 1);
910 QUIC_DVLOG(1) << "chunk offset " << chopped_stream[random_idx].first
911 << " size " << chopped_stream[random_idx].second;
912 shuffled_buf_.push_front(chopped_stream[random_idx]);
913 chopped_stream[random_idx] = chopped_stream[i];
914 }
915 }
916
917 // Write the currently first chunk of data in the out-of-order stream into
918 // QuicStreamSequencerBuffer. If current chuck cannot be written into buffer
919 // because it goes beyond current capacity, move it to the end of
920 // shuffled_buf_ and write it later.
921 void WriteNextChunkToBuffer() {
922 OffsetSizePair& chunk = shuffled_buf_.front();
923 QuicStreamOffset offset = chunk.first;
924 const size_t num_to_write = chunk.second;
925 std::unique_ptr<char[]> write_buf{new char[max_chunk_size_bytes_]};
926 for (size_t i = 0; i < num_to_write; ++i) {
927 write_buf[i] = (offset + i) % 256;
928 }
vasilvvc872ee42020-10-07 19:50:22 -0700929 absl::string_view string_piece_w(write_buf.get(), num_to_write);
bncce609f72019-06-24 10:23:58 -0700930 auto result = buffer_->OnStreamData(offset, string_piece_w, &written_,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500931 &error_details_);
932 if (result == QUIC_NO_ERROR) {
933 shuffled_buf_.pop_front();
934 total_bytes_written_ += num_to_write;
935 } else {
936 // This chunk offset exceeds window size.
937 shuffled_buf_.push_back(chunk);
938 shuffled_buf_.pop_front();
939 }
940 QUIC_DVLOG(1) << " write at offset: " << offset
941 << " len to write: " << num_to_write
942 << " write result: " << result
943 << " left over: " << shuffled_buf_.size();
944 }
945
946 protected:
947 std::list<OffsetSizePair> shuffled_buf_;
948 size_t max_chunk_size_bytes_;
949 QuicStreamOffset bytes_to_buffer_;
950 size_t total_bytes_written_ = 0;
951 size_t total_bytes_read_ = 0;
952 SimpleRandom rng_;
953};
954
955TEST_F(QuicStreamSequencerBufferRandomIOTest, RandomWriteAndReadv) {
956 // Set kMaxReadSize larger than kBlockSizeBytes to test both small and large
957 // read.
958 const size_t kMaxReadSize = kBlockSizeBytes * 2;
959 // kNumReads is larger than 1 to test how multiple read destinations work.
960 const size_t kNumReads = 2;
961 // Since write and read operation have equal possibility to be called. Bytes
962 // to be written into and read out of should roughly the same.
963 const size_t kMaxWriteSize = kNumReads * kMaxReadSize;
964 size_t iterations = 0;
965
966 CreateSourceAndShuffle(kMaxWriteSize);
967
968 while ((!shuffled_buf_.empty() || total_bytes_read_ < bytes_to_buffer_) &&
969 iterations <= 2 * bytes_to_buffer_) {
970 uint8_t next_action =
971 shuffled_buf_.empty() ? uint8_t{1} : rng_.RandUint64() % 2;
972 QUIC_DVLOG(1) << "iteration: " << iterations;
973 switch (next_action) {
974 case 0: { // write
975 WriteNextChunkToBuffer();
976 ASSERT_TRUE(helper_->CheckBufferInvariants());
977 break;
978 }
979 case 1: { // readv
980 std::unique_ptr<char[][kMaxReadSize]> read_buf{
981 new char[kNumReads][kMaxReadSize]};
982 iovec dest_iov[kNumReads];
983 size_t num_to_read = 0;
984 for (size_t i = 0; i < kNumReads; ++i) {
985 dest_iov[i].iov_base =
986 reinterpret_cast<void*>(const_cast<char*>(read_buf[i]));
987 dest_iov[i].iov_len = rng_.RandUint64() % kMaxReadSize;
988 num_to_read += dest_iov[i].iov_len;
989 }
990 size_t actually_read;
bncf54082a2019-11-27 10:19:47 -0800991 EXPECT_THAT(buffer_->Readv(dest_iov, kNumReads, &actually_read,
992 &error_details_),
993 IsQuicNoError());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500994 ASSERT_LE(actually_read, num_to_read);
995 QUIC_DVLOG(1) << " read from offset: " << total_bytes_read_
996 << " size: " << num_to_read
997 << " actual read: " << actually_read;
998 for (size_t i = 0; i < actually_read; ++i) {
999 char ch = (i + total_bytes_read_) % 256;
1000 ASSERT_EQ(ch, GetCharFromIOVecs(i, dest_iov, kNumReads))
1001 << " at iteration " << iterations;
1002 }
1003 total_bytes_read_ += actually_read;
1004 ASSERT_EQ(total_bytes_read_, buffer_->BytesConsumed());
1005 ASSERT_TRUE(helper_->CheckBufferInvariants());
1006 break;
1007 }
1008 }
1009 ++iterations;
1010 ASSERT_LE(total_bytes_read_, total_bytes_written_);
1011 }
1012 EXPECT_LT(iterations, bytes_to_buffer_) << "runaway test";
1013 EXPECT_LE(bytes_to_buffer_, total_bytes_read_)
1014 << "iterations: " << iterations;
1015 EXPECT_LE(bytes_to_buffer_, total_bytes_written_);
1016}
1017
1018TEST_F(QuicStreamSequencerBufferRandomIOTest, RandomWriteAndConsumeInPlace) {
1019 // The value 4 is chosen such that the max write size is no larger than the
1020 // maximum buffer capacity.
1021 const size_t kMaxNumReads = 4;
1022 // Adjust write amount be roughly equal to that GetReadableRegions() can get.
1023 const size_t kMaxWriteSize = kMaxNumReads * kBlockSizeBytes;
1024 ASSERT_LE(kMaxWriteSize, max_capacity_bytes_);
1025 size_t iterations = 0;
1026
1027 CreateSourceAndShuffle(kMaxWriteSize);
1028
1029 while ((!shuffled_buf_.empty() || total_bytes_read_ < bytes_to_buffer_) &&
1030 iterations <= 2 * bytes_to_buffer_) {
1031 uint8_t next_action =
1032 shuffled_buf_.empty() ? uint8_t{1} : rng_.RandUint64() % 2;
1033 QUIC_DVLOG(1) << "iteration: " << iterations;
1034 switch (next_action) {
1035 case 0: { // write
1036 WriteNextChunkToBuffer();
1037 ASSERT_TRUE(helper_->CheckBufferInvariants());
1038 break;
1039 }
1040 case 1: { // GetReadableRegions and then MarkConsumed
1041 size_t num_read = rng_.RandUint64() % kMaxNumReads + 1;
1042 iovec dest_iov[kMaxNumReads];
1043 ASSERT_TRUE(helper_->CheckBufferInvariants());
1044 size_t actually_num_read =
1045 buffer_->GetReadableRegions(dest_iov, num_read);
1046 ASSERT_LE(actually_num_read, num_read);
1047 size_t avail_bytes = 0;
1048 for (size_t i = 0; i < actually_num_read; ++i) {
1049 avail_bytes += dest_iov[i].iov_len;
1050 }
1051 // process random number of bytes (check the value of each byte).
1052 size_t bytes_to_process = rng_.RandUint64() % (avail_bytes + 1);
1053 size_t bytes_processed = 0;
1054 for (size_t i = 0; i < actually_num_read; ++i) {
1055 size_t bytes_in_block = std::min<size_t>(
1056 bytes_to_process - bytes_processed, dest_iov[i].iov_len);
1057 if (bytes_in_block == 0) {
1058 break;
1059 }
1060 for (size_t j = 0; j < bytes_in_block; ++j) {
1061 ASSERT_LE(bytes_processed, bytes_to_process);
1062 char char_expected =
1063 (buffer_->BytesConsumed() + bytes_processed) % 256;
1064 ASSERT_EQ(char_expected,
1065 reinterpret_cast<const char*>(dest_iov[i].iov_base)[j])
1066 << " at iteration " << iterations;
1067 ++bytes_processed;
1068 }
1069 }
1070
1071 buffer_->MarkConsumed(bytes_processed);
1072
1073 QUIC_DVLOG(1) << "iteration " << iterations << ": try to get "
1074 << num_read << " readable regions, actually get "
1075 << actually_num_read
1076 << " from offset: " << total_bytes_read_
1077 << "\nprocesse bytes: " << bytes_processed;
1078 total_bytes_read_ += bytes_processed;
1079 ASSERT_EQ(total_bytes_read_, buffer_->BytesConsumed());
1080 ASSERT_TRUE(helper_->CheckBufferInvariants());
1081 break;
1082 }
1083 }
1084 ++iterations;
1085 ASSERT_LE(total_bytes_read_, total_bytes_written_);
1086 }
1087 EXPECT_LT(iterations, bytes_to_buffer_) << "runaway test";
1088 EXPECT_LE(bytes_to_buffer_, total_bytes_read_)
1089 << "iterations: " << iterations;
1090 EXPECT_LE(bytes_to_buffer_, total_bytes_written_);
1091}
1092
haoyuewang21843db2020-11-09 20:45:38 -08001093TEST_F(QuicStreamSequencerBufferTest, GrowBlockSizeOnDemand) {
1094 SetQuicReloadableFlag(quic_allocate_stream_sequencer_buffer_blocks_on_demand,
1095 true);
1096 max_capacity_bytes_ = 1024 * kBlockSizeBytes;
1097 std::string source_of_one_block(kBlockSizeBytes, 'a');
1098 Initialize();
1099
1100 ASSERT_EQ(helper_->current_blocks_count(), 0u);
1101
1102 // A minimum of 8 blocks are allocated
1103 buffer_->OnStreamData(0, source_of_one_block, &written_, &error_details_);
1104 ASSERT_EQ(helper_->current_blocks_count(), 8u);
1105
1106 // Number of blocks doesn't grow if the data is within the capacity.
1107 buffer_->OnStreamData(kBlockSizeBytes * 7, source_of_one_block, &written_,
1108 &error_details_);
1109 ASSERT_EQ(helper_->current_blocks_count(), 8u);
1110
1111 // Number of blocks grows by a factor of 4 normally.
1112 buffer_->OnStreamData(kBlockSizeBytes * 8, "a", &written_, &error_details_);
1113 ASSERT_EQ(helper_->current_blocks_count(), 32u);
1114
1115 // Number of blocks grow to the demanded size of 140 instead of 128 since
1116 // that's not enough.
1117 buffer_->OnStreamData(kBlockSizeBytes * 139, source_of_one_block, &written_,
1118 &error_details_);
1119 ASSERT_EQ(helper_->current_blocks_count(), 140u);
1120
1121 // Number of blocks grows by a factor of 4 normally.
1122 buffer_->OnStreamData(kBlockSizeBytes * 140, source_of_one_block, &written_,
1123 &error_details_);
1124 ASSERT_EQ(helper_->current_blocks_count(), 560u);
1125
1126 // max_capacity_bytes is reached and number of blocks is capped.
1127 buffer_->OnStreamData(kBlockSizeBytes * 560, source_of_one_block, &written_,
1128 &error_details_);
1129 ASSERT_EQ(helper_->current_blocks_count(), 1024u);
1130
1131 // max_capacity_bytes is reached and number of blocks is capped.
1132 buffer_->OnStreamData(kBlockSizeBytes * 1025, source_of_one_block, &written_,
1133 &error_details_);
1134 ASSERT_EQ(helper_->current_blocks_count(), 1024u);
1135}
1136
QUICHE teama6ef0a62019-03-07 20:34:33 -05001137} // anonymous namespace
1138
1139} // namespace test
1140
1141} // namespace quic