blob: 335aa2dd3d8fc5dd5b152dad7512e71d811d4673 [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
5#include "net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer.h"
6
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
QUICHE teama6ef0a62019-03-07 20:34:33 -050014#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
15#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
16#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050017#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
18#include "net/third_party/quiche/src/quic/test_tools/quic_stream_sequencer_buffer_peer.h"
19#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
20
21namespace quic {
22
23namespace test {
24
25char GetCharFromIOVecs(size_t offset, iovec iov[], size_t count) {
26 size_t start_offset = 0;
27 for (size_t i = 0; i < count; i++) {
28 if (iov[i].iov_len == 0) {
29 continue;
30 }
31 size_t end_offset = start_offset + iov[i].iov_len - 1;
32 if (offset >= start_offset && offset <= end_offset) {
33 const char* buf = reinterpret_cast<const char*>(iov[i].iov_base);
34 return buf[offset - start_offset];
35 }
36 start_offset += iov[i].iov_len;
37 }
dschinazi4620e9a2019-04-26 16:07:11 -070038 QUIC_LOG(ERROR) << "Could not locate char at offset " << offset << " in "
39 << count << " iovecs";
QUICHE teama6ef0a62019-03-07 20:34:33 -050040 for (size_t i = 0; i < count; ++i) {
dschinazi4620e9a2019-04-26 16:07:11 -070041 QUIC_LOG(ERROR) << " iov[" << i << "].iov_len = " << iov[i].iov_len;
QUICHE teama6ef0a62019-03-07 20:34:33 -050042 }
43 return '\0';
44}
45
46const size_t kMaxNumGapsAllowed = 2 * kMaxPacketGap;
47
48static const size_t kBlockSizeBytes =
49 QuicStreamSequencerBuffer::kBlockSizeBytes;
50typedef QuicStreamSequencerBuffer::BufferBlock BufferBlock;
51
52namespace {
53
54class QuicStreamSequencerBufferTest : public QuicTest {
55 public:
56 void SetUp() override { Initialize(); }
57
58 void ResetMaxCapacityBytes(size_t max_capacity_bytes) {
59 max_capacity_bytes_ = max_capacity_bytes;
60 Initialize();
61 }
62
63 protected:
64 void Initialize() {
65 buffer_ = QuicMakeUnique<QuicStreamSequencerBuffer>((max_capacity_bytes_));
66 helper_ = QuicMakeUnique<QuicStreamSequencerBufferPeer>((buffer_.get()));
67 }
68
69 // Use 2.5 here to make sure the buffer has more than one block and its end
70 // doesn't align with the end of a block in order to test all the offset
71 // calculation.
72 size_t max_capacity_bytes_ = 2.5 * kBlockSizeBytes;
73
74 std::unique_ptr<QuicStreamSequencerBuffer> buffer_;
75 std::unique_ptr<QuicStreamSequencerBufferPeer> helper_;
vasilvvc48c8712019-03-11 13:38:16 -070076 std::string error_details_;
QUICHE teama6ef0a62019-03-07 20:34:33 -050077};
78
79TEST_F(QuicStreamSequencerBufferTest, InitializeWithMaxRecvWindowSize) {
80 ResetMaxCapacityBytes(16 * 1024 * 1024); // 16MB
81 EXPECT_EQ(2 * 1024u, // 16MB / 8KB = 2K
82 helper_->block_count());
83 EXPECT_EQ(max_capacity_bytes_, helper_->max_buffer_capacity());
84 EXPECT_TRUE(helper_->CheckInitialState());
85}
86
87TEST_F(QuicStreamSequencerBufferTest, InitializationWithDifferentSizes) {
88 const size_t kCapacity = 2 * QuicStreamSequencerBuffer::kBlockSizeBytes;
89 ResetMaxCapacityBytes(kCapacity);
90 EXPECT_EQ(max_capacity_bytes_, helper_->max_buffer_capacity());
91 EXPECT_TRUE(helper_->CheckInitialState());
92
93 const size_t kCapacity1 = 8 * QuicStreamSequencerBuffer::kBlockSizeBytes;
94 ResetMaxCapacityBytes(kCapacity1);
95 EXPECT_EQ(kCapacity1, helper_->max_buffer_capacity());
96 EXPECT_TRUE(helper_->CheckInitialState());
97}
98
99TEST_F(QuicStreamSequencerBufferTest, ClearOnEmpty) {
100 buffer_->Clear();
101 EXPECT_TRUE(helper_->CheckBufferInvariants());
102}
103
104TEST_F(QuicStreamSequencerBufferTest, OnStreamData0length) {
105 size_t written;
106 QuicErrorCode error =
107 buffer_->OnStreamData(800, "", &written, &error_details_);
108 EXPECT_EQ(error, QUIC_EMPTY_STREAM_FRAME_NO_FIN);
109 EXPECT_TRUE(helper_->CheckBufferInvariants());
110}
111
112TEST_F(QuicStreamSequencerBufferTest, OnStreamDataWithinBlock) {
113 EXPECT_FALSE(helper_->IsBufferAllocated());
vasilvvc48c8712019-03-11 13:38:16 -0700114 std::string source(1024, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500115 size_t written;
116 EXPECT_EQ(QUIC_NO_ERROR,
117 buffer_->OnStreamData(800, source, &written, &error_details_));
118 BufferBlock* block_ptr = helper_->GetBlock(0);
119 for (size_t i = 0; i < source.size(); ++i) {
120 ASSERT_EQ('a', block_ptr->buffer[helper_->GetInBlockOffset(800) + i]);
121 }
122 EXPECT_EQ(2, helper_->IntervalSize());
123 EXPECT_EQ(0u, helper_->ReadableBytes());
124 EXPECT_EQ(1u, helper_->bytes_received().Size());
125 EXPECT_EQ(800u, helper_->bytes_received().begin()->min());
126 EXPECT_EQ(1824u, helper_->bytes_received().begin()->max());
127 EXPECT_TRUE(helper_->CheckBufferInvariants());
128 EXPECT_TRUE(helper_->IsBufferAllocated());
129}
130
131TEST_F(QuicStreamSequencerBufferTest, Move) {
132 EXPECT_FALSE(helper_->IsBufferAllocated());
vasilvvc48c8712019-03-11 13:38:16 -0700133 std::string source(1024, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500134 size_t written;
135 EXPECT_EQ(QUIC_NO_ERROR,
136 buffer_->OnStreamData(800, source, &written, &error_details_));
137 BufferBlock* block_ptr = helper_->GetBlock(0);
138 for (size_t i = 0; i < source.size(); ++i) {
139 ASSERT_EQ('a', block_ptr->buffer[helper_->GetInBlockOffset(800) + i]);
140 }
141
142 QuicStreamSequencerBuffer buffer2(std::move(*buffer_));
143 QuicStreamSequencerBufferPeer helper2(&buffer2);
144
145 EXPECT_FALSE(helper_->IsBufferAllocated());
146
147 EXPECT_EQ(2, helper2.IntervalSize());
148 EXPECT_EQ(0u, helper2.ReadableBytes());
149 EXPECT_EQ(1u, helper2.bytes_received().Size());
150 EXPECT_EQ(800u, helper2.bytes_received().begin()->min());
151 EXPECT_EQ(1824u, helper2.bytes_received().begin()->max());
152 EXPECT_TRUE(helper2.CheckBufferInvariants());
153 EXPECT_TRUE(helper2.IsBufferAllocated());
154}
155
156TEST_F(QuicStreamSequencerBufferTest, OnStreamDataInvalidSource) {
157 // Pass in an invalid source, expects to return error.
158 QuicStringPiece source;
159 source = QuicStringPiece(nullptr, 1024);
160 size_t written;
161 EXPECT_EQ(QUIC_STREAM_SEQUENCER_INVALID_STATE,
162 buffer_->OnStreamData(800, source, &written, &error_details_));
163 EXPECT_EQ(0u, error_details_.find(QuicStrCat(
164 "QuicStreamSequencerBuffer error: OnStreamData() "
165 "dest == nullptr: ",
166 false, " source == nullptr: ", true)));
167}
168
169TEST_F(QuicStreamSequencerBufferTest, OnStreamDataWithOverlap) {
vasilvvc48c8712019-03-11 13:38:16 -0700170 std::string source(1024, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500171 // Write something into [800, 1824)
172 size_t written;
173 EXPECT_EQ(QUIC_NO_ERROR,
174 buffer_->OnStreamData(800, source, &written, &error_details_));
175 // Try to write to [0, 1024) and [1024, 2048).
176 EXPECT_EQ(QUIC_NO_ERROR,
177 buffer_->OnStreamData(0, source, &written, &error_details_));
178 EXPECT_EQ(QUIC_NO_ERROR,
179 buffer_->OnStreamData(1024, source, &written, &error_details_));
180}
181
182TEST_F(QuicStreamSequencerBufferTest,
183 OnStreamDataOverlapAndDuplicateCornerCases) {
vasilvvc48c8712019-03-11 13:38:16 -0700184 std::string source(1024, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500185 // Write something into [800, 1824)
186 size_t written;
187 buffer_->OnStreamData(800, source, &written, &error_details_);
vasilvvc48c8712019-03-11 13:38:16 -0700188 source = std::string(800, 'b');
189 std::string one_byte = "c";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500190 // Write [1, 801).
191 EXPECT_EQ(QUIC_NO_ERROR,
192 buffer_->OnStreamData(1, source, &written, &error_details_));
193 // Write [0, 800).
194 EXPECT_EQ(QUIC_NO_ERROR,
195 buffer_->OnStreamData(0, source, &written, &error_details_));
196 // Write [1823, 1824).
197 EXPECT_EQ(QUIC_NO_ERROR,
198 buffer_->OnStreamData(1823, one_byte, &written, &error_details_));
199 EXPECT_EQ(0u, written);
200 // write one byte to [1824, 1825)
201 EXPECT_EQ(QUIC_NO_ERROR,
202 buffer_->OnStreamData(1824, one_byte, &written, &error_details_));
203 EXPECT_TRUE(helper_->CheckBufferInvariants());
204}
205
206TEST_F(QuicStreamSequencerBufferTest, OnStreamDataWithoutOverlap) {
vasilvvc48c8712019-03-11 13:38:16 -0700207 std::string source(1024, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500208 // Write something into [800, 1824).
209 size_t written;
210 EXPECT_EQ(QUIC_NO_ERROR,
211 buffer_->OnStreamData(800, source, &written, &error_details_));
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).
214 EXPECT_EQ(QUIC_NO_ERROR,
215 buffer_->OnStreamData(kBlockSizeBytes * 2 - 20, source, &written,
216 &error_details_));
217 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 size_t written;
232 // Frame [2^32 + 500, 2^32 + 600).
233 QuicStreamOffset offset = pow(2, 32) + 500;
234 EXPECT_EQ(QUIC_NO_ERROR,
235 buffer_->OnStreamData(offset, source, &written, &error_details_));
236 EXPECT_EQ(2, helper_->IntervalSize());
237
238 // Frame [2^32 + 700, 2^32 + 800).
239 offset = pow(2, 32) + 700;
240 EXPECT_EQ(QUIC_NO_ERROR,
241 buffer_->OnStreamData(offset, source, &written, &error_details_));
242 EXPECT_EQ(3, helper_->IntervalSize());
243
244 // Another frame [2^32 + 300, 2^32 + 400).
245 offset = pow(2, 32) + 300;
246 EXPECT_EQ(QUIC_NO_ERROR,
247 buffer_->OnStreamData(offset, source, &written, &error_details_));
248 EXPECT_EQ(4, helper_->IntervalSize());
249}
250
251TEST_F(QuicStreamSequencerBufferTest, OnStreamDataTillEnd) {
252 // Write 50 bytes to the end.
253 const size_t kBytesToWrite = 50;
vasilvvc48c8712019-03-11 13:38:16 -0700254 std::string source(kBytesToWrite, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500255 size_t written;
256 EXPECT_EQ(QUIC_NO_ERROR,
257 buffer_->OnStreamData(max_capacity_bytes_ - kBytesToWrite, source,
258 &written, &error_details_));
259 EXPECT_EQ(50u, buffer_->BytesBuffered());
260 EXPECT_TRUE(helper_->CheckBufferInvariants());
261}
262
263TEST_F(QuicStreamSequencerBufferTest, OnStreamDataTillEndCorner) {
264 // Write 1 byte to the end.
265 const size_t kBytesToWrite = 1;
vasilvvc48c8712019-03-11 13:38:16 -0700266 std::string source(kBytesToWrite, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500267 size_t written;
268 EXPECT_EQ(QUIC_NO_ERROR,
269 buffer_->OnStreamData(max_capacity_bytes_ - kBytesToWrite, source,
270 &written, &error_details_));
271 EXPECT_EQ(1u, buffer_->BytesBuffered());
272 EXPECT_TRUE(helper_->CheckBufferInvariants());
273}
274
275TEST_F(QuicStreamSequencerBufferTest, OnStreamDataBeyondCapacity) {
vasilvvc48c8712019-03-11 13:38:16 -0700276 std::string source(60, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500277 size_t written;
278 EXPECT_EQ(QUIC_INTERNAL_ERROR,
279 buffer_->OnStreamData(max_capacity_bytes_ - 50, source, &written,
280 &error_details_));
281 EXPECT_TRUE(helper_->CheckBufferInvariants());
282
283 source = "b";
284 EXPECT_EQ(QUIC_INTERNAL_ERROR,
285 buffer_->OnStreamData(max_capacity_bytes_, source, &written,
286 &error_details_));
287 EXPECT_TRUE(helper_->CheckBufferInvariants());
288
289 EXPECT_EQ(QUIC_INTERNAL_ERROR,
290 buffer_->OnStreamData(max_capacity_bytes_ * 1000, source, &written,
291 &error_details_));
292 EXPECT_TRUE(helper_->CheckBufferInvariants());
293
294 // Disallow current_gap != gaps_.end()
295 EXPECT_EQ(QUIC_INTERNAL_ERROR,
296 buffer_->OnStreamData(static_cast<QuicStreamOffset>(-1), source,
297 &written, &error_details_));
298 EXPECT_TRUE(helper_->CheckBufferInvariants());
299
300 // Disallow offset + size overflow
301 source = "bbb";
302 EXPECT_EQ(QUIC_INTERNAL_ERROR,
303 buffer_->OnStreamData(static_cast<QuicStreamOffset>(-2), source,
304 &written, &error_details_));
305 EXPECT_TRUE(helper_->CheckBufferInvariants());
306 EXPECT_EQ(0u, buffer_->BytesBuffered());
307}
308
309TEST_F(QuicStreamSequencerBufferTest, Readv100Bytes) {
vasilvvc48c8712019-03-11 13:38:16 -0700310 std::string source(1024, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500311 // Write something into [kBlockSizeBytes, kBlockSizeBytes + 1024).
312 size_t written;
313 buffer_->OnStreamData(kBlockSizeBytes, source, &written, &error_details_);
314 EXPECT_FALSE(buffer_->HasBytesToRead());
vasilvvc48c8712019-03-11 13:38:16 -0700315 source = std::string(100, 'b');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500316 // Write something into [0, 100).
317 buffer_->OnStreamData(0, source, &written, &error_details_);
318 EXPECT_TRUE(buffer_->HasBytesToRead());
319 // Read into a iovec array with total capacity of 120 bytes.
320 char dest[120];
321 iovec iovecs[3]{iovec{dest, 40}, iovec{dest + 40, 40}, iovec{dest + 80, 40}};
322 size_t read;
323 EXPECT_EQ(QUIC_NO_ERROR, buffer_->Readv(iovecs, 3, &read, &error_details_));
324 QUIC_LOG(ERROR) << error_details_;
325 EXPECT_EQ(100u, read);
326 EXPECT_EQ(100u, buffer_->BytesConsumed());
vasilvvc48c8712019-03-11 13:38:16 -0700327 EXPECT_EQ(source, std::string(dest, read));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500328 // The first block should be released as its data has been read out.
329 EXPECT_EQ(nullptr, helper_->GetBlock(0));
330 EXPECT_TRUE(helper_->CheckBufferInvariants());
331}
332
333TEST_F(QuicStreamSequencerBufferTest, ReadvAcrossBlocks) {
vasilvvc48c8712019-03-11 13:38:16 -0700334 std::string source(kBlockSizeBytes + 50, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500335 // Write 1st block to full and extand 50 bytes to next block.
336 size_t written;
337 buffer_->OnStreamData(0, source, &written, &error_details_);
338 EXPECT_EQ(source.size(), helper_->ReadableBytes());
339 // Iteratively read 512 bytes from buffer_-> Overwrite dest[] each time.
340 char dest[512];
341 while (helper_->ReadableBytes()) {
342 std::fill(dest, dest + 512, 0);
343 iovec iovecs[2]{iovec{dest, 256}, iovec{dest + 256, 256}};
344 size_t read;
345 EXPECT_EQ(QUIC_NO_ERROR, buffer_->Readv(iovecs, 2, &read, &error_details_));
346 }
347 // The last read only reads the rest 50 bytes in 2nd block.
vasilvvc48c8712019-03-11 13:38:16 -0700348 EXPECT_EQ(std::string(50, 'a'), std::string(dest, 50));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500349 EXPECT_EQ(0, dest[50]) << "Dest[50] shouln't be filled.";
350 EXPECT_EQ(source.size(), buffer_->BytesConsumed());
351 EXPECT_TRUE(buffer_->Empty());
352 EXPECT_TRUE(helper_->CheckBufferInvariants());
353}
354
355TEST_F(QuicStreamSequencerBufferTest, ClearAfterRead) {
vasilvvc48c8712019-03-11 13:38:16 -0700356 std::string source(kBlockSizeBytes + 50, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500357 // Write 1st block to full with 'a'.
358 size_t written;
359 buffer_->OnStreamData(0, source, &written, &error_details_);
360 // Read first 512 bytes from buffer to make space at the beginning.
361 char dest[512]{0};
362 const iovec iov{dest, 512};
363 size_t read;
364 EXPECT_EQ(QUIC_NO_ERROR, buffer_->Readv(&iov, 1, &read, &error_details_));
365 // Clear() should make buffer empty while preserving BytesConsumed()
366 buffer_->Clear();
367 EXPECT_TRUE(buffer_->Empty());
368 EXPECT_TRUE(helper_->CheckBufferInvariants());
369}
370
371TEST_F(QuicStreamSequencerBufferTest,
372 OnStreamDataAcrossLastBlockAndFillCapacity) {
vasilvvc48c8712019-03-11 13:38:16 -0700373 std::string source(kBlockSizeBytes + 50, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500374 // Write 1st block to full with 'a'.
375 size_t written;
376 buffer_->OnStreamData(0, source, &written, &error_details_);
377 // Read first 512 bytes from buffer to make space at the beginning.
378 char dest[512]{0};
379 const iovec iov{dest, 512};
380 size_t read;
381 EXPECT_EQ(QUIC_NO_ERROR, buffer_->Readv(&iov, 1, &read, &error_details_));
382 EXPECT_EQ(source.size(), written);
383
384 // Write more than half block size of bytes in the last block with 'b', which
385 // will wrap to the beginning and reaches the full capacity.
vasilvvc48c8712019-03-11 13:38:16 -0700386 source = std::string(0.5 * kBlockSizeBytes + 512, 'b');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500387 EXPECT_EQ(QUIC_NO_ERROR, buffer_->OnStreamData(2 * kBlockSizeBytes, source,
388 &written, &error_details_));
389 EXPECT_EQ(source.size(), written);
390 EXPECT_TRUE(helper_->CheckBufferInvariants());
391}
392
393TEST_F(QuicStreamSequencerBufferTest,
394 OnStreamDataAcrossLastBlockAndExceedCapacity) {
vasilvvc48c8712019-03-11 13:38:16 -0700395 std::string source(kBlockSizeBytes + 50, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500396 // Write 1st block to full.
397 size_t written;
398 buffer_->OnStreamData(0, source, &written, &error_details_);
399 // Read first 512 bytes from buffer to make space at the beginning.
400 char dest[512]{0};
401 const iovec iov{dest, 512};
402 size_t read;
403 EXPECT_EQ(QUIC_NO_ERROR, buffer_->Readv(&iov, 1, &read, &error_details_));
404
405 // Try to write from [max_capacity_bytes_ - 0.5 * kBlockSizeBytes,
406 // max_capacity_bytes_ + 512 + 1). But last bytes exceeds current capacity.
vasilvvc48c8712019-03-11 13:38:16 -0700407 source = std::string(0.5 * kBlockSizeBytes + 512 + 1, 'b');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500408 EXPECT_EQ(QUIC_INTERNAL_ERROR,
409 buffer_->OnStreamData(2 * kBlockSizeBytes, source, &written,
410 &error_details_));
411 EXPECT_TRUE(helper_->CheckBufferInvariants());
412}
413
414TEST_F(QuicStreamSequencerBufferTest, ReadvAcrossLastBlock) {
415 // Write to full capacity and read out 512 bytes at beginning and continue
416 // appending 256 bytes.
vasilvvc48c8712019-03-11 13:38:16 -0700417 std::string source(max_capacity_bytes_, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500418 size_t written;
419 buffer_->OnStreamData(0, source, &written, &error_details_);
420 char dest[512]{0};
421 const iovec iov{dest, 512};
422 size_t read;
423 EXPECT_EQ(QUIC_NO_ERROR, buffer_->Readv(&iov, 1, &read, &error_details_));
vasilvvc48c8712019-03-11 13:38:16 -0700424 source = std::string(256, 'b');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500425 buffer_->OnStreamData(max_capacity_bytes_, source, &written, &error_details_);
426 EXPECT_TRUE(helper_->CheckBufferInvariants());
427
428 // Read all data out.
429 std::unique_ptr<char[]> dest1{new char[max_capacity_bytes_]};
430 dest1[0] = 0;
431 const iovec iov1{dest1.get(), max_capacity_bytes_};
432 EXPECT_EQ(QUIC_NO_ERROR, buffer_->Readv(&iov1, 1, &read, &error_details_));
433 EXPECT_EQ(max_capacity_bytes_ - 512 + 256, read);
434 EXPECT_EQ(max_capacity_bytes_ + 256, buffer_->BytesConsumed());
435 EXPECT_TRUE(buffer_->Empty());
436 EXPECT_TRUE(helper_->CheckBufferInvariants());
437}
438
439TEST_F(QuicStreamSequencerBufferTest, ReadvEmpty) {
440 char dest[512]{0};
441 iovec iov{dest, 512};
442 size_t read;
443 EXPECT_EQ(QUIC_NO_ERROR, buffer_->Readv(&iov, 1, &read, &error_details_));
444 EXPECT_EQ(0u, read);
445 EXPECT_TRUE(helper_->CheckBufferInvariants());
446}
447
448TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionsEmpty) {
449 iovec iovs[2];
450 int iov_count = buffer_->GetReadableRegions(iovs, 2);
451 EXPECT_EQ(0, iov_count);
452 EXPECT_EQ(nullptr, iovs[iov_count].iov_base);
453 EXPECT_EQ(0u, iovs[iov_count].iov_len);
454}
455
456TEST_F(QuicStreamSequencerBufferTest, ReleaseWholeBuffer) {
457 // Tests that buffer is not deallocated unless ReleaseWholeBuffer() is called.
vasilvvc48c8712019-03-11 13:38:16 -0700458 std::string source(100, 'b');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500459 // Write something into [0, 100).
460 size_t written;
461 buffer_->OnStreamData(0, source, &written, &error_details_);
462 EXPECT_TRUE(buffer_->HasBytesToRead());
463 char dest[120];
464 iovec iovecs[3]{iovec{dest, 40}, iovec{dest + 40, 40}, iovec{dest + 80, 40}};
465 size_t read;
466 EXPECT_EQ(QUIC_NO_ERROR, buffer_->Readv(iovecs, 3, &read, &error_details_));
467 EXPECT_EQ(100u, read);
468 EXPECT_EQ(100u, buffer_->BytesConsumed());
469 EXPECT_TRUE(helper_->CheckBufferInvariants());
470 EXPECT_TRUE(helper_->IsBufferAllocated());
471 buffer_->ReleaseWholeBuffer();
472 EXPECT_FALSE(helper_->IsBufferAllocated());
473}
474
475TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionsBlockedByGap) {
476 // Write into [1, 1024).
vasilvvc48c8712019-03-11 13:38:16 -0700477 std::string source(1023, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500478 size_t written;
479 buffer_->OnStreamData(1, source, &written, &error_details_);
480 // Try to get readable regions, but none is there.
481 iovec iovs[2];
482 int iov_count = buffer_->GetReadableRegions(iovs, 2);
483 EXPECT_EQ(0, iov_count);
484}
485
486TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionsTillEndOfBlock) {
487 // Write first block to full with [0, 256) 'a' and the rest 'b' then read out
488 // [0, 256)
vasilvvc48c8712019-03-11 13:38:16 -0700489 std::string source(kBlockSizeBytes, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500490 size_t written;
491 buffer_->OnStreamData(0, source, &written, &error_details_);
492 char dest[256];
493 helper_->Read(dest, 256);
494 // Get readable region from [256, 1024)
495 iovec iovs[2];
496 int iov_count = buffer_->GetReadableRegions(iovs, 2);
497 EXPECT_EQ(1, iov_count);
vasilvvc48c8712019-03-11 13:38:16 -0700498 EXPECT_EQ(std::string(kBlockSizeBytes - 256, 'a'),
499 std::string(reinterpret_cast<const char*>(iovs[0].iov_base),
500 iovs[0].iov_len));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500501}
502
503TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionsWithinOneBlock) {
504 // Write into [0, 1024) and then read out [0, 256)
vasilvvc48c8712019-03-11 13:38:16 -0700505 std::string source(1024, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500506 size_t written;
507 buffer_->OnStreamData(0, source, &written, &error_details_);
508 char dest[256];
509 helper_->Read(dest, 256);
510 // Get readable region from [256, 1024)
511 iovec iovs[2];
512 int iov_count = buffer_->GetReadableRegions(iovs, 2);
513 EXPECT_EQ(1, iov_count);
vasilvvc48c8712019-03-11 13:38:16 -0700514 EXPECT_EQ(std::string(1024 - 256, 'a'),
515 std::string(reinterpret_cast<const char*>(iovs[0].iov_base),
516 iovs[0].iov_len));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500517}
518
519TEST_F(QuicStreamSequencerBufferTest,
520 GetReadableRegionsAcrossBlockWithLongIOV) {
521 // Write into [0, 2 * kBlockSizeBytes + 1024) and then read out [0, 1024)
vasilvvc48c8712019-03-11 13:38:16 -0700522 std::string source(2 * kBlockSizeBytes + 1024, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500523 size_t written;
524 buffer_->OnStreamData(0, source, &written, &error_details_);
525 char dest[1024];
526 helper_->Read(dest, 1024);
527
528 iovec iovs[4];
529 int iov_count = buffer_->GetReadableRegions(iovs, 4);
530 EXPECT_EQ(3, iov_count);
531 EXPECT_EQ(kBlockSizeBytes - 1024, iovs[0].iov_len);
532 EXPECT_EQ(kBlockSizeBytes, iovs[1].iov_len);
533 EXPECT_EQ(1024u, iovs[2].iov_len);
534}
535
536TEST_F(QuicStreamSequencerBufferTest,
537 GetReadableRegionsWithMultipleIOVsAcrossEnd) {
538 // Write into [0, 2 * kBlockSizeBytes + 1024) and then read out [0, 1024)
539 // and then append 1024 + 512 bytes.
vasilvvc48c8712019-03-11 13:38:16 -0700540 std::string source(2.5 * kBlockSizeBytes - 1024, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500541 size_t written;
542 buffer_->OnStreamData(0, source, &written, &error_details_);
543 char dest[1024];
544 helper_->Read(dest, 1024);
545 // Write across the end.
vasilvvc48c8712019-03-11 13:38:16 -0700546 source = std::string(1024 + 512, 'b');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500547 buffer_->OnStreamData(2.5 * kBlockSizeBytes - 1024, source, &written,
548 &error_details_);
549 // Use short iovec's.
550 iovec iovs[2];
551 int iov_count = buffer_->GetReadableRegions(iovs, 2);
552 EXPECT_EQ(2, iov_count);
553 EXPECT_EQ(kBlockSizeBytes - 1024, iovs[0].iov_len);
554 EXPECT_EQ(kBlockSizeBytes, iovs[1].iov_len);
555 // Use long iovec's and wrap the end of buffer.
556 iovec iovs1[5];
557 EXPECT_EQ(4, buffer_->GetReadableRegions(iovs1, 5));
558 EXPECT_EQ(0.5 * kBlockSizeBytes, iovs1[2].iov_len);
559 EXPECT_EQ(512u, iovs1[3].iov_len);
vasilvvc48c8712019-03-11 13:38:16 -0700560 EXPECT_EQ(std::string(512, 'b'),
561 std::string(reinterpret_cast<const char*>(iovs1[3].iov_base),
562 iovs1[3].iov_len));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500563}
564
565TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionEmpty) {
566 iovec iov;
567 EXPECT_FALSE(buffer_->GetReadableRegion(&iov));
568 EXPECT_EQ(nullptr, iov.iov_base);
569 EXPECT_EQ(0u, iov.iov_len);
570}
571
572TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionBeforeGap) {
573 // Write into [1, 1024).
vasilvvc48c8712019-03-11 13:38:16 -0700574 std::string source(1023, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500575 size_t written;
576 buffer_->OnStreamData(1, source, &written, &error_details_);
577 // GetReadableRegion should return false because range [0,1) hasn't been
578 // filled yet.
579 iovec iov;
580 EXPECT_FALSE(buffer_->GetReadableRegion(&iov));
581}
582
583TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionTillEndOfBlock) {
584 // Write into [0, kBlockSizeBytes + 1) and then read out [0, 256)
vasilvvc48c8712019-03-11 13:38:16 -0700585 std::string source(kBlockSizeBytes + 1, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500586 size_t written;
587 buffer_->OnStreamData(0, source, &written, &error_details_);
588 char dest[256];
589 helper_->Read(dest, 256);
590 // Get readable region from [256, 1024)
591 iovec iov;
592 EXPECT_TRUE(buffer_->GetReadableRegion(&iov));
593 EXPECT_EQ(
vasilvvc48c8712019-03-11 13:38:16 -0700594 std::string(kBlockSizeBytes - 256, 'a'),
595 std::string(reinterpret_cast<const char*>(iov.iov_base), iov.iov_len));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500596}
597
598TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionTillGap) {
599 // Write into [0, kBlockSizeBytes - 1) and then read out [0, 256)
vasilvvc48c8712019-03-11 13:38:16 -0700600 std::string source(kBlockSizeBytes - 1, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500601 size_t written;
602 buffer_->OnStreamData(0, source, &written, &error_details_);
603 char dest[256];
604 helper_->Read(dest, 256);
605 // Get readable region from [256, 1023)
606 iovec iov;
607 EXPECT_TRUE(buffer_->GetReadableRegion(&iov));
608 EXPECT_EQ(
vasilvvc48c8712019-03-11 13:38:16 -0700609 std::string(kBlockSizeBytes - 1 - 256, 'a'),
610 std::string(reinterpret_cast<const char*>(iov.iov_base), iov.iov_len));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500611}
612
613TEST_F(QuicStreamSequencerBufferTest, PrefetchEmptyBuffer) {
614 iovec iov;
615 EXPECT_FALSE(buffer_->PrefetchNextRegion(&iov));
616}
617
618TEST_F(QuicStreamSequencerBufferTest, PrefetchInitialBuffer) {
vasilvvc48c8712019-03-11 13:38:16 -0700619 std::string source(kBlockSizeBytes, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500620 size_t written;
621 buffer_->OnStreamData(0, source, &written, &error_details_);
622 iovec iov;
623 EXPECT_TRUE(buffer_->PrefetchNextRegion(&iov));
vasilvvc48c8712019-03-11 13:38:16 -0700624 EXPECT_EQ(source, std::string(reinterpret_cast<const char*>(iov.iov_base),
625 iov.iov_len));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500626}
627
628TEST_F(QuicStreamSequencerBufferTest, PrefetchBufferWithOffset) {
vasilvvc48c8712019-03-11 13:38:16 -0700629 std::string source(1024, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500630 size_t written;
631 buffer_->OnStreamData(0, source, &written, &error_details_);
632 iovec iov;
633 EXPECT_TRUE(buffer_->PrefetchNextRegion(&iov));
vasilvvc48c8712019-03-11 13:38:16 -0700634 EXPECT_EQ(source, std::string(reinterpret_cast<const char*>(iov.iov_base),
635 iov.iov_len));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500636 // The second frame goes into the same bucket.
vasilvvc48c8712019-03-11 13:38:16 -0700637 std::string source2(800, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500638 buffer_->OnStreamData(1024, source2, &written, &error_details_);
639 EXPECT_TRUE(buffer_->PrefetchNextRegion(&iov));
vasilvvc48c8712019-03-11 13:38:16 -0700640 EXPECT_EQ(source2, std::string(reinterpret_cast<const char*>(iov.iov_base),
641 iov.iov_len));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500642}
643
644TEST_F(QuicStreamSequencerBufferTest, PrefetchBufferWithMultipleBucket) {
645 const size_t data_size = 1024;
vasilvvc48c8712019-03-11 13:38:16 -0700646 std::string source(data_size, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500647 size_t written;
648 buffer_->OnStreamData(0, source, &written, &error_details_);
649 iovec iov;
650 EXPECT_TRUE(buffer_->PrefetchNextRegion(&iov));
vasilvvc48c8712019-03-11 13:38:16 -0700651 EXPECT_EQ(source, std::string(reinterpret_cast<const char*>(iov.iov_base),
652 iov.iov_len));
653 std::string source2(kBlockSizeBytes, 'b');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500654 buffer_->OnStreamData(data_size, source2, &written, &error_details_);
655 EXPECT_TRUE(buffer_->PrefetchNextRegion(&iov));
656 EXPECT_EQ(
vasilvvc48c8712019-03-11 13:38:16 -0700657 std::string(kBlockSizeBytes - data_size, 'b'),
658 std::string(reinterpret_cast<const char*>(iov.iov_base), iov.iov_len));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500659 EXPECT_TRUE(buffer_->PrefetchNextRegion(&iov));
660 EXPECT_EQ(
vasilvvc48c8712019-03-11 13:38:16 -0700661 std::string(data_size, 'b'),
662 std::string(reinterpret_cast<const char*>(iov.iov_base), iov.iov_len));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500663}
664
665TEST_F(QuicStreamSequencerBufferTest, PrefetchBufferAfterBlockRetired) {
vasilvvc48c8712019-03-11 13:38:16 -0700666 std::string source(kBlockSizeBytes, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500667 size_t written;
668 buffer_->OnStreamData(0, source, &written, &error_details_);
669 iovec iov;
670 EXPECT_TRUE(buffer_->PrefetchNextRegion(&iov));
vasilvvc48c8712019-03-11 13:38:16 -0700671 EXPECT_EQ(source, std::string(reinterpret_cast<const char*>(iov.iov_base),
672 iov.iov_len));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500673 // Read the whole block so it's retired.
674 char dest[kBlockSizeBytes];
675 helper_->Read(dest, kBlockSizeBytes);
676
vasilvvc48c8712019-03-11 13:38:16 -0700677 std::string source2(300, 'b');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500678 buffer_->OnStreamData(kBlockSizeBytes, source2, &written, &error_details_);
679
680 EXPECT_TRUE(buffer_->PrefetchNextRegion(&iov));
vasilvvc48c8712019-03-11 13:38:16 -0700681 EXPECT_EQ(source2, std::string(reinterpret_cast<const char*>(iov.iov_base),
682 iov.iov_len));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500683}
684
685TEST_F(QuicStreamSequencerBufferTest, PrefetchContinously) {
vasilvvc48c8712019-03-11 13:38:16 -0700686 std::string source(kBlockSizeBytes, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500687 size_t written;
688 buffer_->OnStreamData(0, source, &written, &error_details_);
689 iovec iov;
690 EXPECT_TRUE(buffer_->PrefetchNextRegion(&iov));
vasilvvc48c8712019-03-11 13:38:16 -0700691 EXPECT_EQ(source, std::string(reinterpret_cast<const char*>(iov.iov_base),
692 iov.iov_len));
693 std::string source2(kBlockSizeBytes, 'b');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500694 buffer_->OnStreamData(kBlockSizeBytes, source2, &written, &error_details_);
695 EXPECT_TRUE(buffer_->PrefetchNextRegion(&iov));
vasilvvc48c8712019-03-11 13:38:16 -0700696 EXPECT_EQ(source2, std::string(reinterpret_cast<const char*>(iov.iov_base),
697 iov.iov_len));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500698}
699
700TEST_F(QuicStreamSequencerBufferTest, ConsumeMoreThanPrefetch) {
vasilvvc48c8712019-03-11 13:38:16 -0700701 std::string source(100, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500702 size_t written;
703 buffer_->OnStreamData(0, source, &written, &error_details_);
704 char dest[30];
705 helper_->Read(dest, 30);
706 iovec iov;
707 EXPECT_TRUE(buffer_->PrefetchNextRegion(&iov));
708 EXPECT_EQ(
vasilvvc48c8712019-03-11 13:38:16 -0700709 std::string(70, 'a'),
710 std::string(reinterpret_cast<const char*>(iov.iov_base), iov.iov_len));
711 std::string source2(100, 'b');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500712 buffer_->OnStreamData(100, source2, &written, &error_details_);
713 buffer_->MarkConsumed(100);
714 EXPECT_TRUE(buffer_->PrefetchNextRegion(&iov));
715 EXPECT_EQ(
vasilvvc48c8712019-03-11 13:38:16 -0700716 std::string(70, 'b'),
717 std::string(reinterpret_cast<const char*>(iov.iov_base), iov.iov_len));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500718}
719
720TEST_F(QuicStreamSequencerBufferTest, PrefetchMoreThanBufferHas) {
vasilvvc48c8712019-03-11 13:38:16 -0700721 std::string source(100, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500722 size_t written;
723 buffer_->OnStreamData(0, source, &written, &error_details_);
724 iovec iov;
725 EXPECT_TRUE(buffer_->PrefetchNextRegion(&iov));
726 EXPECT_EQ(
vasilvvc48c8712019-03-11 13:38:16 -0700727 std::string(100, 'a'),
728 std::string(reinterpret_cast<const char*>(iov.iov_base), iov.iov_len));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500729 EXPECT_FALSE(buffer_->PrefetchNextRegion(&iov));
730}
731
732TEST_F(QuicStreamSequencerBufferTest, MarkConsumedInOneBlock) {
733 // Write into [0, 1024) and then read out [0, 256)
vasilvvc48c8712019-03-11 13:38:16 -0700734 std::string source(1024, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500735 size_t written;
736 buffer_->OnStreamData(0, source, &written, &error_details_);
737 char dest[256];
738 helper_->Read(dest, 256);
739
740 EXPECT_TRUE(buffer_->MarkConsumed(512));
741 EXPECT_EQ(256u + 512u, buffer_->BytesConsumed());
742 EXPECT_EQ(256u, helper_->ReadableBytes());
743 buffer_->MarkConsumed(256);
744 EXPECT_TRUE(buffer_->Empty());
745 EXPECT_TRUE(helper_->CheckBufferInvariants());
746}
747
748TEST_F(QuicStreamSequencerBufferTest, MarkConsumedNotEnoughBytes) {
749 // Write into [0, 1024) and then read out [0, 256)
vasilvvc48c8712019-03-11 13:38:16 -0700750 std::string source(1024, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500751 size_t written;
752 buffer_->OnStreamData(0, source, &written, &error_details_);
753 char dest[256];
754 helper_->Read(dest, 256);
755
756 // Consume 1st 512 bytes
757 EXPECT_TRUE(buffer_->MarkConsumed(512));
758 EXPECT_EQ(256u + 512u, buffer_->BytesConsumed());
759 EXPECT_EQ(256u, helper_->ReadableBytes());
760 // Try to consume one bytes more than available. Should return false.
761 EXPECT_FALSE(buffer_->MarkConsumed(257));
762 EXPECT_EQ(256u + 512u, buffer_->BytesConsumed());
763 iovec iov;
764 EXPECT_TRUE(buffer_->GetReadableRegion(&iov));
765 EXPECT_TRUE(helper_->CheckBufferInvariants());
766}
767
768TEST_F(QuicStreamSequencerBufferTest, MarkConsumedAcrossBlock) {
769 // Write into [0, 2 * kBlockSizeBytes + 1024) and then read out [0, 1024)
vasilvvc48c8712019-03-11 13:38:16 -0700770 std::string source(2 * kBlockSizeBytes + 1024, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500771 size_t written;
772 buffer_->OnStreamData(0, source, &written, &error_details_);
773 char dest[1024];
774 helper_->Read(dest, 1024);
775
776 buffer_->MarkConsumed(2 * kBlockSizeBytes);
777 EXPECT_EQ(source.size(), buffer_->BytesConsumed());
778 EXPECT_TRUE(buffer_->Empty());
779 EXPECT_TRUE(helper_->CheckBufferInvariants());
780}
781
782TEST_F(QuicStreamSequencerBufferTest, MarkConsumedAcrossEnd) {
783 // Write into [0, 2.5 * kBlockSizeBytes - 1024) and then read out [0, 1024)
784 // and then append 1024 + 512 bytes.
vasilvvc48c8712019-03-11 13:38:16 -0700785 std::string source(2.5 * kBlockSizeBytes - 1024, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500786 size_t written;
787 buffer_->OnStreamData(0, source, &written, &error_details_);
788 char dest[1024];
789 helper_->Read(dest, 1024);
vasilvvc48c8712019-03-11 13:38:16 -0700790 source = std::string(1024 + 512, 'b');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500791 buffer_->OnStreamData(2.5 * kBlockSizeBytes - 1024, source, &written,
792 &error_details_);
793 EXPECT_EQ(1024u, buffer_->BytesConsumed());
794
795 // Consume to the end of 2nd block.
796 buffer_->MarkConsumed(2 * kBlockSizeBytes - 1024);
797 EXPECT_EQ(2 * kBlockSizeBytes, buffer_->BytesConsumed());
798 // Consume across the physical end of buffer
799 buffer_->MarkConsumed(0.5 * kBlockSizeBytes + 500);
800 EXPECT_EQ(max_capacity_bytes_ + 500, buffer_->BytesConsumed());
801 EXPECT_EQ(12u, helper_->ReadableBytes());
802 // Consume to the logical end of buffer
803 buffer_->MarkConsumed(12);
804 EXPECT_EQ(max_capacity_bytes_ + 512, buffer_->BytesConsumed());
805 EXPECT_TRUE(buffer_->Empty());
806 EXPECT_TRUE(helper_->CheckBufferInvariants());
807}
808
809TEST_F(QuicStreamSequencerBufferTest, FlushBufferedFrames) {
810 // Write into [0, 2.5 * kBlockSizeBytes - 1024) and then read out [0, 1024).
vasilvvc48c8712019-03-11 13:38:16 -0700811 std::string source(max_capacity_bytes_ - 1024, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500812 size_t written;
813 buffer_->OnStreamData(0, source, &written, &error_details_);
814 char dest[1024];
815 helper_->Read(dest, 1024);
816 EXPECT_EQ(1024u, buffer_->BytesConsumed());
817 // Write [1024, 512) to the physical beginning.
vasilvvc48c8712019-03-11 13:38:16 -0700818 source = std::string(512, 'b');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500819 buffer_->OnStreamData(max_capacity_bytes_, source, &written, &error_details_);
820 EXPECT_EQ(512u, written);
821 EXPECT_EQ(max_capacity_bytes_ - 1024 + 512, buffer_->FlushBufferedFrames());
822 EXPECT_EQ(max_capacity_bytes_ + 512, buffer_->BytesConsumed());
823 EXPECT_TRUE(buffer_->Empty());
824 EXPECT_TRUE(helper_->CheckBufferInvariants());
825 // Clear buffer at this point should still preserve BytesConsumed().
826 buffer_->Clear();
827 EXPECT_EQ(max_capacity_bytes_ + 512, buffer_->BytesConsumed());
828 EXPECT_TRUE(helper_->CheckBufferInvariants());
829}
830
831TEST_F(QuicStreamSequencerBufferTest, TooManyGaps) {
832 // Make sure max capacity is large enough that it is possible to have more
833 // than |kMaxNumGapsAllowed| number of gaps.
834 max_capacity_bytes_ = 3 * kBlockSizeBytes;
835 // Feed buffer with 1-byte discontiguous frames. e.g. [1,2), [3,4), [5,6)...
836 for (QuicStreamOffset begin = 1; begin <= max_capacity_bytes_; begin += 2) {
837 size_t written;
838 QuicErrorCode rs =
839 buffer_->OnStreamData(begin, "a", &written, &error_details_);
840
841 QuicStreamOffset last_straw = 2 * kMaxNumGapsAllowed - 1;
842 if (begin == last_straw) {
843 EXPECT_EQ(QUIC_TOO_MANY_STREAM_DATA_INTERVALS, rs);
844 EXPECT_EQ("Too many data intervals received for this stream.",
845 error_details_);
846 break;
847 }
848 }
849}
850
851class QuicStreamSequencerBufferRandomIOTest
852 : public QuicStreamSequencerBufferTest {
853 public:
854 typedef std::pair<QuicStreamOffset, size_t> OffsetSizePair;
855
856 void SetUp() override {
857 // Test against a larger capacity then above tests. Also make sure the last
858 // block is partially available to use.
859 max_capacity_bytes_ = 6.25 * kBlockSizeBytes;
860 // Stream to be buffered should be larger than the capacity to test wrap
861 // around.
862 bytes_to_buffer_ = 2 * max_capacity_bytes_;
863 Initialize();
864
865 uint64_t seed = QuicRandom::GetInstance()->RandUint64();
866 QUIC_LOG(INFO) << "**** The current seed is " << seed << " ****";
867 rng_.set_seed(seed);
868 }
869
870 // Create an out-of-order source stream with given size to populate
871 // shuffled_buf_.
872 void CreateSourceAndShuffle(size_t max_chunk_size_bytes) {
873 max_chunk_size_bytes_ = max_chunk_size_bytes;
874 std::unique_ptr<OffsetSizePair[]> chopped_stream(
875 new OffsetSizePair[bytes_to_buffer_]);
876
877 // Split stream into small chunks with random length. chopped_stream will be
878 // populated with segmented stream chunks.
879 size_t start_chopping_offset = 0;
880 size_t iterations = 0;
881 while (start_chopping_offset < bytes_to_buffer_) {
882 size_t max_chunk = std::min<size_t>(
883 max_chunk_size_bytes_, bytes_to_buffer_ - start_chopping_offset);
884 size_t chunk_size = rng_.RandUint64() % max_chunk + 1;
885 chopped_stream[iterations] =
886 OffsetSizePair(start_chopping_offset, chunk_size);
887 start_chopping_offset += chunk_size;
888 ++iterations;
889 }
890 DCHECK(start_chopping_offset == bytes_to_buffer_);
891 size_t chunk_num = iterations;
892
893 // Randomly change the sequence of in-ordered OffsetSizePairs to make a
894 // out-of-order array of OffsetSizePairs.
895 for (int i = chunk_num - 1; i >= 0; --i) {
896 size_t random_idx = rng_.RandUint64() % (i + 1);
897 QUIC_DVLOG(1) << "chunk offset " << chopped_stream[random_idx].first
898 << " size " << chopped_stream[random_idx].second;
899 shuffled_buf_.push_front(chopped_stream[random_idx]);
900 chopped_stream[random_idx] = chopped_stream[i];
901 }
902 }
903
904 // Write the currently first chunk of data in the out-of-order stream into
905 // QuicStreamSequencerBuffer. If current chuck cannot be written into buffer
906 // because it goes beyond current capacity, move it to the end of
907 // shuffled_buf_ and write it later.
908 void WriteNextChunkToBuffer() {
909 OffsetSizePair& chunk = shuffled_buf_.front();
910 QuicStreamOffset offset = chunk.first;
911 const size_t num_to_write = chunk.second;
912 std::unique_ptr<char[]> write_buf{new char[max_chunk_size_bytes_]};
913 for (size_t i = 0; i < num_to_write; ++i) {
914 write_buf[i] = (offset + i) % 256;
915 }
916 QuicStringPiece string_piece_w(write_buf.get(), num_to_write);
917 size_t written;
918 auto result = buffer_->OnStreamData(offset, string_piece_w, &written,
919 &error_details_);
920 if (result == QUIC_NO_ERROR) {
921 shuffled_buf_.pop_front();
922 total_bytes_written_ += num_to_write;
923 } else {
924 // This chunk offset exceeds window size.
925 shuffled_buf_.push_back(chunk);
926 shuffled_buf_.pop_front();
927 }
928 QUIC_DVLOG(1) << " write at offset: " << offset
929 << " len to write: " << num_to_write
930 << " write result: " << result
931 << " left over: " << shuffled_buf_.size();
932 }
933
934 protected:
935 std::list<OffsetSizePair> shuffled_buf_;
936 size_t max_chunk_size_bytes_;
937 QuicStreamOffset bytes_to_buffer_;
938 size_t total_bytes_written_ = 0;
939 size_t total_bytes_read_ = 0;
940 SimpleRandom rng_;
941};
942
943TEST_F(QuicStreamSequencerBufferRandomIOTest, RandomWriteAndReadv) {
944 // Set kMaxReadSize larger than kBlockSizeBytes to test both small and large
945 // read.
946 const size_t kMaxReadSize = kBlockSizeBytes * 2;
947 // kNumReads is larger than 1 to test how multiple read destinations work.
948 const size_t kNumReads = 2;
949 // Since write and read operation have equal possibility to be called. Bytes
950 // to be written into and read out of should roughly the same.
951 const size_t kMaxWriteSize = kNumReads * kMaxReadSize;
952 size_t iterations = 0;
953
954 CreateSourceAndShuffle(kMaxWriteSize);
955
956 while ((!shuffled_buf_.empty() || total_bytes_read_ < bytes_to_buffer_) &&
957 iterations <= 2 * bytes_to_buffer_) {
958 uint8_t next_action =
959 shuffled_buf_.empty() ? uint8_t{1} : rng_.RandUint64() % 2;
960 QUIC_DVLOG(1) << "iteration: " << iterations;
961 switch (next_action) {
962 case 0: { // write
963 WriteNextChunkToBuffer();
964 ASSERT_TRUE(helper_->CheckBufferInvariants());
965 break;
966 }
967 case 1: { // readv
968 std::unique_ptr<char[][kMaxReadSize]> read_buf{
969 new char[kNumReads][kMaxReadSize]};
970 iovec dest_iov[kNumReads];
971 size_t num_to_read = 0;
972 for (size_t i = 0; i < kNumReads; ++i) {
973 dest_iov[i].iov_base =
974 reinterpret_cast<void*>(const_cast<char*>(read_buf[i]));
975 dest_iov[i].iov_len = rng_.RandUint64() % kMaxReadSize;
976 num_to_read += dest_iov[i].iov_len;
977 }
978 size_t actually_read;
979 EXPECT_EQ(QUIC_NO_ERROR,
980 buffer_->Readv(dest_iov, kNumReads, &actually_read,
981 &error_details_));
982 ASSERT_LE(actually_read, num_to_read);
983 QUIC_DVLOG(1) << " read from offset: " << total_bytes_read_
984 << " size: " << num_to_read
985 << " actual read: " << actually_read;
986 for (size_t i = 0; i < actually_read; ++i) {
987 char ch = (i + total_bytes_read_) % 256;
988 ASSERT_EQ(ch, GetCharFromIOVecs(i, dest_iov, kNumReads))
989 << " at iteration " << iterations;
990 }
991 total_bytes_read_ += actually_read;
992 ASSERT_EQ(total_bytes_read_, buffer_->BytesConsumed());
993 ASSERT_TRUE(helper_->CheckBufferInvariants());
994 break;
995 }
996 }
997 ++iterations;
998 ASSERT_LE(total_bytes_read_, total_bytes_written_);
999 }
1000 EXPECT_LT(iterations, bytes_to_buffer_) << "runaway test";
1001 EXPECT_LE(bytes_to_buffer_, total_bytes_read_)
1002 << "iterations: " << iterations;
1003 EXPECT_LE(bytes_to_buffer_, total_bytes_written_);
1004}
1005
1006TEST_F(QuicStreamSequencerBufferRandomIOTest, RandomWriteAndConsumeInPlace) {
1007 // The value 4 is chosen such that the max write size is no larger than the
1008 // maximum buffer capacity.
1009 const size_t kMaxNumReads = 4;
1010 // Adjust write amount be roughly equal to that GetReadableRegions() can get.
1011 const size_t kMaxWriteSize = kMaxNumReads * kBlockSizeBytes;
1012 ASSERT_LE(kMaxWriteSize, max_capacity_bytes_);
1013 size_t iterations = 0;
1014
1015 CreateSourceAndShuffle(kMaxWriteSize);
1016
1017 while ((!shuffled_buf_.empty() || total_bytes_read_ < bytes_to_buffer_) &&
1018 iterations <= 2 * bytes_to_buffer_) {
1019 uint8_t next_action =
1020 shuffled_buf_.empty() ? uint8_t{1} : rng_.RandUint64() % 2;
1021 QUIC_DVLOG(1) << "iteration: " << iterations;
1022 switch (next_action) {
1023 case 0: { // write
1024 WriteNextChunkToBuffer();
1025 ASSERT_TRUE(helper_->CheckBufferInvariants());
1026 break;
1027 }
1028 case 1: { // GetReadableRegions and then MarkConsumed
1029 size_t num_read = rng_.RandUint64() % kMaxNumReads + 1;
1030 iovec dest_iov[kMaxNumReads];
1031 ASSERT_TRUE(helper_->CheckBufferInvariants());
1032 size_t actually_num_read =
1033 buffer_->GetReadableRegions(dest_iov, num_read);
1034 ASSERT_LE(actually_num_read, num_read);
1035 size_t avail_bytes = 0;
1036 for (size_t i = 0; i < actually_num_read; ++i) {
1037 avail_bytes += dest_iov[i].iov_len;
1038 }
1039 // process random number of bytes (check the value of each byte).
1040 size_t bytes_to_process = rng_.RandUint64() % (avail_bytes + 1);
1041 size_t bytes_processed = 0;
1042 for (size_t i = 0; i < actually_num_read; ++i) {
1043 size_t bytes_in_block = std::min<size_t>(
1044 bytes_to_process - bytes_processed, dest_iov[i].iov_len);
1045 if (bytes_in_block == 0) {
1046 break;
1047 }
1048 for (size_t j = 0; j < bytes_in_block; ++j) {
1049 ASSERT_LE(bytes_processed, bytes_to_process);
1050 char char_expected =
1051 (buffer_->BytesConsumed() + bytes_processed) % 256;
1052 ASSERT_EQ(char_expected,
1053 reinterpret_cast<const char*>(dest_iov[i].iov_base)[j])
1054 << " at iteration " << iterations;
1055 ++bytes_processed;
1056 }
1057 }
1058
1059 buffer_->MarkConsumed(bytes_processed);
1060
1061 QUIC_DVLOG(1) << "iteration " << iterations << ": try to get "
1062 << num_read << " readable regions, actually get "
1063 << actually_num_read
1064 << " from offset: " << total_bytes_read_
1065 << "\nprocesse bytes: " << bytes_processed;
1066 total_bytes_read_ += bytes_processed;
1067 ASSERT_EQ(total_bytes_read_, buffer_->BytesConsumed());
1068 ASSERT_TRUE(helper_->CheckBufferInvariants());
1069 break;
1070 }
1071 }
1072 ++iterations;
1073 ASSERT_LE(total_bytes_read_, total_bytes_written_);
1074 }
1075 EXPECT_LT(iterations, bytes_to_buffer_) << "runaway test";
1076 EXPECT_LE(bytes_to_buffer_, total_bytes_read_)
1077 << "iterations: " << iterations;
1078 EXPECT_LE(bytes_to_buffer_, total_bytes_written_);
1079}
1080
1081} // anonymous namespace
1082
1083} // namespace test
1084
1085} // namespace quic